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
{
36 AudioManagerTest() : audio_manager_(AudioManager::CreateForTesting()) {
37 // Wait for audio thread initialization to complete. Otherwise the
38 // enumeration type may not have been set yet.
39 base::WaitableEvent
event(false, false);
40 audio_manager_
->GetTaskRunner()->PostTask(FROM_HERE
, base::Bind(
41 &base::WaitableEvent::Signal
, base::Unretained(&event
)));
46 bool SetMMDeviceEnumeration() {
47 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
48 // Windows Wave is used as default if Windows XP was detected =>
49 // return false since MMDevice is not supported on XP.
50 if (amw
->enumeration_type() == AudioManagerWin::kWaveEnumeration
)
53 amw
->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration
);
57 void SetWaveEnumeration() {
58 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
59 amw
->SetEnumerationType(AudioManagerWin::kWaveEnumeration
);
62 std::string
GetDeviceIdFromPCMWaveInAudioInputStream(
63 const std::string
& device_id
) {
64 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
65 AudioParameters
parameters(
66 AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_STEREO
,
67 AudioParameters::kAudioCDSampleRate
, 16,
69 scoped_ptr
<PCMWaveInAudioInputStream
> stream(
70 static_cast<PCMWaveInAudioInputStream
*>(
71 amw
->CreatePCMWaveInAudioInputStream(parameters
, device_id
)));
72 return stream
.get() ? stream
->device_id_
: std::string();
76 // Helper method which verifies that the device list starts with a valid
77 // default record followed by non-default device names.
78 static void CheckDeviceNames(const AudioDeviceNames
& device_names
) {
79 DVLOG(2) << "Got " << device_names
.size() << " audio devices.";
80 if (!device_names
.empty()) {
81 AudioDeviceNames::const_iterator it
= device_names
.begin();
83 // The first device in the list should always be the default device.
84 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName
),
86 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId
), it
->unique_id
);
89 // Other devices should have non-empty name and id and should not contain
90 // default name or id.
91 while (it
!= device_names
.end()) {
92 EXPECT_FALSE(it
->device_name
.empty());
93 EXPECT_FALSE(it
->unique_id
.empty());
94 DVLOG(2) << "Device ID(" << it
->unique_id
95 << "), label: " << it
->device_name
;
96 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName
),
98 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId
),
103 // Log a warning so we can see the status on the build bots. No need to
104 // break the test though since this does successfully test the code and
105 // some failure cases.
106 LOG(WARNING
) << "No input devices detected";
110 bool InputDevicesAvailable() {
111 return audio_manager_
->HasAudioInputDevices();
114 bool OutputDevicesAvailable() {
115 return audio_manager_
->HasAudioOutputDevices();
118 #if defined(USE_ALSA) || defined(USE_PULSEAUDIO)
120 void CreateAudioManagerForTesting() {
121 // Only one AudioManager may exist at a time, so destroy the one we're
122 // currently holding before creating a new one.
123 audio_manager_
.reset();
124 audio_manager_
.reset(T::Create(&fake_audio_log_factory_
));
128 // Synchronously runs the provided callback/closure on the audio thread.
129 void RunOnAudioThread(const base::Closure
& closure
) {
130 if (!audio_manager_
->GetTaskRunner()->BelongsToCurrentThread()) {
131 base::WaitableEvent
event(false, false);
132 audio_manager_
->GetTaskRunner()->PostTask(
134 base::Bind(&AudioManagerTest::RunOnAudioThreadImpl
,
135 base::Unretained(this),
144 void RunOnAudioThreadImpl(const base::Closure
& closure
,
145 base::WaitableEvent
* event
) {
146 DCHECK(audio_manager_
->GetTaskRunner()->BelongsToCurrentThread());
151 FakeAudioLogFactory fake_audio_log_factory_
;
152 scoped_ptr
<AudioManager
> audio_manager_
;
155 // Test that devices can be enumerated.
156 TEST_F(AudioManagerTest
, EnumerateInputDevices
) {
157 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
159 AudioDeviceNames device_names
;
161 base::Bind(&AudioManager::GetAudioInputDeviceNames
,
162 base::Unretained(audio_manager_
.get()),
164 CheckDeviceNames(device_names
);
167 // Test that devices can be enumerated.
168 TEST_F(AudioManagerTest
, EnumerateOutputDevices
) {
169 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
171 AudioDeviceNames device_names
;
173 base::Bind(&AudioManager::GetAudioOutputDeviceNames
,
174 base::Unretained(audio_manager_
.get()),
176 CheckDeviceNames(device_names
);
179 // Run additional tests for Windows since enumeration can be done using
180 // two different APIs. MMDevice is default for Vista and higher and Wave
181 // is default for XP and lower.
184 // Override default enumeration API and force usage of Windows MMDevice.
185 // This test will only run on Windows Vista and higher.
186 TEST_F(AudioManagerTest
, EnumerateInputDevicesWinMMDevice
) {
187 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
189 AudioDeviceNames device_names
;
190 if (!SetMMDeviceEnumeration()) {
191 // Usage of MMDevice will fail on XP and lower.
192 LOG(WARNING
) << "MM device enumeration is not supported.";
195 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
196 CheckDeviceNames(device_names
);
199 TEST_F(AudioManagerTest
, EnumerateOutputDevicesWinMMDevice
) {
200 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
202 AudioDeviceNames device_names
;
203 if (!SetMMDeviceEnumeration()) {
204 // Usage of MMDevice will fail on XP and lower.
205 LOG(WARNING
) << "MM device enumeration is not supported.";
208 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
209 CheckDeviceNames(device_names
);
212 // Override default enumeration API and force usage of Windows Wave.
213 // This test will run on Windows XP, Windows Vista and Windows 7.
214 TEST_F(AudioManagerTest
, EnumerateInputDevicesWinWave
) {
215 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
217 AudioDeviceNames device_names
;
218 SetWaveEnumeration();
219 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
220 CheckDeviceNames(device_names
);
223 TEST_F(AudioManagerTest
, EnumerateOutputDevicesWinWave
) {
224 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
226 AudioDeviceNames device_names
;
227 SetWaveEnumeration();
228 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
229 CheckDeviceNames(device_names
);
232 TEST_F(AudioManagerTest
, WinXPDeviceIdUnchanged
) {
233 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
235 AudioDeviceNames xp_device_names
;
236 SetWaveEnumeration();
237 audio_manager_
->GetAudioInputDeviceNames(&xp_device_names
);
238 CheckDeviceNames(xp_device_names
);
240 // Device ID should remain unchanged, including the default device ID.
241 for (AudioDeviceNames::iterator i
= xp_device_names
.begin();
242 i
!= xp_device_names
.end(); ++i
) {
243 EXPECT_EQ(i
->unique_id
,
244 GetDeviceIdFromPCMWaveInAudioInputStream(i
->unique_id
));
248 TEST_F(AudioManagerTest
, ConvertToWinXPInputDeviceId
) {
249 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
251 if (!SetMMDeviceEnumeration()) {
252 // Usage of MMDevice will fail on XP and lower.
253 LOG(WARNING
) << "MM device enumeration is not supported.";
257 AudioDeviceNames device_names
;
258 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
259 CheckDeviceNames(device_names
);
261 for (AudioDeviceNames::iterator i
= device_names
.begin();
262 i
!= device_names
.end(); ++i
) {
263 std::string converted_id
=
264 GetDeviceIdFromPCMWaveInAudioInputStream(i
->unique_id
);
265 if (i
== device_names
.begin()) {
266 // The first in the list is the default device ID, which should not be
267 // changed when passed to PCMWaveInAudioInputStream.
268 EXPECT_EQ(i
->unique_id
, converted_id
);
270 // MMDevice-style device IDs should be converted to WaveIn-style device
272 EXPECT_NE(i
->unique_id
, converted_id
);
277 #endif // defined(OS_WIN)
279 #if defined(USE_PULSEAUDIO)
280 // On Linux, there are two implementations available and both can
281 // sometimes be tested on a single system. These tests specifically
284 TEST_F(AudioManagerTest
, EnumerateInputDevicesPulseaudio
) {
285 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
287 CreateAudioManagerForTesting
<AudioManagerPulse
>();
288 if (audio_manager_
.get()) {
289 AudioDeviceNames device_names
;
290 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
291 CheckDeviceNames(device_names
);
293 LOG(WARNING
) << "No pulseaudio on this system.";
297 TEST_F(AudioManagerTest
, EnumerateOutputDevicesPulseaudio
) {
298 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
300 CreateAudioManagerForTesting
<AudioManagerPulse
>();
301 if (audio_manager_
.get()) {
302 AudioDeviceNames device_names
;
303 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
304 CheckDeviceNames(device_names
);
306 LOG(WARNING
) << "No pulseaudio on this system.";
309 #endif // defined(USE_PULSEAUDIO)
311 #if defined(USE_ALSA)
312 // On Linux, there are two implementations available and both can
313 // sometimes be tested on a single system. These tests specifically
316 TEST_F(AudioManagerTest
, EnumerateInputDevicesAlsa
) {
317 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
319 DVLOG(2) << "Testing AudioManagerAlsa.";
320 CreateAudioManagerForTesting
<AudioManagerAlsa
>();
321 AudioDeviceNames device_names
;
322 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
323 CheckDeviceNames(device_names
);
326 TEST_F(AudioManagerTest
, EnumerateOutputDevicesAlsa
) {
327 ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
329 DVLOG(2) << "Testing AudioManagerAlsa.";
330 CreateAudioManagerForTesting
<AudioManagerAlsa
>();
331 AudioDeviceNames device_names
;
332 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
333 CheckDeviceNames(device_names
);
335 #endif // defined(USE_ALSA)
337 TEST_F(AudioManagerTest
, GetDefaultOutputStreamParameters
) {
338 #if defined(OS_WIN) || defined(OS_MACOSX)
339 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
341 AudioParameters params
= audio_manager_
->GetDefaultOutputStreamParameters();
342 EXPECT_TRUE(params
.IsValid());
343 #endif // defined(OS_WIN) || defined(OS_MACOSX)
346 TEST_F(AudioManagerTest
, GetAssociatedOutputDeviceID
) {
347 #if defined(OS_WIN) || defined(OS_MACOSX)
348 ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable() && OutputDevicesAvailable());
350 AudioDeviceNames device_names
;
351 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
352 bool found_an_associated_device
= false;
353 for (AudioDeviceNames::iterator it
= device_names
.begin();
354 it
!= device_names
.end();
356 EXPECT_FALSE(it
->unique_id
.empty());
357 EXPECT_FALSE(it
->device_name
.empty());
358 std::string
output_device_id(
359 audio_manager_
->GetAssociatedOutputDeviceID(it
->unique_id
));
360 if (!output_device_id
.empty()) {
361 DVLOG(2) << it
->unique_id
<< " matches with " << output_device_id
;
362 found_an_associated_device
= true;
366 EXPECT_TRUE(found_an_associated_device
);
367 #endif // defined(OS_WIN) || defined(OS_MACOSX)