summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordalecurtis <dalecurtis@chromium.org>2015-11-10 10:25:58 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-10 18:26:52 +0000
commitdd1b4ad61b745e8d75195cd0b4938086d3b6062d (patch)
tree2c9c7b807f5e10ced053650cdd95bb66a08b60b9
parent2641bbb33465cf9d2442886162e4911cd91c011c (diff)
downloadchromium_src-dd1b4ad61b745e8d75195cd0b4938086d3b6062d.zip
chromium_src-dd1b4ad61b745e8d75195cd0b4938086d3b6062d.tar.gz
chromium_src-dd1b4ad61b745e8d75195cd0b4938086d3b6062d.tar.bz2
Revert of Stall audio thread after device changes to avoid 3rd party deadlock. (patchset #2 id:20001 of https://codereview.chromium.org/1428413003/ )
Reason for revert: Did not reduce the number of crash reports, so reverting. :( Original issue's description: > Stall audio thread after device changes to avoid 3rd party deadlock. > > Speculative change to see if stalling callbacks into the Windows > audio subsystem after a device change is detected will reduce the > frequency of deadlock in 3rd party WDM drivers. > > This change reroutes both input and output device changes through > the AudioManagerWin, where a simple sleep on the audio thread > stalls any outstanding activity. > > The stall should be fine as the audio thread is used primarily as > an asychronous control channel. I've chosen a stall over a post > delayed task to ensure that any outstanding tasks are prevented. > > If this CL is successful we can experiment with loosening to a > PostDelayedTask will still bear fruit. > > BUG=422522 > TEST=device change works as normal. > > Committed: https://crrev.com/6ffe80ed4dea8b85925ba6dfa2a0cb8f472fb951 > Cr-Commit-Position: refs/heads/master@{#358707} TBR=watk@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=422522 Review URL: https://codereview.chromium.org/1430423002 Cr-Commit-Position: refs/heads/master@{#358854}
-rw-r--r--media/audio/win/audio_device_listener_win.cc10
-rw-r--r--media/audio/win/audio_device_listener_win.h8
-rw-r--r--media/audio/win/audio_device_listener_win_unittest.cc24
-rw-r--r--media/audio/win/audio_manager_win.cc21
-rw-r--r--media/audio/win/audio_manager_win.h9
5 files changed, 20 insertions, 52 deletions
diff --git a/media/audio/win/audio_device_listener_win.cc b/media/audio/win/audio_device_listener_win.cc
index 056ab7c..505007b 100644
--- a/media/audio/win/audio_device_listener_win.cc
+++ b/media/audio/win/audio_device_listener_win.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/system_monitor/system_monitor.h"
#include "base/time/default_tick_clock.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/windows_version.h"
@@ -30,7 +31,7 @@ static std::string RoleToString(ERole role) {
}
}
-AudioDeviceListenerWin::AudioDeviceListenerWin(const ListenerCB& listener_cb)
+AudioDeviceListenerWin::AudioDeviceListenerWin(const base::Closure& listener_cb)
: listener_cb_(listener_cb), tick_clock_(new base::DefaultTickClock()) {
CHECK(CoreAudioUtil::IsSupported());
@@ -97,7 +98,10 @@ STDMETHODIMP AudioDeviceListenerWin::OnDeviceRemoved(LPCWSTR device_id) {
STDMETHODIMP AudioDeviceListenerWin::OnDeviceStateChanged(LPCWSTR device_id,
DWORD new_state) {
- listener_cb_.Run(kInputDeviceChange);
+ base::SystemMonitor* monitor = base::SystemMonitor::Get();
+ if (monitor)
+ monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
+
return S_OK;
}
@@ -127,7 +131,7 @@ STDMETHODIMP AudioDeviceListenerWin::OnDefaultDeviceChanged(
now - last_device_change_time_ >
base::TimeDelta::FromMilliseconds(kDeviceChangeLimitMs)) {
last_device_change_time_ = now;
- listener_cb_.Run(kOutputDeviceChange);
+ listener_cb_.Run();
did_run_listener_cb = true;
}
diff --git a/media/audio/win/audio_device_listener_win.h b/media/audio/win/audio_device_listener_win.h
index 8875269..053afa6 100644
--- a/media/audio/win/audio_device_listener_win.h
+++ b/media/audio/win/audio_device_listener_win.h
@@ -31,14 +31,10 @@ namespace media {
// TODO(dalecurtis, henrika): Support input device changes.
class MEDIA_EXPORT AudioDeviceListenerWin : public IMMNotificationClient {
public:
- // Callback returns whether input or output devices have changed.
- enum DeviceNotificationType { kInputDeviceChange, kOutputDeviceChange };
- using ListenerCB = base::Callback<void(DeviceNotificationType)>;
-
// The listener callback will be called from a system level multimedia thread,
// thus the callee must be thread safe. |listener| is a permanent callback
// and must outlive AudioDeviceListenerWin.
- explicit AudioDeviceListenerWin(const ListenerCB& listener_cb);
+ explicit AudioDeviceListenerWin(const base::Closure& listener_cb);
virtual ~AudioDeviceListenerWin();
private:
@@ -60,7 +56,7 @@ class MEDIA_EXPORT AudioDeviceListenerWin : public IMMNotificationClient {
ERole role,
LPCWSTR new_default_device_id) override;
- ListenerCB listener_cb_;
+ base::Closure listener_cb_;
ScopedComPtr<IMMDeviceEnumerator> device_enumerator_;
// Used to rate limit device change events.
diff --git a/media/audio/win/audio_device_listener_win_unittest.cc b/media/audio/win/audio_device_listener_win_unittest.cc
index 855c590..4b78d93 100644
--- a/media/audio/win/audio_device_listener_win_unittest.cc
+++ b/media/audio/win/audio_device_listener_win_unittest.cc
@@ -60,8 +60,8 @@ class AudioDeviceListenerWinTest : public testing::Test {
base::ASCIIToUTF16(new_device_id).c_str()) == S_OK;
}
- MOCK_METHOD1(OnDeviceChange,
- void(AudioDeviceListenerWin::DeviceNotificationType));
+
+ MOCK_METHOD0(OnDeviceChange, void());
private:
ScopedCOMInitializer com_init_;
@@ -75,16 +75,12 @@ class AudioDeviceListenerWinTest : public testing::Test {
TEST_F(AudioDeviceListenerWinTest, OutputDeviceChange) {
ABORT_AUDIO_TEST_IF_NOT(CoreAudioUtil::IsSupported());
- EXPECT_CALL(*this,
- OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange))
- .Times(1);
+ EXPECT_CALL(*this, OnDeviceChange()).Times(1);
ASSERT_TRUE(SimulateDefaultOutputDeviceChange(kFirstTestDevice));
testing::Mock::VerifyAndClear(this);
AdvanceLastDeviceChangeTime();
- EXPECT_CALL(*this,
- OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange))
- .Times(1);
+ EXPECT_CALL(*this, OnDeviceChange()).Times(1);
ASSERT_TRUE(SimulateDefaultOutputDeviceChange(kSecondTestDevice));
// The second device event should be ignored since it occurs too soon.
@@ -96,23 +92,17 @@ TEST_F(AudioDeviceListenerWinTest, OutputDeviceChange) {
TEST_F(AudioDeviceListenerWinTest, NullOutputDeviceChange) {
ABORT_AUDIO_TEST_IF_NOT(CoreAudioUtil::IsSupported());
- EXPECT_CALL(*this,
- OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange))
- .Times(1);
+ EXPECT_CALL(*this, OnDeviceChange()).Times(1);
ASSERT_TRUE(SimulateNullDefaultOutputDeviceChange());
testing::Mock::VerifyAndClear(this);
AdvanceLastDeviceChangeTime();
- EXPECT_CALL(*this,
- OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange))
- .Times(1);
+ EXPECT_CALL(*this, OnDeviceChange()).Times(1);
ASSERT_TRUE(SimulateDefaultOutputDeviceChange(kFirstTestDevice));
testing::Mock::VerifyAndClear(this);
AdvanceLastDeviceChangeTime();
- EXPECT_CALL(*this,
- OnDeviceChange(AudioDeviceListenerWin::kOutputDeviceChange))
- .Times(1);
+ EXPECT_CALL(*this, OnDeviceChange()).Times(1);
ASSERT_TRUE(SimulateNullDefaultOutputDeviceChange());
}
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index 0b97afb..70e6c1b 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -21,9 +21,9 @@
#include "base/process/launch.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/system_monitor/system_monitor.h"
#include "base/win/windows_version.h"
#include "media/audio/audio_parameters.h"
+#include "media/audio/win/audio_device_listener_win.h"
#include "media/audio/win/audio_low_latency_input_win.h"
#include "media/audio/win/audio_low_latency_output_win.h"
#include "media/audio/win/audio_manager_win.h"
@@ -171,7 +171,7 @@ void AudioManagerWin::InitializeOnAudioThread() {
// AudioDeviceListenerWin must be initialized on a COM thread and should
// only be used if WASAPI / Core Audio is supported.
output_device_listener_.reset(new AudioDeviceListenerWin(BindToCurrentLoop(
- base::Bind(&AudioManagerWin::StallAudioThreadAfterDeviceChange,
+ base::Bind(&AudioManagerWin::NotifyAllOutputDeviceChangeListeners,
base::Unretained(this)))));
}
}
@@ -538,23 +538,6 @@ AudioInputStream* AudioManagerWin::CreatePCMWaveInAudioInputStream(
xp_device_id);
}
-void AudioManagerWin::StallAudioThreadAfterDeviceChange(
- AudioDeviceListenerWin::DeviceNotificationType notification_type) {
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
-
- if (notification_type == AudioDeviceListenerWin::kInputDeviceChange) {
- base::SystemMonitor* monitor = base::SystemMonitor::Get();
- if (monitor) {
- monitor->ProcessDevicesChanged(
- base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
- }
- return;
- }
-
- DCHECK_EQ(notification_type, AudioDeviceListenerWin::kOutputDeviceChange);
- NotifyAllOutputDeviceChangeListeners();
-}
-
/// static
AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
return new AudioManagerWin(audio_log_factory);
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index 3d33b55..9826566 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -8,10 +8,11 @@
#include <string>
#include "media/audio/audio_manager_base.h"
-#include "media/audio/win/audio_device_listener_win.h"
namespace media {
+class AudioDeviceListenerWin;
+
// Windows implementation of the AudioManager singleton. This class is internal
// to the audio output and only internal users can call methods not exposed by
// the AudioManager class.
@@ -87,12 +88,6 @@ class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
void GetAudioDeviceNamesImpl(bool input, AudioDeviceNames* device_names);
- // We frequently see deadlock in third party Windows audio drivers, so after
- // a device change is detected, stall for a second before allowing calls into
- // the Windows audio subsystem. See http://crbug.com/422522
- void StallAudioThreadAfterDeviceChange(
- AudioDeviceListenerWin::DeviceNotificationType notification_type);
-
// Listen for output device changes.
scoped_ptr<AudioDeviceListenerWin> output_device_listener_;