OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/audio/audio_manager.h" | 5 #include "media/audio/audio_manager.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/environment.h" | 10 #include "base/environment.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
13 #include "base/strings/string_number_conversions.h" | |
13 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
14 #include "base/test/test_message_loop.h" | 15 #include "base/test/test_message_loop.h" |
15 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
16 #include "build/build_config.h" | 17 #include "build/build_config.h" |
17 #include "media/audio/audio_device_description.h" | 18 #include "media/audio/audio_device_description.h" |
18 #include "media/audio/audio_manager.h" | 19 #include "media/audio/audio_manager.h" |
19 #include "media/audio/audio_output_proxy.h" | 20 #include "media/audio/audio_output_proxy.h" |
20 #include "media/audio/audio_unittest_util.h" | 21 #include "media/audio/audio_unittest_util.h" |
21 #include "media/audio/fake_audio_log_factory.h" | 22 #include "media/audio/fake_audio_log_factory.h" |
22 #include "media/audio/fake_audio_manager.h" | 23 #include "media/audio/fake_audio_manager.h" |
23 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
24 | 25 |
25 #if defined(USE_ALSA) | 26 #if defined(USE_ALSA) |
26 #include "media/audio/alsa/audio_manager_alsa.h" | 27 #include "media/audio/alsa/audio_manager_alsa.h" |
27 #endif // defined(USE_ALSA) | 28 #endif // defined(USE_ALSA) |
28 | 29 |
29 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
30 #include "base/win/scoped_com_initializer.h" | 31 #include "base/win/scoped_com_initializer.h" |
31 #include "media/audio/win/audio_manager_win.h" | 32 #include "media/audio/win/audio_manager_win.h" |
32 #include "media/audio/win/wavein_input_win.h" | 33 #include "media/audio/win/wavein_input_win.h" |
33 #endif | 34 #endif |
34 | 35 |
35 #if defined(USE_PULSEAUDIO) | 36 #if defined(USE_PULSEAUDIO) |
36 #include "media/audio/pulse/audio_manager_pulse.h" | 37 #include "media/audio/pulse/audio_manager_pulse.h" |
37 #endif // defined(USE_PULSEAUDIO) | 38 #endif // defined(USE_PULSEAUDIO) |
38 | 39 |
40 #if defined(USE_CRAS) | |
41 #include "chromeos/audio/audio_devices_pref_handler_stub.h" | |
42 #include "chromeos/audio/cras_audio_handler.h" | |
43 #include "chromeos/dbus/dbus_thread_manager.h" | |
44 #include "chromeos/dbus/fake_cras_audio_client.h" | |
45 #include "media/audio/cras/audio_manager_cras.h" | |
46 #endif // defined(USE_CRAS) | |
47 | |
39 namespace media { | 48 namespace media { |
40 | 49 |
41 namespace { | 50 namespace { |
42 template <typename T> | 51 template <typename T> |
43 struct TestAudioManagerFactory { | 52 struct TestAudioManagerFactory { |
44 static ScopedAudioManagerPtr Create(AudioLogFactory* audio_log_factory) { | 53 static ScopedAudioManagerPtr Create(AudioLogFactory* audio_log_factory) { |
45 return ScopedAudioManagerPtr(new T(base::ThreadTaskRunnerHandle::Get(), | 54 return ScopedAudioManagerPtr(new T(base::ThreadTaskRunnerHandle::Get(), |
46 base::ThreadTaskRunnerHandle::Get(), | 55 base::ThreadTaskRunnerHandle::Get(), |
47 audio_log_factory)); | 56 audio_log_factory)); |
48 } | 57 } |
(...skipping 13 matching lines...) Expand all Loading... | |
62 } | 71 } |
63 }; | 72 }; |
64 #endif // defined(USE_PULSEAUDIO) | 73 #endif // defined(USE_PULSEAUDIO) |
65 | 74 |
66 template <> | 75 template <> |
67 struct TestAudioManagerFactory<std::nullptr_t> { | 76 struct TestAudioManagerFactory<std::nullptr_t> { |
68 static ScopedAudioManagerPtr Create(AudioLogFactory* audio_log_factory) { | 77 static ScopedAudioManagerPtr Create(AudioLogFactory* audio_log_factory) { |
69 return AudioManager::CreateForTesting(base::ThreadTaskRunnerHandle::Get()); | 78 return AudioManager::CreateForTesting(base::ThreadTaskRunnerHandle::Get()); |
70 } | 79 } |
71 }; | 80 }; |
81 | |
82 #if defined(USE_CRAS) | |
83 using chromeos::AudioNode; | |
84 using chromeos::AudioNodeList; | |
85 | |
86 const uint64_t kJabraSpeaker1Id = 30001; | |
87 const uint64_t kJabraSpeaker1StableDeviceId = 80001; | |
88 const uint64_t kJabraSpeaker2Id = 30002; | |
89 const uint64_t kJabraSpeaker2StableDeviceId = 80002; | |
90 const uint64_t kHDMIOutputId = 30003; | |
91 const uint64_t kHDMIOutputStabeDevicelId = 80003; | |
92 const uint64_t kJabraMic1Id = 40001; | |
93 const uint64_t kJabraMic1StableDeviceId = 90001; | |
94 const uint64_t kJabraMic2Id = 40002; | |
95 const uint64_t kJabraMic2StableDeviceId = 90002; | |
96 const uint64_t kWebcamMicId = 40003; | |
97 const uint64_t kWebcamMicStableDeviceId = 90003; | |
98 | |
99 const AudioNode kJabraSpeaker1(false, | |
100 kJabraSpeaker1Id, | |
101 kJabraSpeaker1StableDeviceId, | |
102 "Jabra Speaker", | |
103 "USB", | |
104 "Jabra Speaker 1", | |
105 false, | |
106 0); | |
107 | |
108 const AudioNode kJabraSpeaker2(false, | |
109 kJabraSpeaker2Id, | |
110 kJabraSpeaker2StableDeviceId, | |
111 "Jabra Speaker", | |
112 "USB", | |
113 "Jabra Speaker 2", | |
114 false, | |
115 0); | |
116 | |
117 const AudioNode kHDMIOutput(false, | |
118 kHDMIOutputId, | |
119 kHDMIOutputStabeDevicelId, | |
120 "HDMI output", | |
121 "HDMI", | |
122 "HDA Intel MID", | |
123 false, | |
124 0); | |
125 | |
126 const AudioNode kJabraMic1(true, | |
127 kJabraMic1Id, | |
128 kJabraMic1StableDeviceId, | |
129 "Jabra Mic", | |
130 "USB", | |
131 "Jabra Mic 1", | |
132 false, | |
133 0); | |
134 | |
135 const AudioNode kJabraMic2(true, | |
136 kJabraMic2Id, | |
137 kJabraMic2StableDeviceId, | |
138 "Jabra Mic", | |
139 "USB", | |
140 "Jabra Mic 2", | |
141 false, | |
142 0); | |
143 | |
144 const AudioNode kUSBCameraMic(true, | |
145 kWebcamMicId, | |
146 kWebcamMicStableDeviceId, | |
147 "Webcam Mic", | |
148 "USB", | |
149 "Logitech Webcam", | |
150 false, | |
151 0); | |
152 #endif // defined(USE_CRAS) | |
153 | |
72 } // namespace | 154 } // namespace |
73 | 155 |
74 // Test fixture which allows us to override the default enumeration API on | 156 // Test fixture which allows us to override the default enumeration API on |
75 // Windows. | 157 // Windows. |
76 class AudioManagerTest : public ::testing::Test { | 158 class AudioManagerTest : public ::testing::Test { |
77 public: | 159 public: |
78 void HandleDefaultDeviceIDsTest() { | 160 void HandleDefaultDeviceIDsTest() { |
79 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 161 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
80 CHANNEL_LAYOUT_STEREO, 48000, 16, 2048); | 162 CHANNEL_LAYOUT_STEREO, 48000, 16, 2048); |
81 | 163 |
(...skipping 26 matching lines...) Expand all Loading... | |
108 void GetDefaultOutputStreamParameters(media::AudioParameters* params) { | 190 void GetDefaultOutputStreamParameters(media::AudioParameters* params) { |
109 *params = audio_manager_->GetDefaultOutputStreamParameters(); | 191 *params = audio_manager_->GetDefaultOutputStreamParameters(); |
110 } | 192 } |
111 | 193 |
112 void GetAssociatedOutputDeviceID(const std::string& input_device_id, | 194 void GetAssociatedOutputDeviceID(const std::string& input_device_id, |
113 std::string* output_device_id) { | 195 std::string* output_device_id) { |
114 *output_device_id = | 196 *output_device_id = |
115 audio_manager_->GetAssociatedOutputDeviceID(input_device_id); | 197 audio_manager_->GetAssociatedOutputDeviceID(input_device_id); |
116 } | 198 } |
117 | 199 |
200 #if defined(USE_CRAS) | |
201 void TearDown() override { | |
202 chromeos::CrasAudioHandler::Shutdown(); | |
203 audio_pref_handler_ = nullptr; | |
204 chromeos::DBusThreadManager::Shutdown(); | |
205 } | |
206 | |
207 void SetUpCrasAudioHandlerWithTestingNodes(const AudioNodeList& audio_nodes) { | |
208 chromeos::DBusThreadManager::Initialize(); | |
209 audio_client_ = static_cast<chromeos::FakeCrasAudioClient*>( | |
210 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()); | |
211 audio_client_->SetAudioNodesForTesting(audio_nodes); | |
212 audio_pref_handler_ = new chromeos::AudioDevicesPrefHandlerStub(); | |
213 chromeos::CrasAudioHandler::Initialize(audio_pref_handler_); | |
214 cras_audio_handler_ = chromeos::CrasAudioHandler::Get(); | |
215 base::RunLoop().RunUntilIdle(); | |
216 } | |
217 #endif // defined(USE_CRAS) | |
218 | |
118 protected: | 219 protected: |
119 AudioManagerTest() { CreateAudioManagerForTesting(); } | 220 AudioManagerTest() { CreateAudioManagerForTesting(); } |
120 ~AudioManagerTest() override {} | 221 ~AudioManagerTest() override {} |
121 | 222 |
122 #if defined(OS_WIN) | 223 #if defined(OS_WIN) |
123 bool SetMMDeviceEnumeration() { | 224 bool SetMMDeviceEnumeration() { |
124 AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get()); | 225 AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get()); |
125 // Windows Wave is used as default if Windows XP was detected => | 226 // Windows Wave is used as default if Windows XP was detected => |
126 // return false since MMDevice is not supported on XP. | 227 // return false since MMDevice is not supported on XP. |
127 if (amw->enumeration_type() == AudioManagerWin::kWaveEnumeration) | 228 if (amw->enumeration_type() == AudioManagerWin::kWaveEnumeration) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 ++it; | 279 ++it; |
179 } | 280 } |
180 } else { | 281 } else { |
181 // Log a warning so we can see the status on the build bots. No need to | 282 // Log a warning so we can see the status on the build bots. No need to |
182 // break the test though since this does successfully test the code and | 283 // break the test though since this does successfully test the code and |
183 // some failure cases. | 284 // some failure cases. |
184 LOG(WARNING) << "No input devices detected"; | 285 LOG(WARNING) << "No input devices detected"; |
185 } | 286 } |
186 } | 287 } |
187 | 288 |
289 #if defined(USE_CRAS) | |
290 // Helper method for (USE_CRAS) which verifies that the device list starts | |
291 // with a valid default record followed by physical device names. | |
292 static void CheckDeviceNamesCras( | |
293 const AudioDeviceNames& device_names, | |
294 const std::map<uint64_t, std::string>& expectation) { | |
295 DVLOG(2) << "Got " << device_names.size() << " audio devices."; | |
296 if (!device_names.empty()) { | |
297 AudioDeviceNames::const_iterator it = device_names.begin(); | |
298 | |
299 // The first device in the list should always be the default device. | |
300 EXPECT_EQ(AudioDeviceDescription::GetDefaultDeviceName(), | |
301 it->device_name); | |
302 EXPECT_EQ(std::string(AudioDeviceDescription::kDefaultDeviceId), | |
303 it->unique_id); | |
304 ++it; | |
tommi (sloooow) - chröme
2016/06/18 14:00:37
nit: move this to just above the loop. As is, it l
Qiang(Joe) Xu
2016/07/06 16:27:02
Done.
| |
305 | |
306 // |device_names|'size should be |expectation|'s size plus one because of | |
307 // default device. | |
308 EXPECT_EQ(device_names.size(), expectation.size() + 1); | |
309 // Check other devices that should have non-empty name and id, and should | |
310 // be contained in expectation. | |
311 while (it != device_names.end()) { | |
312 EXPECT_FALSE(it->device_name.empty()); | |
313 EXPECT_FALSE(it->unique_id.empty()); | |
314 DVLOG(2) << "Device ID(" << it->unique_id | |
315 << "), label: " << it->device_name; | |
316 uint64_t key; | |
317 EXPECT_TRUE(base::StringToUint64(it->unique_id, &key)); | |
318 EXPECT_TRUE(expectation.find(key) != expectation.end()); | |
319 EXPECT_EQ(expectation.find(key)->second, it->device_name); | |
320 ++it; | |
321 } | |
322 } else { | |
323 // Log a warning so we can see the status on the build bots. No need to | |
324 // break the test though since this does successfully test the code and | |
325 // some failure cases. | |
326 LOG(WARNING) << "No input devices detected"; | |
327 } | |
328 } | |
329 #endif // defined(USE_CRAS) | |
330 | |
188 bool InputDevicesAvailable() { | 331 bool InputDevicesAvailable() { |
189 return audio_manager_->HasAudioInputDevices(); | 332 return audio_manager_->HasAudioInputDevices(); |
190 } | 333 } |
191 bool OutputDevicesAvailable() { | 334 bool OutputDevicesAvailable() { |
192 return audio_manager_->HasAudioOutputDevices(); | 335 return audio_manager_->HasAudioOutputDevices(); |
193 } | 336 } |
194 | 337 |
195 template <typename T = std::nullptr_t> | 338 template <typename T = std::nullptr_t> |
196 void CreateAudioManagerForTesting() { | 339 void CreateAudioManagerForTesting() { |
197 // Only one AudioManager may exist at a time, so destroy the one we're | 340 // Only one AudioManager may exist at a time, so destroy the one we're |
198 // currently holding before creating a new one. | 341 // currently holding before creating a new one. |
199 // Flush the message loop to run any shutdown tasks posted by AudioManager. | 342 // Flush the message loop to run any shutdown tasks posted by AudioManager. |
200 audio_manager_.reset(); | 343 audio_manager_.reset(); |
201 base::RunLoop().RunUntilIdle(); | 344 base::RunLoop().RunUntilIdle(); |
202 | 345 |
203 audio_manager_ = | 346 audio_manager_ = |
204 TestAudioManagerFactory<T>::Create(&fake_audio_log_factory_); | 347 TestAudioManagerFactory<T>::Create(&fake_audio_log_factory_); |
205 // A few AudioManager implementations post initialization tasks to | 348 // A few AudioManager implementations post initialization tasks to |
206 // audio thread. Flush the thread to ensure that |audio_manager_| is | 349 // audio thread. Flush the thread to ensure that |audio_manager_| is |
207 // initialized and ready to use before returning from this function. | 350 // initialized and ready to use before returning from this function. |
208 // TODO(alokp): We should perhaps do this in AudioManager::Create(). | 351 // TODO(alokp): We should perhaps do this in AudioManager::Create(). |
209 base::RunLoop().RunUntilIdle(); | 352 base::RunLoop().RunUntilIdle(); |
210 } | 353 } |
211 | 354 |
212 base::TestMessageLoop message_loop_; | 355 base::TestMessageLoop message_loop_; |
213 FakeAudioLogFactory fake_audio_log_factory_; | 356 FakeAudioLogFactory fake_audio_log_factory_; |
214 ScopedAudioManagerPtr audio_manager_; | 357 ScopedAudioManagerPtr audio_manager_; |
358 | |
359 #if defined(USE_CRAS) | |
360 chromeos::CrasAudioHandler* cras_audio_handler_ = nullptr; // Not owned. | |
361 chromeos::FakeCrasAudioClient* audio_client_ = nullptr; // Not owned. | |
362 scoped_refptr<chromeos::AudioDevicesPrefHandlerStub> audio_pref_handler_; | |
363 #endif // defined(USE_CRAS) | |
215 }; | 364 }; |
216 | 365 |
366 #if defined(USE_CRAS) | |
367 TEST_F(AudioManagerTest, EnumerateInputDevicesCras) { | |
368 // Setup the devices without internal mic, so that it doesn't exist | |
369 // beamforming capable mic. | |
370 AudioNodeList audio_nodes; | |
371 audio_nodes.push_back(kJabraMic1); | |
372 audio_nodes.push_back(kJabraMic2); | |
373 audio_nodes.push_back(kUSBCameraMic); | |
374 audio_nodes.push_back(kHDMIOutput); | |
375 audio_nodes.push_back(kJabraSpeaker1); | |
376 SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); | |
377 | |
378 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable()); | |
379 | |
380 // Setup expectation with physical devices. | |
381 std::map<uint64_t, std::string> expectation; | |
382 expectation[kJabraMic1.id] = kJabraMic1.device_name; | |
383 expectation[kJabraMic2.id] = kJabraMic2.device_name; | |
384 expectation[kUSBCameraMic.id] = kUSBCameraMic.device_name; | |
385 | |
386 DVLOG(2) << "Testing AudioManagerCras."; | |
387 CreateAudioManagerForTesting<AudioManagerCras>(); | |
388 AudioDeviceNames device_names; | |
389 audio_manager_->GetAudioInputDeviceNames(&device_names); | |
390 CheckDeviceNamesCras(device_names, expectation); | |
391 } | |
392 | |
393 TEST_F(AudioManagerTest, EnumerateOutputDevicesCras) { | |
394 // Setup the devices without internal mic, so that it doesn't exist | |
395 // beamforming capable mic. | |
396 AudioNodeList audio_nodes; | |
397 audio_nodes.push_back(kJabraMic1); | |
398 audio_nodes.push_back(kJabraMic2); | |
399 audio_nodes.push_back(kUSBCameraMic); | |
400 audio_nodes.push_back(kHDMIOutput); | |
401 audio_nodes.push_back(kJabraSpeaker1); | |
402 SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); | |
403 | |
404 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable()); | |
405 | |
406 // Setup expectation with physical devices. | |
407 std::map<uint64_t, std::string> expectation; | |
408 expectation[kHDMIOutput.id] = kHDMIOutput.device_name; | |
409 expectation[kJabraSpeaker1.id] = kJabraSpeaker1.device_name; | |
410 | |
411 DVLOG(2) << "Testing AudioManagerCras."; | |
412 CreateAudioManagerForTesting<AudioManagerCras>(); | |
413 AudioDeviceNames device_names; | |
414 audio_manager_->GetAudioOutputDeviceNames(&device_names); | |
415 CheckDeviceNamesCras(device_names, expectation); | |
416 } | |
417 #else // !defined(USE_CRAS) | |
418 | |
217 TEST_F(AudioManagerTest, HandleDefaultDeviceIDs) { | 419 TEST_F(AudioManagerTest, HandleDefaultDeviceIDs) { |
218 // Use a fake manager so we can makeup device ids, this will still use the | 420 // Use a fake manager so we can makeup device ids, this will still use the |
219 // AudioManagerBase code. | 421 // AudioManagerBase code. |
220 CreateAudioManagerForTesting<FakeAudioManager>(); | 422 CreateAudioManagerForTesting<FakeAudioManager>(); |
221 HandleDefaultDeviceIDsTest(); | 423 HandleDefaultDeviceIDsTest(); |
222 base::RunLoop().RunUntilIdle(); | 424 base::RunLoop().RunUntilIdle(); |
223 } | 425 } |
224 | 426 |
225 // Test that devices can be enumerated. | 427 // Test that devices can be enumerated. |
226 TEST_F(AudioManagerTest, EnumerateInputDevices) { | 428 TEST_F(AudioManagerTest, EnumerateInputDevices) { |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
424 GetAssociatedOutputDeviceID(it->unique_id, &output_device_id); | 626 GetAssociatedOutputDeviceID(it->unique_id, &output_device_id); |
425 if (!output_device_id.empty()) { | 627 if (!output_device_id.empty()) { |
426 DVLOG(2) << it->unique_id << " matches with " << output_device_id; | 628 DVLOG(2) << it->unique_id << " matches with " << output_device_id; |
427 found_an_associated_device = true; | 629 found_an_associated_device = true; |
428 } | 630 } |
429 } | 631 } |
430 | 632 |
431 EXPECT_TRUE(found_an_associated_device); | 633 EXPECT_TRUE(found_an_associated_device); |
432 #endif // defined(OS_WIN) || defined(OS_MACOSX) | 634 #endif // defined(OS_WIN) || defined(OS_MACOSX) |
433 } | 635 } |
636 #endif // defined(USE_CRAS) | |
434 | 637 |
435 } // namespace media | 638 } // namespace media |
OLD | NEW |