diff options
author | Guido Urdaneta <guidou@chromium.org> | 2016-01-19 16:44:45 +0100 |
---|---|---|
committer | Guido Urdaneta <guidou@chromium.org> | 2016-01-19 15:46:20 +0000 |
commit | 92eee5fadce818fd2ffec2821b0a1f09d6c25a55 (patch) | |
tree | 0496a0b5ad8b20122fefa9163ca9d5b00bc3d221 | |
parent | 0ab02382f778bb73f29bc3795acd22bbbd3569a3 (diff) | |
download | chromium_src-92eee5fadce818fd2ffec2821b0a1f09d6c25a55.zip chromium_src-92eee5fadce818fd2ffec2821b0a1f09d6c25a55.tar.gz chromium_src-92eee5fadce818fd2ffec2821b0a1f09d6c25a55.tar.bz2 |
Correctly handle enumerations for AudioManagers that report only the default audio output device.
BUG=578993
Review URL: https://codereview.chromium.org/1602083003
Cr-Commit-Position: refs/heads/master@{#370113}
(cherry picked from commit bbfc18f1577804ae0ee6f42d5866940116c97696)
Review URL: https://codereview.chromium.org/1607923002 .
Cr-Commit-Position: refs/branch-heads/2623@{#9}
Cr-Branched-From: 92d77538a86529ca35f9220bd3cd512cbea1f086-refs/heads/master@{#369907}
6 files changed, 148 insertions, 21 deletions
diff --git a/content/browser/renderer_host/media/audio_output_device_enumerator.cc b/content/browser/renderer_host/media/audio_output_device_enumerator.cc index 70a4320..54c0531 100644 --- a/content/browser/renderer_host/media/audio_output_device_enumerator.cc +++ b/content/browser/renderer_host/media/audio_output_device_enumerator.cc @@ -23,16 +23,19 @@ AudioOutputDeviceEnumeration EnumerateDevicesOnDeviceThread( media::AudioDeviceNames device_names; audio_manager->GetAudioOutputDeviceNames(&device_names); + snapshot.has_actual_devices = !device_names.empty(); + // If no devices in enumeration, return a list with a default device - if (device_names.empty()) { - snapshot.push_back({media::AudioManagerBase::kDefaultDeviceId, - media::AudioManager::GetDefaultDeviceName(), - audio_manager->GetDefaultOutputStreamParameters()}); + if (!snapshot.has_actual_devices) { + snapshot.devices.push_back( + {media::AudioManagerBase::kDefaultDeviceId, + media::AudioManager::GetDefaultDeviceName(), + audio_manager->GetDefaultOutputStreamParameters()}); return snapshot; } for (const media::AudioDeviceName& name : device_names) { - snapshot.push_back( + snapshot.devices.push_back( {name.unique_id, name.device_name, name.unique_id == media::AudioManagerBase::kDefaultDeviceId ? audio_manager->GetDefaultOutputStreamParameters() @@ -43,6 +46,16 @@ AudioOutputDeviceEnumeration EnumerateDevicesOnDeviceThread( } // namespace +AudioOutputDeviceEnumeration::AudioOutputDeviceEnumeration( + const std::vector<AudioOutputDeviceInfo>& devices, + bool has_actual_devices) + : devices(devices), has_actual_devices(has_actual_devices) {} + +AudioOutputDeviceEnumeration::AudioOutputDeviceEnumeration() + : has_actual_devices(false) {} + +AudioOutputDeviceEnumeration::~AudioOutputDeviceEnumeration() {} + AudioOutputDeviceEnumerator::AudioOutputDeviceEnumerator( media::AudioManager* audio_manager, CachePolicy cache_policy) diff --git a/content/browser/renderer_host/media/audio_output_device_enumerator.h b/content/browser/renderer_host/media/audio_output_device_enumerator.h index 740e9c6..bf223a9 100644 --- a/content/browser/renderer_host/media/audio_output_device_enumerator.h +++ b/content/browser/renderer_host/media/audio_output_device_enumerator.h @@ -43,7 +43,19 @@ struct AudioOutputDeviceInfo { media::AudioParameters output_params; }; -typedef std::vector<AudioOutputDeviceInfo> AudioOutputDeviceEnumeration; +// The result of an enumeration. It is used only in the browser side. +struct AudioOutputDeviceEnumeration { + public: + AudioOutputDeviceEnumeration( + const std::vector<AudioOutputDeviceInfo>& devices, + bool has_actual_devices); + AudioOutputDeviceEnumeration(); + ~AudioOutputDeviceEnumeration(); + + std::vector<AudioOutputDeviceInfo> devices; + bool has_actual_devices; +}; + typedef base::Callback<void(const AudioOutputDeviceEnumeration&)> AudioOutputDeviceEnumerationCB; @@ -59,11 +71,15 @@ class CONTENT_EXPORT AudioOutputDeviceEnumerator { // Does an enumeration and provides the results to the callback. // If there are no physical devices, the result contains a single entry with - // the default parameters provided by the underlying audio manager. + // the default parameters provided by the underlying audio manager and with + // the |has_actual_devices| field set to false. // The behavior with no physical devices is there to ease the transition // from the use of RenderThreadImpl::GetAudioHardwareConfig(), which always // provides default parameters, even if there are no devices. // See https://crbug.com/549125. + // Some audio managers always report a single device, regardless of the + // physical devices in the system. In this case the |has_actual_devices| field + // is set to true to differentiate from the case of no physical devices. void Enumerate(const AudioOutputDeviceEnumerationCB& callback); // Invalidates the current cache. diff --git a/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc b/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc index de1aa34..ac6140c 100644 --- a/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc +++ b/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" +#include "base/strings/string_number_conversions.h" #include "base/thread_task_runner_handle.h" #include "content/browser/renderer_host/media/audio_output_device_enumerator.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -25,24 +26,62 @@ using testing::_; namespace content { namespace { + class MockAudioManager : public media::FakeAudioManager { public: - MockAudioManager() : FakeAudioManager(&fake_audio_log_factory_) {} + MockAudioManager(size_t num_devices) + : FakeAudioManager(&fake_audio_log_factory_), num_devices_(num_devices) {} + MockAudioManager() : MockAudioManager(0) {} ~MockAudioManager() override {} - MOCK_METHOD1(GetAudioOutputDeviceNames, void(media::AudioDeviceNames*)); + + MOCK_METHOD1(MockGetAudioOutputDeviceNames, void(media::AudioDeviceNames*)); + + void GetAudioOutputDeviceNames( + media::AudioDeviceNames* device_names) override { + DCHECK(device_names->empty()); + MockGetAudioOutputDeviceNames(device_names); + if (num_devices_ > 0) { + device_names->push_back( + media::AudioDeviceName(AudioManager::GetDefaultDeviceName(), + AudioManagerBase::kDefaultDeviceId)); + for (size_t i = 0; i < num_devices_; i++) { + device_names->push_back( + media::AudioDeviceName("FakeDeviceName_" + base::IntToString(i), + "FakeDeviceId_" + base::IntToString(i))); + } + } + } private: media::FakeAudioLogFactory fake_audio_log_factory_; + size_t num_devices_; DISALLOW_COPY_AND_ASSIGN(MockAudioManager); }; + +// Fake audio manager that exposes only the default device +class OnlyDefaultDeviceAudioManager : public MockAudioManager { + public: + OnlyDefaultDeviceAudioManager() {} + ~OnlyDefaultDeviceAudioManager() override {} + void GetAudioOutputDeviceNames( + media::AudioDeviceNames* device_names) override { + DCHECK(device_names->empty()); + MockGetAudioOutputDeviceNames(device_names); + device_names->push_front( + media::AudioDeviceName(AudioManager::GetDefaultDeviceName(), + AudioManagerBase::kDefaultDeviceId)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(OnlyDefaultDeviceAudioManager); +}; + } // namespace class AudioOutputDeviceEnumeratorTest : public ::testing::Test { public: AudioOutputDeviceEnumeratorTest() - : thread_bundle_(), task_runner_(base::ThreadTaskRunnerHandle::Get()) { - audio_manager_.reset(new MockAudioManager()); - } + : thread_bundle_(), task_runner_(base::ThreadTaskRunnerHandle::Get()) {} ~AudioOutputDeviceEnumeratorTest() override {} @@ -65,6 +104,14 @@ class AudioOutputDeviceEnumeratorTest : public ::testing::Test { } } + void EnumerateCountCallback(size_t num_entries_expected, + bool actual_devices_expected, + const AudioOutputDeviceEnumeration& result) { + EXPECT_EQ(actual_devices_expected, result.has_actual_devices); + EXPECT_EQ(num_entries_expected, result.devices.size()); + task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure()); + } + void QuitCallback(const AudioOutputDeviceEnumeration& result) { MockCallback(result); task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure()); @@ -82,7 +129,8 @@ class AudioOutputDeviceEnumeratorTest : public ::testing::Test { TEST_F(AudioOutputDeviceEnumeratorTest, EnumerateWithCache) { const int num_calls = 10; - EXPECT_CALL(*audio_manager_, GetAudioOutputDeviceNames(_)).Times(1); + audio_manager_.reset(new MockAudioManager()); + EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(1); EXPECT_CALL(*this, MockCallback(_)).Times(num_calls); AudioOutputDeviceEnumerator enumerator( audio_manager_.get(), @@ -95,7 +143,9 @@ TEST_F(AudioOutputDeviceEnumeratorTest, EnumerateWithCache) { TEST_F(AudioOutputDeviceEnumeratorTest, EnumerateWithNoCache) { const int num_calls = 10; - EXPECT_CALL(*audio_manager_, GetAudioOutputDeviceNames(_)).Times(num_calls); + audio_manager_.reset(new MockAudioManager()); + EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)) + .Times(num_calls); EXPECT_CALL(*this, MockCallback(_)).Times(num_calls); AudioOutputDeviceEnumerator enumerator( audio_manager_.get(), @@ -106,4 +156,54 @@ TEST_F(AudioOutputDeviceEnumeratorTest, EnumerateWithNoCache) { run_loop_.Run(); } +TEST_F(AudioOutputDeviceEnumeratorTest, EnumerateNoDevices) { + audio_manager_.reset(new MockAudioManager()); + EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)); + AudioOutputDeviceEnumerator enumerator( + audio_manager_.get(), + AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING); + enumerator.Enumerate( + base::Bind(&AudioOutputDeviceEnumeratorTest::EnumerateCountCallback, + base::Unretained(this), 1, false)); + run_loop_.Run(); +} + +TEST_F(AudioOutputDeviceEnumeratorTest, EnumerateOnlyDefaultDevice) { + audio_manager_.reset(new OnlyDefaultDeviceAudioManager()); + EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)); + AudioOutputDeviceEnumerator enumerator( + audio_manager_.get(), + AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING); + enumerator.Enumerate( + base::Bind(&AudioOutputDeviceEnumeratorTest::EnumerateCountCallback, + base::Unretained(this), 1, true)); + run_loop_.Run(); +} + +TEST_F(AudioOutputDeviceEnumeratorTest, EnumerateOneDevice) { + size_t num_devices = 1; + audio_manager_.reset(new MockAudioManager(num_devices)); + EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)); + AudioOutputDeviceEnumerator enumerator( + audio_manager_.get(), + AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING); + enumerator.Enumerate( + base::Bind(&AudioOutputDeviceEnumeratorTest::EnumerateCountCallback, + base::Unretained(this), num_devices + 1, true)); + run_loop_.Run(); +} + +TEST_F(AudioOutputDeviceEnumeratorTest, EnumerateMultipleDevices) { + size_t num_devices = 5; + audio_manager_.reset(new MockAudioManager(num_devices)); + EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)); + AudioOutputDeviceEnumerator enumerator( + audio_manager_.get(), + AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING); + enumerator.Enumerate( + base::Bind(&AudioOutputDeviceEnumeratorTest::EnumerateCountCallback, + base::Unretained(this), num_devices + 1, true)); + run_loop_.Run(); +} + } // namespace content diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc index 49e395b..d469d34 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_renderer_host.cc @@ -840,9 +840,9 @@ void AudioRendererHost::TranslateDeviceID( const std::string& device_id, const GURL& security_origin, const OutputDeviceInfoCB& callback, - const AudioOutputDeviceEnumeration& device_infos) { + const AudioOutputDeviceEnumeration& enumeration) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - for (const AudioOutputDeviceInfo& device_info : device_infos) { + for (const AudioOutputDeviceInfo& device_info : enumeration.devices) { if (device_id.empty()) { if (device_info.unique_id == media::AudioManagerBase::kDefaultDeviceId) { callback.Run(true, device_info); diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h index ce32fb1..e549df2 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.h +++ b/content/browser/renderer_host/media/audio_renderer_host.h @@ -231,7 +231,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter { void TranslateDeviceID(const std::string& device_id, const GURL& gurl_security_origin, const OutputDeviceInfoCB& callback, - const AudioOutputDeviceEnumeration& device_infos); + const AudioOutputDeviceEnumeration& enumeration); // Helper method to check if the authorization procedure for stream // |stream_id| has started. diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 49c828b..f602e8d 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc @@ -739,10 +739,8 @@ void MediaStreamManager::AudioOutputDevicesEnumerated( DVLOG(1) << "AudioOutputDevicesEnumerated()"; StreamDeviceInfoArray device_infos; - // If the enumeration contains only one entry, it means there are no devices. - // The single entry contains default parameters from the audio manager. - if (device_enumeration.size() > 1) { - for (const auto& entry : device_enumeration) { + if (device_enumeration.has_actual_devices) { + for (const auto& entry : device_enumeration.devices) { StreamDeviceInfo device_info(MEDIA_DEVICE_AUDIO_OUTPUT, entry.device_name, entry.unique_id); device_infos.push_back(device_info); |