Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / media / audio / audio_manager_unittest.cc
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.
4
5 #include "base/bind.h"
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/fake_audio_log_factory.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 #if defined(USE_ALSA)
16 #include "media/audio/alsa/audio_manager_alsa.h"
17 #endif  // defined(USE_ALSA)
18
19 #if defined(OS_WIN)
20 #include "base/win/scoped_com_initializer.h"
21 #include "media/audio/win/audio_manager_win.h"
22 #include "media/audio/win/wavein_input_win.h"
23 #endif
24
25 #if defined(USE_PULSEAUDIO)
26 #include "media/audio/pulse/audio_manager_pulse.h"
27 #endif  // defined(USE_PULSEAUDIO)
28
29 namespace media {
30
31 // Test fixture which allows us to override the default enumeration API on
32 // Windows.
33 class AudioManagerTest : public ::testing::Test {
34  protected:
35   AudioManagerTest()
36       : audio_manager_(AudioManager::CreateForTesting())
37 #if defined(OS_WIN)
38       , com_init_(base::win::ScopedCOMInitializer::kMTA)
39 #endif
40   {
41     // Wait for audio thread initialization to complete.  Otherwise the
42     // enumeration type may not have been set yet.
43     base::WaitableEvent event(false, false);
44     audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
45         &base::WaitableEvent::Signal, base::Unretained(&event)));
46     event.Wait();
47   }
48
49   AudioManager* audio_manager() { return audio_manager_.get(); };
50
51 #if defined(OS_WIN)
52   bool SetMMDeviceEnumeration() {
53     AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
54     // Windows Wave is used as default if Windows XP was detected =>
55     // return false since MMDevice is not supported on XP.
56     if (amw->enumeration_type() == AudioManagerWin::kWaveEnumeration)
57       return false;
58
59     amw->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration);
60     return true;
61   }
62
63   void SetWaveEnumeration() {
64     AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
65     amw->SetEnumerationType(AudioManagerWin::kWaveEnumeration);
66   }
67
68   std::string GetDeviceIdFromPCMWaveInAudioInputStream(
69       const std::string& device_id) {
70     AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
71     AudioParameters parameters(
72         AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
73         AudioParameters::kAudioCDSampleRate, 16,
74         1024);
75     scoped_ptr<PCMWaveInAudioInputStream> stream(
76         static_cast<PCMWaveInAudioInputStream*>(
77             amw->CreatePCMWaveInAudioInputStream(parameters, device_id)));
78     return stream.get() ? stream->device_id_ : std::string();
79   }
80 #endif
81
82   // Helper method which verifies that the device list starts with a valid
83   // default record followed by non-default device names.
84   static void CheckDeviceNames(const AudioDeviceNames& device_names) {
85     VLOG(2) << "Got " << device_names.size() << " audio devices.";
86     if (!device_names.empty()) {
87       AudioDeviceNames::const_iterator it = device_names.begin();
88
89       // The first device in the list should always be the default device.
90       EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName),
91                 it->device_name);
92       EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId), it->unique_id);
93       ++it;
94
95       // Other devices should have non-empty name and id and should not contain
96       // default name or id.
97       while (it != device_names.end()) {
98         EXPECT_FALSE(it->device_name.empty());
99         EXPECT_FALSE(it->unique_id.empty());
100         VLOG(2) << "Device ID(" << it->unique_id
101                 << "), label: " << it->device_name;
102         EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName),
103                   it->device_name);
104         EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId),
105                   it->unique_id);
106         ++it;
107       }
108     } else {
109       // Log a warning so we can see the status on the build bots.  No need to
110       // break the test though since this does successfully test the code and
111       // some failure cases.
112       LOG(WARNING) << "No input devices detected";
113     }
114   }
115
116   bool CanRunInputTest() {
117     return audio_manager_->HasAudioInputDevices();
118   }
119
120   bool CanRunOutputTest() {
121     return audio_manager_->HasAudioOutputDevices();
122   }
123
124 #if defined(USE_ALSA) || defined(USE_PULSEAUDIO)
125   template <class T>
126   void CreateAudioManagerForTesting() {
127     // Only one AudioManager may exist at a time, so destroy the one we're
128     // currently holding before creating a new one.
129     audio_manager_.reset();
130     audio_manager_.reset(T::Create(&fake_audio_log_factory_));
131   }
132 #endif
133
134   // Synchronously runs the provided callback/closure on the audio thread.
135   void RunOnAudioThread(const base::Closure& closure) {
136     if (!audio_manager()->GetTaskRunner()->BelongsToCurrentThread()) {
137       base::WaitableEvent event(false, false);
138       audio_manager_->GetTaskRunner()->PostTask(
139           FROM_HERE,
140           base::Bind(&AudioManagerTest::RunOnAudioThreadImpl,
141                      base::Unretained(this),
142                      closure,
143                      &event));
144       event.Wait();
145     } else {
146       closure.Run();
147     }
148   }
149
150   void RunOnAudioThreadImpl(const base::Closure& closure,
151                             base::WaitableEvent* event) {
152     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
153     closure.Run();
154     event->Signal();
155   }
156
157   FakeAudioLogFactory fake_audio_log_factory_;
158   scoped_ptr<AudioManager> audio_manager_;
159
160 #if defined(OS_WIN)
161   // The MMDevice API requires COM to be initialized on the current thread.
162   base::win::ScopedCOMInitializer com_init_;
163 #endif
164 };
165
166 // Test that devices can be enumerated.
167 TEST_F(AudioManagerTest, EnumerateInputDevices) {
168   if (!CanRunInputTest())
169     return;
170
171   AudioDeviceNames device_names;
172   RunOnAudioThread(
173       base::Bind(&AudioManager::GetAudioInputDeviceNames,
174                  base::Unretained(audio_manager()),
175                  &device_names));
176   CheckDeviceNames(device_names);
177 }
178
179 // Test that devices can be enumerated.
180 TEST_F(AudioManagerTest, EnumerateOutputDevices) {
181   if (!CanRunOutputTest())
182     return;
183
184   AudioDeviceNames device_names;
185   RunOnAudioThread(
186       base::Bind(&AudioManager::GetAudioOutputDeviceNames,
187                  base::Unretained(audio_manager()),
188                  &device_names));
189   CheckDeviceNames(device_names);
190 }
191
192 // Run additional tests for Windows since enumeration can be done using
193 // two different APIs. MMDevice is default for Vista and higher and Wave
194 // is default for XP and lower.
195 #if defined(OS_WIN)
196
197 // Override default enumeration API and force usage of Windows MMDevice.
198 // This test will only run on Windows Vista and higher.
199 TEST_F(AudioManagerTest, EnumerateInputDevicesWinMMDevice) {
200   if (!CanRunInputTest())
201     return;
202
203   AudioDeviceNames device_names;
204   if (!SetMMDeviceEnumeration()) {
205     // Usage of MMDevice will fail on XP and lower.
206     LOG(WARNING) << "MM device enumeration is not supported.";
207     return;
208   }
209   audio_manager_->GetAudioInputDeviceNames(&device_names);
210   CheckDeviceNames(device_names);
211 }
212
213 TEST_F(AudioManagerTest, EnumerateOutputDevicesWinMMDevice) {
214   if (!CanRunOutputTest())
215     return;
216
217   AudioDeviceNames device_names;
218   if (!SetMMDeviceEnumeration()) {
219     // Usage of MMDevice will fail on XP and lower.
220     LOG(WARNING) << "MM device enumeration is not supported.";
221     return;
222   }
223   audio_manager_->GetAudioOutputDeviceNames(&device_names);
224   CheckDeviceNames(device_names);
225 }
226
227 // Override default enumeration API and force usage of Windows Wave.
228 // This test will run on Windows XP, Windows Vista and Windows 7.
229 TEST_F(AudioManagerTest, EnumerateInputDevicesWinWave) {
230   if (!CanRunInputTest())
231     return;
232
233   AudioDeviceNames device_names;
234   SetWaveEnumeration();
235   audio_manager_->GetAudioInputDeviceNames(&device_names);
236   CheckDeviceNames(device_names);
237 }
238
239 TEST_F(AudioManagerTest, EnumerateOutputDevicesWinWave) {
240   if (!CanRunOutputTest())
241     return;
242
243   AudioDeviceNames device_names;
244   SetWaveEnumeration();
245   audio_manager_->GetAudioOutputDeviceNames(&device_names);
246   CheckDeviceNames(device_names);
247 }
248
249 TEST_F(AudioManagerTest, WinXPDeviceIdUnchanged) {
250   if (!CanRunInputTest())
251     return;
252
253   AudioDeviceNames xp_device_names;
254   SetWaveEnumeration();
255   audio_manager_->GetAudioInputDeviceNames(&xp_device_names);
256   CheckDeviceNames(xp_device_names);
257
258   // Device ID should remain unchanged, including the default device ID.
259   for (AudioDeviceNames::iterator i = xp_device_names.begin();
260        i != xp_device_names.end(); ++i) {
261     EXPECT_EQ(i->unique_id,
262               GetDeviceIdFromPCMWaveInAudioInputStream(i->unique_id));
263   }
264 }
265
266 TEST_F(AudioManagerTest, ConvertToWinXPInputDeviceId) {
267   if (!CanRunInputTest())
268     return;
269
270   if (!SetMMDeviceEnumeration()) {
271     // Usage of MMDevice will fail on XP and lower.
272     LOG(WARNING) << "MM device enumeration is not supported.";
273     return;
274   }
275
276   AudioDeviceNames device_names;
277   audio_manager_->GetAudioInputDeviceNames(&device_names);
278   CheckDeviceNames(device_names);
279
280   for (AudioDeviceNames::iterator i = device_names.begin();
281        i != device_names.end(); ++i) {
282     std::string converted_id =
283         GetDeviceIdFromPCMWaveInAudioInputStream(i->unique_id);
284     if (i == device_names.begin()) {
285       // The first in the list is the default device ID, which should not be
286       // changed when passed to PCMWaveInAudioInputStream.
287       EXPECT_EQ(i->unique_id, converted_id);
288     } else {
289       // MMDevice-style device IDs should be converted to WaveIn-style device
290       // IDs.
291       EXPECT_NE(i->unique_id, converted_id);
292     }
293   }
294 }
295
296 #endif  // defined(OS_WIN)
297
298 #if defined(USE_PULSEAUDIO)
299 // On Linux, there are two implementations available and both can
300 // sometimes be tested on a single system. These tests specifically
301 // test Pulseaudio.
302
303 TEST_F(AudioManagerTest, EnumerateInputDevicesPulseaudio) {
304   if (!CanRunInputTest())
305     return;
306
307   CreateAudioManagerForTesting<AudioManagerPulse>();
308   if (audio_manager_.get()) {
309     AudioDeviceNames device_names;
310     audio_manager_->GetAudioInputDeviceNames(&device_names);
311     CheckDeviceNames(device_names);
312   } else {
313     LOG(WARNING) << "No pulseaudio on this system.";
314   }
315 }
316
317 TEST_F(AudioManagerTest, EnumerateOutputDevicesPulseaudio) {
318   if (!CanRunOutputTest())
319     return;
320
321   CreateAudioManagerForTesting<AudioManagerPulse>();
322   if (audio_manager_.get()) {
323     AudioDeviceNames device_names;
324     audio_manager_->GetAudioOutputDeviceNames(&device_names);
325     CheckDeviceNames(device_names);
326   } else {
327     LOG(WARNING) << "No pulseaudio on this system.";
328   }
329 }
330 #endif  // defined(USE_PULSEAUDIO)
331
332 #if defined(USE_ALSA)
333 // On Linux, there are two implementations available and both can
334 // sometimes be tested on a single system. These tests specifically
335 // test Alsa.
336
337 TEST_F(AudioManagerTest, EnumerateInputDevicesAlsa) {
338   if (!CanRunInputTest())
339     return;
340
341   VLOG(2) << "Testing AudioManagerAlsa.";
342   CreateAudioManagerForTesting<AudioManagerAlsa>();
343   AudioDeviceNames device_names;
344   audio_manager_->GetAudioInputDeviceNames(&device_names);
345   CheckDeviceNames(device_names);
346 }
347
348 TEST_F(AudioManagerTest, EnumerateOutputDevicesAlsa) {
349   if (!CanRunOutputTest())
350     return;
351
352   VLOG(2) << "Testing AudioManagerAlsa.";
353   CreateAudioManagerForTesting<AudioManagerAlsa>();
354   AudioDeviceNames device_names;
355   audio_manager_->GetAudioOutputDeviceNames(&device_names);
356   CheckDeviceNames(device_names);
357 }
358 #endif  // defined(USE_ALSA)
359
360 TEST_F(AudioManagerTest, GetDefaultOutputStreamParameters) {
361 #if defined(OS_WIN) || defined(OS_MACOSX)
362   if (!CanRunInputTest())
363     return;
364
365   AudioParameters params = audio_manager_->GetDefaultOutputStreamParameters();
366   EXPECT_TRUE(params.IsValid());
367 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
368 }
369
370 TEST_F(AudioManagerTest, GetAssociatedOutputDeviceID) {
371 #if defined(OS_WIN) || defined(OS_MACOSX)
372   if (!CanRunInputTest() || !CanRunOutputTest())
373     return;
374
375   AudioDeviceNames device_names;
376   audio_manager_->GetAudioInputDeviceNames(&device_names);
377   bool found_an_associated_device = false;
378   for (AudioDeviceNames::iterator it = device_names.begin();
379        it != device_names.end();
380        ++it) {
381     EXPECT_FALSE(it->unique_id.empty());
382     EXPECT_FALSE(it->device_name.empty());
383     std::string output_device_id(
384         audio_manager_->GetAssociatedOutputDeviceID(it->unique_id));
385     if (!output_device_id.empty()) {
386       VLOG(2) << it->unique_id << " matches with " << output_device_id;
387       found_an_associated_device = true;
388     }
389   }
390
391   EXPECT_TRUE(found_an_associated_device);
392 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
393 }
394
395 }  // namespace media