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
3 // found in the LICENSE file.
6 #include "base/environment.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "media/audio/audio_manager.h"
11 #include "media/audio/audio_manager_base.h"
12 #include "media/audio/audio_unittest_util.h"
13 #include "media/audio/fake_audio_log_factory.h"
14 #include "testing/gtest/include/gtest/gtest.h"
17 #include "media/audio/alsa/audio_manager_alsa.h"
18 #endif // defined(USE_ALSA)
21 #include "base/win/scoped_com_initializer.h"
22 #include "media/audio/win/audio_manager_win.h"
23 #include "media/audio/win/wavein_input_win.h"
26 #if defined(USE_PULSEAUDIO)
27 #include "media/audio/pulse/audio_manager_pulse.h"
28 #endif // defined(USE_PULSEAUDIO)
32 // Test fixture which allows us to override the default enumeration API on
34 class AudioManagerTest
: public ::testing::Test
{
37 : audio_manager_(AudioManager::CreateForTesting())
39 , com_init_(base::win::ScopedCOMInitializer::kMTA
)
42 // Wait for audio thread initialization to complete. Otherwise the
43 // enumeration type may not have been set yet.
44 base::WaitableEvent
event(false, false);
45 audio_manager_
->GetTaskRunner()->PostTask(FROM_HERE
, base::Bind(
46 &base::WaitableEvent::Signal
, base::Unretained(&event
)));
51 bool SetMMDeviceEnumeration() {
52 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
53 // Windows Wave is used as default if Windows XP was detected =>
54 // return false since MMDevice is not supported on XP.
55 if (amw
->enumeration_type() == AudioManagerWin::kWaveEnumeration
)
58 amw
->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration
);
62 void SetWaveEnumeration() {
63 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
64 amw
->SetEnumerationType(AudioManagerWin::kWaveEnumeration
);
67 std::string
GetDeviceIdFromPCMWaveInAudioInputStream(
68 const std::string
& device_id
) {
69 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
70 AudioParameters
parameters(
71 AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_STEREO
,
72 AudioParameters::kAudioCDSampleRate
, 16,
74 scoped_ptr
<PCMWaveInAudioInputStream
> stream(
75 static_cast<PCMWaveInAudioInputStream
*>(
76 amw
->CreatePCMWaveInAudioInputStream(parameters
, device_id
)));
77 return stream
.get() ? stream
->device_id_
: std::string();
81 // Helper method which verifies that the device list starts with a valid
82 // default record followed by non-default device names.
83 static void CheckDeviceNames(const AudioDeviceNames
& device_names
) {
84 DVLOG(2) << "Got " << device_names
.size() << " audio devices.";
85 if (!device_names
.empty()) {
86 AudioDeviceNames::const_iterator it
= device_names
.begin();
88 // The first device in the list should always be the default device.
89 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName
),
91 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId
), it
->unique_id
);
94 // Other devices should have non-empty name and id and should not contain
95 // default name or id.
96 while (it
!= device_names
.end()) {
97 EXPECT_FALSE(it
->device_name
.empty());
98 EXPECT_FALSE(it
->unique_id
.empty());
99 DVLOG(2) << "Device ID(" << it
->unique_id
100 << "), label: " << it
->device_name
;
101 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName
),
103 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId
),
108 // Log a warning so we can see the status on the build bots. No need to
109 // break the test though since this does successfully test the code and
110 // some failure cases.
111 LOG(WARNING
) << "No input devices detected";
115 bool InputDevicesAvailable() {
116 return audio_manager_
->HasAudioInputDevices();
119 bool OutputDevicesAvailable() {
120 return audio_manager_
->HasAudioOutputDevices();
123 #if defined(USE_ALSA) || defined(USE_PULSEAUDIO)
125 void CreateAudioManagerForTesting() {
126 // Only one AudioManager may exist at a time, so destroy the one we're
127 // currently holding before creating a new one.
128 audio_manager_
.reset();
129 audio_manager_
.reset(T::Create(&fake_audio_log_factory_
));
133 // Synchronously runs the provided callback/closure on the audio thread.
134 void RunOnAudioThread(const base::Closure
& closure
) {
135 if (!audio_manager_
->GetTaskRunner()->BelongsToCurrentThread()) {
136 base::WaitableEvent
event(false, false);
137 audio_manager_
->GetTaskRunner()->PostTask(
139 base::Bind(&AudioManagerTest::RunOnAudioThreadImpl
,
140 base::Unretained(this),
149 void RunOnAudioThreadImpl(const base::Closure
& closure
,
150 base::WaitableEvent
* event
) {
151 DCHECK(audio_manager_
->GetTaskRunner()->BelongsToCurrentThread());
156 FakeAudioLogFactory fake_audio_log_factory_
;
157 scoped_ptr
<AudioManager
> audio_manager_
;
160 // The MMDevice API requires COM to be initialized on the current thread.
161 base::win::ScopedCOMInitializer com_init_
;
165 // Test that devices can be enumerated.
166 TEST_F(AudioManagerTest
, EnumerateInputDevices
) {
167 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
169 AudioDeviceNames device_names
;
171 base::Bind(&AudioManager::GetAudioInputDeviceNames
,
172 base::Unretained(audio_manager_
.get()),
174 CheckDeviceNames(device_names
);
177 // Test that devices can be enumerated.
178 TEST_F(AudioManagerTest
, EnumerateOutputDevices
) {
179 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
181 AudioDeviceNames device_names
;
183 base::Bind(&AudioManager::GetAudioOutputDeviceNames
,
184 base::Unretained(audio_manager_
.get()),
186 CheckDeviceNames(device_names
);
189 // Run additional tests for Windows since enumeration can be done using
190 // two different APIs. MMDevice is default for Vista and higher and Wave
191 // is default for XP and lower.
194 // Override default enumeration API and force usage of Windows MMDevice.
195 // This test will only run on Windows Vista and higher.
196 TEST_F(AudioManagerTest
, EnumerateInputDevicesWinMMDevice
) {
197 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
199 AudioDeviceNames device_names
;
200 if (!SetMMDeviceEnumeration()) {
201 // Usage of MMDevice will fail on XP and lower.
202 LOG(WARNING
) << "MM device enumeration is not supported.";
205 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
206 CheckDeviceNames(device_names
);
209 TEST_F(AudioManagerTest
, EnumerateOutputDevicesWinMMDevice
) {
210 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
212 AudioDeviceNames device_names
;
213 if (!SetMMDeviceEnumeration()) {
214 // Usage of MMDevice will fail on XP and lower.
215 LOG(WARNING
) << "MM device enumeration is not supported.";
218 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
219 CheckDeviceNames(device_names
);
222 // Override default enumeration API and force usage of Windows Wave.
223 // This test will run on Windows XP, Windows Vista and Windows 7.
224 TEST_F(AudioManagerTest
, EnumerateInputDevicesWinWave
) {
225 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
227 AudioDeviceNames device_names
;
228 SetWaveEnumeration();
229 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
230 CheckDeviceNames(device_names
);
233 TEST_F(AudioManagerTest
, EnumerateOutputDevicesWinWave
) {
234 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
236 AudioDeviceNames device_names
;
237 SetWaveEnumeration();
238 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
239 CheckDeviceNames(device_names
);
242 TEST_F(AudioManagerTest
, WinXPDeviceIdUnchanged
) {
243 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
245 AudioDeviceNames xp_device_names
;
246 SetWaveEnumeration();
247 audio_manager_
->GetAudioInputDeviceNames(&xp_device_names
);
248 CheckDeviceNames(xp_device_names
);
250 // Device ID should remain unchanged, including the default device ID.
251 for (AudioDeviceNames::iterator i
= xp_device_names
.begin();
252 i
!= xp_device_names
.end(); ++i
) {
253 EXPECT_EQ(i
->unique_id
,
254 GetDeviceIdFromPCMWaveInAudioInputStream(i
->unique_id
));
258 TEST_F(AudioManagerTest
, ConvertToWinXPInputDeviceId
) {
259 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
261 if (!SetMMDeviceEnumeration()) {
262 // Usage of MMDevice will fail on XP and lower.
263 LOG(WARNING
) << "MM device enumeration is not supported.";
267 AudioDeviceNames device_names
;
268 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
269 CheckDeviceNames(device_names
);
271 for (AudioDeviceNames::iterator i
= device_names
.begin();
272 i
!= device_names
.end(); ++i
) {
273 std::string converted_id
=
274 GetDeviceIdFromPCMWaveInAudioInputStream(i
->unique_id
);
275 if (i
== device_names
.begin()) {
276 // The first in the list is the default device ID, which should not be
277 // changed when passed to PCMWaveInAudioInputStream.
278 EXPECT_EQ(i
->unique_id
, converted_id
);
280 // MMDevice-style device IDs should be converted to WaveIn-style device
282 EXPECT_NE(i
->unique_id
, converted_id
);
287 #endif // defined(OS_WIN)
289 #if defined(USE_PULSEAUDIO)
290 // On Linux, there are two implementations available and both can
291 // sometimes be tested on a single system. These tests specifically
294 TEST_F(AudioManagerTest
, EnumerateInputDevicesPulseaudio
) {
295 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
297 CreateAudioManagerForTesting
<AudioManagerPulse
>();
298 if (audio_manager_
.get()) {
299 AudioDeviceNames device_names
;
300 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
301 CheckDeviceNames(device_names
);
303 LOG(WARNING
) << "No pulseaudio on this system.";
307 TEST_F(AudioManagerTest
, EnumerateOutputDevicesPulseaudio
) {
308 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
310 CreateAudioManagerForTesting
<AudioManagerPulse
>();
311 if (audio_manager_
.get()) {
312 AudioDeviceNames device_names
;
313 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
314 CheckDeviceNames(device_names
);
316 LOG(WARNING
) << "No pulseaudio on this system.";
319 #endif // defined(USE_PULSEAUDIO)
321 #if defined(USE_ALSA)
322 // On Linux, there are two implementations available and both can
323 // sometimes be tested on a single system. These tests specifically
326 TEST_F(AudioManagerTest
, EnumerateInputDevicesAlsa
) {
327 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
329 DVLOG(2) << "Testing AudioManagerAlsa.";
330 CreateAudioManagerForTesting
<AudioManagerAlsa
>();
331 AudioDeviceNames device_names
;
332 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
333 CheckDeviceNames(device_names
);
336 TEST_F(AudioManagerTest
, EnumerateOutputDevicesAlsa
) {
337 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
339 DVLOG(2) << "Testing AudioManagerAlsa.";
340 CreateAudioManagerForTesting
<AudioManagerAlsa
>();
341 AudioDeviceNames device_names
;
342 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
343 CheckDeviceNames(device_names
);
345 #endif // defined(USE_ALSA)
347 TEST_F(AudioManagerTest
, GetDefaultOutputStreamParameters
) {
348 #if defined(OS_WIN) || defined(OS_MACOSX)
349 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
351 AudioParameters params
= audio_manager_
->GetDefaultOutputStreamParameters();
352 EXPECT_TRUE(params
.IsValid());
353 #endif // defined(OS_WIN) || defined(OS_MACOSX)
356 TEST_F(AudioManagerTest
, GetAssociatedOutputDeviceID
) {
357 #if defined(OS_WIN) || defined(OS_MACOSX)
358 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable() && OutputDevicesAvailable());
360 AudioDeviceNames device_names
;
361 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
362 bool found_an_associated_device
= false;
363 for (AudioDeviceNames::iterator it
= device_names
.begin();
364 it
!= device_names
.end();
366 EXPECT_FALSE(it
->unique_id
.empty());
367 EXPECT_FALSE(it
->device_name
.empty());
368 std::string
output_device_id(
369 audio_manager_
->GetAssociatedOutputDeviceID(it
->unique_id
));
370 if (!output_device_id
.empty()) {
371 DVLOG(2) << it
->unique_id
<< " matches with " << output_device_id
;
372 found_an_associated_device
= true;
376 EXPECT_TRUE(found_an_associated_device
);
377 #endif // defined(OS_WIN) || defined(OS_MACOSX)