177953d88f1c714874a1038f8667f65fe5b3e1c4
[platform/framework/web/crosswalk.git] / src / media / audio / android / audio_android_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/android/build_info.h"
6 #include "base/basictypes.h"
7 #include "base/file_util.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/run_loop.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/synchronization/lock.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/test/test_timeouts.h"
16 #include "base/time/time.h"
17 #include "build/build_config.h"
18 #include "media/audio/android/audio_manager_android.h"
19 #include "media/audio/audio_io.h"
20 #include "media/audio/audio_manager_base.h"
21 #include "media/audio/mock_audio_source_callback.h"
22 #include "media/base/decoder_buffer.h"
23 #include "media/base/seekable_buffer.h"
24 #include "media/base/test_data_util.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 using ::testing::_;
29 using ::testing::AtLeast;
30 using ::testing::DoAll;
31 using ::testing::Invoke;
32 using ::testing::NotNull;
33 using ::testing::Return;
34
35 namespace media {
36
37 ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) {
38   if (++*count >= limit) {
39     loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
40   }
41 }
42
43 static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw";
44 static const char kSpeechFile_16b_m_48k[] = "speech_16b_mono_48kHz.raw";
45 static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw";
46 static const char kSpeechFile_16b_m_44k[] = "speech_16b_mono_44kHz.raw";
47
48 static const float kCallbackTestTimeMs = 2000.0;
49 static const int kBitsPerSample = 16;
50 static const int kBytesPerSample = kBitsPerSample / 8;
51
52 // Converts AudioParameters::Format enumerator to readable string.
53 static std::string FormatToString(AudioParameters::Format format) {
54   switch (format) {
55     case AudioParameters::AUDIO_PCM_LINEAR:
56       return std::string("AUDIO_PCM_LINEAR");
57     case AudioParameters::AUDIO_PCM_LOW_LATENCY:
58       return std::string("AUDIO_PCM_LOW_LATENCY");
59     case AudioParameters::AUDIO_FAKE:
60       return std::string("AUDIO_FAKE");
61     case AudioParameters::AUDIO_LAST_FORMAT:
62       return std::string("AUDIO_LAST_FORMAT");
63     default:
64       return std::string();
65   }
66 }
67
68 // Converts ChannelLayout enumerator to readable string. Does not include
69 // multi-channel cases since these layouts are not supported on Android.
70 static std::string LayoutToString(ChannelLayout channel_layout) {
71   switch (channel_layout) {
72     case CHANNEL_LAYOUT_NONE:
73       return std::string("CHANNEL_LAYOUT_NONE");
74     case CHANNEL_LAYOUT_MONO:
75       return std::string("CHANNEL_LAYOUT_MONO");
76     case CHANNEL_LAYOUT_STEREO:
77       return std::string("CHANNEL_LAYOUT_STEREO");
78     case CHANNEL_LAYOUT_UNSUPPORTED:
79     default:
80       return std::string("CHANNEL_LAYOUT_UNSUPPORTED");
81   }
82 }
83
84 static double ExpectedTimeBetweenCallbacks(AudioParameters params) {
85   return (base::TimeDelta::FromMicroseconds(
86               params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
87               static_cast<double>(params.sample_rate()))).InMillisecondsF();
88 }
89
90 // Helper method which verifies that the device list starts with a valid
91 // default device name followed by non-default device names.
92 static void CheckDeviceNames(const AudioDeviceNames& device_names) {
93   VLOG(2) << "Got " << device_names.size() << " audio devices.";
94   if (device_names.empty()) {
95     // Log a warning so we can see the status on the build bots.  No need to
96     // break the test though since this does successfully test the code and
97     // some failure cases.
98     LOG(WARNING) << "No input devices detected";
99     return;
100   }
101
102   AudioDeviceNames::const_iterator it = device_names.begin();
103
104   // The first device in the list should always be the default device.
105   EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName),
106             it->device_name);
107   EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId), it->unique_id);
108   ++it;
109
110   // Other devices should have non-empty name and id and should not contain
111   // default name or id.
112   while (it != device_names.end()) {
113     EXPECT_FALSE(it->device_name.empty());
114     EXPECT_FALSE(it->unique_id.empty());
115     VLOG(2) << "Device ID(" << it->unique_id
116             << "), label: " << it->device_name;
117     EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName),
118               it->device_name);
119     EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId),
120               it->unique_id);
121     ++it;
122   }
123 }
124
125 // We clear the data bus to ensure that the test does not cause noise.
126 static int RealOnMoreData(AudioBus* dest, AudioBuffersState buffers_state) {
127   dest->Zero();
128   return dest->frames();
129 }
130
131 std::ostream& operator<<(std::ostream& os, const AudioParameters& params) {
132   using namespace std;
133   os << endl << "format: " << FormatToString(params.format()) << endl
134      << "channel layout: " << LayoutToString(params.channel_layout()) << endl
135      << "sample rate: " << params.sample_rate() << endl
136      << "bits per sample: " << params.bits_per_sample() << endl
137      << "frames per buffer: " << params.frames_per_buffer() << endl
138      << "channels: " << params.channels() << endl
139      << "bytes per buffer: " << params.GetBytesPerBuffer() << endl
140      << "bytes per second: " << params.GetBytesPerSecond() << endl
141      << "bytes per frame: " << params.GetBytesPerFrame() << endl
142      << "chunk size in ms: " << ExpectedTimeBetweenCallbacks(params) << endl
143      << "echo_canceller: "
144      << (params.effects() & AudioParameters::ECHO_CANCELLER);
145   return os;
146 }
147
148 // Gmock implementation of AudioInputStream::AudioInputCallback.
149 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
150  public:
151   MOCK_METHOD4(OnData,
152                void(AudioInputStream* stream,
153                     const AudioBus* src,
154                     uint32 hardware_delay_bytes,
155                     double volume));
156   MOCK_METHOD1(OnError, void(AudioInputStream* stream));
157 };
158
159 // Implements AudioOutputStream::AudioSourceCallback and provides audio data
160 // by reading from a data file.
161 class FileAudioSource : public AudioOutputStream::AudioSourceCallback {
162  public:
163   explicit FileAudioSource(base::WaitableEvent* event, const std::string& name)
164       : event_(event), pos_(0) {
165     // Reads a test file from media/test/data directory and stores it in
166     // a DecoderBuffer.
167     file_ = ReadTestDataFile(name);
168
169     // Log the name of the file which is used as input for this test.
170     base::FilePath file_path = GetTestDataFilePath(name);
171     VLOG(0) << "Reading from file: " << file_path.value().c_str();
172   }
173
174   virtual ~FileAudioSource() {}
175
176   // AudioOutputStream::AudioSourceCallback implementation.
177
178   // Use samples read from a data file and fill up the audio buffer
179   // provided to us in the callback.
180   virtual int OnMoreData(AudioBus* audio_bus,
181                          AudioBuffersState buffers_state) OVERRIDE {
182     bool stop_playing = false;
183     int max_size =
184         audio_bus->frames() * audio_bus->channels() * kBytesPerSample;
185
186     // Adjust data size and prepare for end signal if file has ended.
187     if (pos_ + max_size > file_size()) {
188       stop_playing = true;
189       max_size = file_size() - pos_;
190     }
191
192     // File data is stored as interleaved 16-bit values. Copy data samples from
193     // the file and deinterleave to match the audio bus format.
194     // FromInterleaved() will zero out any unfilled frames when there is not
195     // sufficient data remaining in the file to fill up the complete frame.
196     int frames = max_size / (audio_bus->channels() * kBytesPerSample);
197     if (max_size) {
198       audio_bus->FromInterleaved(file_->data() + pos_, frames, kBytesPerSample);
199       pos_ += max_size;
200     }
201
202     // Set event to ensure that the test can stop when the file has ended.
203     if (stop_playing)
204       event_->Signal();
205
206     return frames;
207   }
208
209   virtual void OnError(AudioOutputStream* stream) OVERRIDE {}
210
211   int file_size() { return file_->data_size(); }
212
213  private:
214   base::WaitableEvent* event_;
215   int pos_;
216   scoped_refptr<DecoderBuffer> file_;
217
218   DISALLOW_COPY_AND_ASSIGN(FileAudioSource);
219 };
220
221 // Implements AudioInputStream::AudioInputCallback and writes the recorded
222 // audio data to a local output file. Note that this implementation should
223 // only be used for manually invoked and evaluated tests, hence the created
224 // file will not be destroyed after the test is done since the intention is
225 // that it shall be available for off-line analysis.
226 class FileAudioSink : public AudioInputStream::AudioInputCallback {
227  public:
228   explicit FileAudioSink(base::WaitableEvent* event,
229                          const AudioParameters& params,
230                          const std::string& file_name)
231       : event_(event), params_(params) {
232     // Allocate space for ~10 seconds of data.
233     const int kMaxBufferSize = 10 * params.GetBytesPerSecond();
234     buffer_.reset(new media::SeekableBuffer(0, kMaxBufferSize));
235
236     // Open up the binary file which will be written to in the destructor.
237     base::FilePath file_path;
238     EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
239     file_path = file_path.AppendASCII(file_name.c_str());
240     binary_file_ = base::OpenFile(file_path, "wb");
241     DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file.";
242     VLOG(0) << "Writing to file: " << file_path.value().c_str();
243   }
244
245   virtual ~FileAudioSink() {
246     int bytes_written = 0;
247     while (bytes_written < buffer_->forward_capacity()) {
248       const uint8* chunk;
249       int chunk_size;
250
251       // Stop writing if no more data is available.
252       if (!buffer_->GetCurrentChunk(&chunk, &chunk_size))
253         break;
254
255       // Write recorded data chunk to the file and prepare for next chunk.
256       // TODO(henrika): use file_util:: instead.
257       fwrite(chunk, 1, chunk_size, binary_file_);
258       buffer_->Seek(chunk_size);
259       bytes_written += chunk_size;
260     }
261     base::CloseFile(binary_file_);
262   }
263
264   // AudioInputStream::AudioInputCallback implementation.
265   virtual void OnData(AudioInputStream* stream,
266                       const AudioBus* src,
267                       uint32 hardware_delay_bytes,
268                       double volume) OVERRIDE {
269     const int num_samples = src->frames() * src->channels();
270     scoped_ptr<int16> interleaved(new int16[num_samples]);
271     const int bytes_per_sample = sizeof(*interleaved);
272     src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get());
273
274     // Store data data in a temporary buffer to avoid making blocking
275     // fwrite() calls in the audio callback. The complete buffer will be
276     // written to file in the destructor.
277     const int size = bytes_per_sample * num_samples;
278     if (!buffer_->Append((const uint8*)interleaved.get(), size))
279       event_->Signal();
280   }
281
282   virtual void OnError(AudioInputStream* stream) OVERRIDE {}
283
284  private:
285   base::WaitableEvent* event_;
286   AudioParameters params_;
287   scoped_ptr<media::SeekableBuffer> buffer_;
288   FILE* binary_file_;
289
290   DISALLOW_COPY_AND_ASSIGN(FileAudioSink);
291 };
292
293 // Implements AudioInputCallback and AudioSourceCallback to support full
294 // duplex audio where captured samples are played out in loopback after
295 // reading from a temporary FIFO storage.
296 class FullDuplexAudioSinkSource
297     : public AudioInputStream::AudioInputCallback,
298       public AudioOutputStream::AudioSourceCallback {
299  public:
300   explicit FullDuplexAudioSinkSource(const AudioParameters& params)
301       : params_(params),
302         previous_time_(base::TimeTicks::Now()),
303         started_(false) {
304     // Start with a reasonably small FIFO size. It will be increased
305     // dynamically during the test if required.
306     fifo_.reset(new media::SeekableBuffer(0, 2 * params.GetBytesPerBuffer()));
307     buffer_.reset(new uint8[params_.GetBytesPerBuffer()]);
308   }
309
310   virtual ~FullDuplexAudioSinkSource() {}
311
312   // AudioInputStream::AudioInputCallback implementation
313   virtual void OnData(AudioInputStream* stream,
314                       const AudioBus* src,
315                       uint32 hardware_delay_bytes,
316                       double volume) OVERRIDE {
317     const base::TimeTicks now_time = base::TimeTicks::Now();
318     const int diff = (now_time - previous_time_).InMilliseconds();
319
320     EXPECT_EQ(params_.bits_per_sample(), 16);
321     const int num_samples = src->frames() * src->channels();
322     scoped_ptr<int16> interleaved(new int16[num_samples]);
323     const int bytes_per_sample = sizeof(*interleaved);
324     src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get());
325     const int size = bytes_per_sample * num_samples;
326
327     base::AutoLock lock(lock_);
328     if (diff > 1000) {
329       started_ = true;
330       previous_time_ = now_time;
331
332       // Log out the extra delay added by the FIFO. This is a best effort
333       // estimate. We might be +- 10ms off here.
334       int extra_fifo_delay =
335           static_cast<int>(BytesToMilliseconds(fifo_->forward_bytes() + size));
336       DVLOG(1) << extra_fifo_delay;
337     }
338
339     // We add an initial delay of ~1 second before loopback starts to ensure
340     // a stable callback sequence and to avoid initial bursts which might add
341     // to the extra FIFO delay.
342     if (!started_)
343       return;
344
345     // Append new data to the FIFO and extend the size if the max capacity
346     // was exceeded. Flush the FIFO when extended just in case.
347     if (!fifo_->Append((const uint8*)interleaved.get(), size)) {
348       fifo_->set_forward_capacity(2 * fifo_->forward_capacity());
349       fifo_->Clear();
350     }
351   }
352
353   virtual void OnError(AudioInputStream* stream) OVERRIDE {}
354
355   // AudioOutputStream::AudioSourceCallback implementation
356   virtual int OnMoreData(AudioBus* dest,
357                          AudioBuffersState buffers_state) OVERRIDE {
358     const int size_in_bytes =
359         (params_.bits_per_sample() / 8) * dest->frames() * dest->channels();
360     EXPECT_EQ(size_in_bytes, params_.GetBytesPerBuffer());
361
362     base::AutoLock lock(lock_);
363
364     // We add an initial delay of ~1 second before loopback starts to ensure
365     // a stable callback sequences and to avoid initial bursts which might add
366     // to the extra FIFO delay.
367     if (!started_) {
368       dest->Zero();
369       return dest->frames();
370     }
371
372     // Fill up destination with zeros if the FIFO does not contain enough
373     // data to fulfill the request.
374     if (fifo_->forward_bytes() < size_in_bytes) {
375       dest->Zero();
376     } else {
377       fifo_->Read(buffer_.get(), size_in_bytes);
378       dest->FromInterleaved(
379           buffer_.get(), dest->frames(), params_.bits_per_sample() / 8);
380     }
381
382     return dest->frames();
383   }
384
385   virtual void OnError(AudioOutputStream* stream) OVERRIDE {}
386
387  private:
388   // Converts from bytes to milliseconds given number of bytes and existing
389   // audio parameters.
390   double BytesToMilliseconds(int bytes) const {
391     const int frames = bytes / params_.GetBytesPerFrame();
392     return (base::TimeDelta::FromMicroseconds(
393                 frames * base::Time::kMicrosecondsPerSecond /
394                 static_cast<double>(params_.sample_rate()))).InMillisecondsF();
395   }
396
397   AudioParameters params_;
398   base::TimeTicks previous_time_;
399   base::Lock lock_;
400   scoped_ptr<media::SeekableBuffer> fifo_;
401   scoped_ptr<uint8[]> buffer_;
402   bool started_;
403
404   DISALLOW_COPY_AND_ASSIGN(FullDuplexAudioSinkSource);
405 };
406
407 // Test fixture class for tests which only exercise the output path.
408 class AudioAndroidOutputTest : public testing::Test {
409  public:
410   AudioAndroidOutputTest()
411       : loop_(new base::MessageLoopForUI()),
412         audio_manager_(AudioManager::CreateForTesting()),
413         audio_output_stream_(NULL) {
414   }
415
416   virtual ~AudioAndroidOutputTest() {
417   }
418
419  protected:
420   AudioManager* audio_manager() { return audio_manager_.get(); }
421   base::MessageLoopForUI* loop() { return loop_.get(); }
422   const AudioParameters& audio_output_parameters() {
423     return audio_output_parameters_;
424   }
425
426   // Synchronously runs the provided callback/closure on the audio thread.
427   void RunOnAudioThread(const base::Closure& closure) {
428     if (!audio_manager()->GetTaskRunner()->BelongsToCurrentThread()) {
429       base::WaitableEvent event(false, false);
430       audio_manager()->GetTaskRunner()->PostTask(
431           FROM_HERE,
432           base::Bind(&AudioAndroidOutputTest::RunOnAudioThreadImpl,
433                      base::Unretained(this),
434                      closure,
435                      &event));
436       event.Wait();
437     } else {
438       closure.Run();
439     }
440   }
441
442   void RunOnAudioThreadImpl(const base::Closure& closure,
443                             base::WaitableEvent* event) {
444     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
445     closure.Run();
446     event->Signal();
447   }
448
449   void GetDefaultOutputStreamParametersOnAudioThread() {
450     RunOnAudioThread(
451         base::Bind(&AudioAndroidOutputTest::GetDefaultOutputStreamParameters,
452                    base::Unretained(this)));
453   }
454
455   void MakeAudioOutputStreamOnAudioThread(const AudioParameters& params) {
456     RunOnAudioThread(
457         base::Bind(&AudioAndroidOutputTest::MakeOutputStream,
458                    base::Unretained(this),
459                    params));
460   }
461
462   void OpenAndCloseAudioOutputStreamOnAudioThread() {
463     RunOnAudioThread(
464         base::Bind(&AudioAndroidOutputTest::OpenAndClose,
465                    base::Unretained(this)));
466   }
467
468   void OpenAndStartAudioOutputStreamOnAudioThread(
469       AudioOutputStream::AudioSourceCallback* source) {
470     RunOnAudioThread(
471         base::Bind(&AudioAndroidOutputTest::OpenAndStart,
472                    base::Unretained(this),
473                    source));
474   }
475
476   void StopAndCloseAudioOutputStreamOnAudioThread() {
477     RunOnAudioThread(
478         base::Bind(&AudioAndroidOutputTest::StopAndClose,
479                    base::Unretained(this)));
480   }
481
482   double AverageTimeBetweenCallbacks(int num_callbacks) const {
483     return ((end_time_ - start_time_) / static_cast<double>(num_callbacks - 1))
484         .InMillisecondsF();
485   }
486
487   void StartOutputStreamCallbacks(const AudioParameters& params) {
488     double expected_time_between_callbacks_ms =
489         ExpectedTimeBetweenCallbacks(params);
490     const int num_callbacks =
491         (kCallbackTestTimeMs / expected_time_between_callbacks_ms);
492     MakeAudioOutputStreamOnAudioThread(params);
493
494     int count = 0;
495     MockAudioSourceCallback source;
496
497     EXPECT_CALL(source, OnMoreData(NotNull(), _))
498         .Times(AtLeast(num_callbacks))
499         .WillRepeatedly(
500              DoAll(CheckCountAndPostQuitTask(&count, num_callbacks, loop()),
501                    Invoke(RealOnMoreData)));
502     EXPECT_CALL(source, OnError(audio_output_stream_)).Times(0);
503
504     OpenAndStartAudioOutputStreamOnAudioThread(&source);
505
506     start_time_ = base::TimeTicks::Now();
507     loop()->Run();
508     end_time_ = base::TimeTicks::Now();
509
510     StopAndCloseAudioOutputStreamOnAudioThread();
511
512     double average_time_between_callbacks_ms =
513         AverageTimeBetweenCallbacks(num_callbacks);
514     VLOG(0) << "expected time between callbacks: "
515             << expected_time_between_callbacks_ms << " ms";
516     VLOG(0) << "average time between callbacks: "
517             << average_time_between_callbacks_ms << " ms";
518     EXPECT_GE(average_time_between_callbacks_ms,
519               0.70 * expected_time_between_callbacks_ms);
520     EXPECT_LE(average_time_between_callbacks_ms,
521               1.50 * expected_time_between_callbacks_ms);
522   }
523
524   void GetDefaultOutputStreamParameters() {
525     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
526     audio_output_parameters_ =
527         audio_manager()->GetDefaultOutputStreamParameters();
528     EXPECT_TRUE(audio_output_parameters_.IsValid());
529   }
530
531   void MakeOutputStream(const AudioParameters& params) {
532     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
533     audio_output_stream_ = audio_manager()->MakeAudioOutputStream(
534         params, std::string());
535     EXPECT_TRUE(audio_output_stream_);
536   }
537
538   void OpenAndClose() {
539     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
540     EXPECT_TRUE(audio_output_stream_->Open());
541     audio_output_stream_->Close();
542     audio_output_stream_ = NULL;
543   }
544
545   void OpenAndStart(AudioOutputStream::AudioSourceCallback* source) {
546     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
547     EXPECT_TRUE(audio_output_stream_->Open());
548     audio_output_stream_->Start(source);
549   }
550
551   void StopAndClose() {
552     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
553     audio_output_stream_->Stop();
554     audio_output_stream_->Close();
555     audio_output_stream_ = NULL;
556   }
557
558   scoped_ptr<base::MessageLoopForUI> loop_;
559   scoped_ptr<AudioManager> audio_manager_;
560   AudioParameters audio_output_parameters_;
561   AudioOutputStream* audio_output_stream_;
562   base::TimeTicks start_time_;
563   base::TimeTicks end_time_;
564
565  private:
566   DISALLOW_COPY_AND_ASSIGN(AudioAndroidOutputTest);
567 };
568
569 // AudioRecordInputStream should only be created on Jelly Bean and higher. This
570 // ensures we only test against the AudioRecord path when that is satisfied.
571 std::vector<bool> RunAudioRecordInputPathTests() {
572   std::vector<bool> tests;
573   tests.push_back(false);
574   if (base::android::BuildInfo::GetInstance()->sdk_int() >= 16)
575     tests.push_back(true);
576   return tests;
577 }
578
579 // Test fixture class for tests which exercise the input path, or both input and
580 // output paths. It is value-parameterized to test against both the Java
581 // AudioRecord (when true) and native OpenSLES (when false) input paths.
582 class AudioAndroidInputTest : public AudioAndroidOutputTest,
583                               public testing::WithParamInterface<bool> {
584  public:
585   AudioAndroidInputTest() : audio_input_stream_(NULL) {}
586
587  protected:
588   const AudioParameters& audio_input_parameters() {
589     return audio_input_parameters_;
590   }
591
592   AudioParameters GetInputStreamParameters() {
593     GetDefaultInputStreamParametersOnAudioThread();
594
595     // Override the platform effects setting to use the AudioRecord or OpenSLES
596     // path as requested.
597     int effects = GetParam() ? AudioParameters::ECHO_CANCELLER :
598                                AudioParameters::NO_EFFECTS;
599     AudioParameters params(audio_input_parameters().format(),
600                            audio_input_parameters().channel_layout(),
601                            audio_input_parameters().input_channels(),
602                            audio_input_parameters().sample_rate(),
603                            audio_input_parameters().bits_per_sample(),
604                            audio_input_parameters().frames_per_buffer(),
605                            effects);
606     return params;
607   }
608
609   void GetDefaultInputStreamParametersOnAudioThread() {
610      RunOnAudioThread(
611         base::Bind(&AudioAndroidInputTest::GetDefaultInputStreamParameters,
612                    base::Unretained(this)));
613   }
614
615   void MakeAudioInputStreamOnAudioThread(const AudioParameters& params) {
616     RunOnAudioThread(
617         base::Bind(&AudioAndroidInputTest::MakeInputStream,
618                    base::Unretained(this),
619                    params));
620   }
621
622   void OpenAndCloseAudioInputStreamOnAudioThread() {
623     RunOnAudioThread(
624         base::Bind(&AudioAndroidInputTest::OpenAndClose,
625                    base::Unretained(this)));
626   }
627
628   void OpenAndStartAudioInputStreamOnAudioThread(
629       AudioInputStream::AudioInputCallback* sink) {
630     RunOnAudioThread(
631         base::Bind(&AudioAndroidInputTest::OpenAndStart,
632                    base::Unretained(this),
633                    sink));
634   }
635
636   void StopAndCloseAudioInputStreamOnAudioThread() {
637     RunOnAudioThread(
638         base::Bind(&AudioAndroidInputTest::StopAndClose,
639                    base::Unretained(this)));
640   }
641
642   void StartInputStreamCallbacks(const AudioParameters& params) {
643     double expected_time_between_callbacks_ms =
644         ExpectedTimeBetweenCallbacks(params);
645     const int num_callbacks =
646         (kCallbackTestTimeMs / expected_time_between_callbacks_ms);
647
648     MakeAudioInputStreamOnAudioThread(params);
649
650     int count = 0;
651     MockAudioInputCallback sink;
652
653     EXPECT_CALL(sink, OnData(audio_input_stream_, NotNull(), _, _))
654         .Times(AtLeast(num_callbacks))
655         .WillRepeatedly(
656             CheckCountAndPostQuitTask(&count, num_callbacks, loop()));
657     EXPECT_CALL(sink, OnError(audio_input_stream_)).Times(0);
658
659     OpenAndStartAudioInputStreamOnAudioThread(&sink);
660
661     start_time_ = base::TimeTicks::Now();
662     loop()->Run();
663     end_time_ = base::TimeTicks::Now();
664
665     StopAndCloseAudioInputStreamOnAudioThread();
666
667     double average_time_between_callbacks_ms =
668         AverageTimeBetweenCallbacks(num_callbacks);
669     VLOG(0) << "expected time between callbacks: "
670             << expected_time_between_callbacks_ms << " ms";
671     VLOG(0) << "average time between callbacks: "
672             << average_time_between_callbacks_ms << " ms";
673     EXPECT_GE(average_time_between_callbacks_ms,
674               0.70 * expected_time_between_callbacks_ms);
675     EXPECT_LE(average_time_between_callbacks_ms,
676               1.30 * expected_time_between_callbacks_ms);
677   }
678
679   void GetDefaultInputStreamParameters() {
680     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
681     audio_input_parameters_ = audio_manager()->GetInputStreamParameters(
682         AudioManagerBase::kDefaultDeviceId);
683   }
684
685   void MakeInputStream(const AudioParameters& params) {
686     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
687     audio_input_stream_ = audio_manager()->MakeAudioInputStream(
688         params, AudioManagerBase::kDefaultDeviceId);
689     EXPECT_TRUE(audio_input_stream_);
690   }
691
692   void OpenAndClose() {
693     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
694     EXPECT_TRUE(audio_input_stream_->Open());
695     audio_input_stream_->Close();
696     audio_input_stream_ = NULL;
697   }
698
699   void OpenAndStart(AudioInputStream::AudioInputCallback* sink) {
700     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
701     EXPECT_TRUE(audio_input_stream_->Open());
702     audio_input_stream_->Start(sink);
703   }
704
705   void StopAndClose() {
706     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
707     audio_input_stream_->Stop();
708     audio_input_stream_->Close();
709     audio_input_stream_ = NULL;
710   }
711
712   AudioInputStream* audio_input_stream_;
713   AudioParameters audio_input_parameters_;
714
715  private:
716   DISALLOW_COPY_AND_ASSIGN(AudioAndroidInputTest);
717 };
718
719 // Get the default audio input parameters and log the result.
720 TEST_P(AudioAndroidInputTest, GetDefaultInputStreamParameters) {
721   // We don't go through AudioAndroidInputTest::GetInputStreamParameters() here
722   // so that we can log the real (non-overridden) values of the effects.
723   GetDefaultInputStreamParametersOnAudioThread();
724   EXPECT_TRUE(audio_input_parameters().IsValid());
725   VLOG(1) << audio_input_parameters();
726 }
727
728 // Get the default audio output parameters and log the result.
729 TEST_F(AudioAndroidOutputTest, GetDefaultOutputStreamParameters) {
730   GetDefaultOutputStreamParametersOnAudioThread();
731   VLOG(1) << audio_output_parameters();
732 }
733
734 // Verify input device enumeration.
735 TEST_F(AudioAndroidInputTest, GetAudioInputDeviceNames) {
736   if (!audio_manager()->HasAudioInputDevices())
737     return;
738   AudioDeviceNames devices;
739   RunOnAudioThread(
740       base::Bind(&AudioManager::GetAudioInputDeviceNames,
741                  base::Unretained(audio_manager()),
742                  &devices));
743   CheckDeviceNames(devices);
744 }
745
746 // Verify output device enumeration.
747 TEST_F(AudioAndroidOutputTest, GetAudioOutputDeviceNames) {
748   if (!audio_manager()->HasAudioOutputDevices())
749     return;
750   AudioDeviceNames devices;
751   RunOnAudioThread(
752       base::Bind(&AudioManager::GetAudioOutputDeviceNames,
753                  base::Unretained(audio_manager()),
754                  &devices));
755   CheckDeviceNames(devices);
756 }
757
758 // Ensure that a default input stream can be created and closed.
759 TEST_P(AudioAndroidInputTest, CreateAndCloseInputStream) {
760   AudioParameters params = GetInputStreamParameters();
761   MakeAudioInputStreamOnAudioThread(params);
762   RunOnAudioThread(
763       base::Bind(&AudioInputStream::Close,
764                  base::Unretained(audio_input_stream_)));
765 }
766
767 // Ensure that a default output stream can be created and closed.
768 // TODO(henrika): should we also verify that this API changes the audio mode
769 // to communication mode, and calls RegisterHeadsetReceiver, the first time
770 // it is called?
771 TEST_F(AudioAndroidOutputTest, CreateAndCloseOutputStream) {
772   GetDefaultOutputStreamParametersOnAudioThread();
773   MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
774   RunOnAudioThread(
775       base::Bind(&AudioOutputStream::Close,
776                  base::Unretained(audio_output_stream_)));
777 }
778
779 // Ensure that a default input stream can be opened and closed.
780 TEST_P(AudioAndroidInputTest, OpenAndCloseInputStream) {
781   AudioParameters params = GetInputStreamParameters();
782   MakeAudioInputStreamOnAudioThread(params);
783   OpenAndCloseAudioInputStreamOnAudioThread();
784 }
785
786 // Ensure that a default output stream can be opened and closed.
787 TEST_F(AudioAndroidOutputTest, OpenAndCloseOutputStream) {
788   GetDefaultOutputStreamParametersOnAudioThread();
789   MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
790   OpenAndCloseAudioOutputStreamOnAudioThread();
791 }
792
793 // Start input streaming using default input parameters and ensure that the
794 // callback sequence is sane.
795 TEST_P(AudioAndroidInputTest, DISABLED_StartInputStreamCallbacks) {
796   AudioParameters native_params = GetInputStreamParameters();
797   StartInputStreamCallbacks(native_params);
798 }
799
800 // Start input streaming using non default input parameters and ensure that the
801 // callback sequence is sane. The only change we make in this test is to select
802 // a 10ms buffer size instead of the default size.
803 TEST_P(AudioAndroidInputTest,
804        DISABLED_StartInputStreamCallbacksNonDefaultParameters) {
805   AudioParameters native_params = GetInputStreamParameters();
806   AudioParameters params(native_params.format(),
807                          native_params.channel_layout(),
808                          native_params.input_channels(),
809                          native_params.sample_rate(),
810                          native_params.bits_per_sample(),
811                          native_params.sample_rate() / 100,
812                          native_params.effects());
813   StartInputStreamCallbacks(params);
814 }
815
816 // Start output streaming using default output parameters and ensure that the
817 // callback sequence is sane.
818 TEST_F(AudioAndroidOutputTest, StartOutputStreamCallbacks) {
819   GetDefaultOutputStreamParametersOnAudioThread();
820   StartOutputStreamCallbacks(audio_output_parameters());
821 }
822
823 // Start output streaming using non default output parameters and ensure that
824 // the callback sequence is sane. The only change we make in this test is to
825 // select a 10ms buffer size instead of the default size and to open up the
826 // device in mono.
827 // TODO(henrika): possibly add support for more variations.
828 TEST_F(AudioAndroidOutputTest, StartOutputStreamCallbacksNonDefaultParameters) {
829   GetDefaultOutputStreamParametersOnAudioThread();
830   AudioParameters params(audio_output_parameters().format(),
831                          CHANNEL_LAYOUT_MONO,
832                          audio_output_parameters().sample_rate(),
833                          audio_output_parameters().bits_per_sample(),
834                          audio_output_parameters().sample_rate() / 100);
835   StartOutputStreamCallbacks(params);
836 }
837
838 // Play out a PCM file segment in real time and allow the user to verify that
839 // the rendered audio sounds OK.
840 // NOTE: this test requires user interaction and is not designed to run as an
841 // automatized test on bots.
842 TEST_F(AudioAndroidOutputTest, DISABLED_RunOutputStreamWithFileAsSource) {
843   GetDefaultOutputStreamParametersOnAudioThread();
844   VLOG(1) << audio_output_parameters();
845   MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
846
847   std::string file_name;
848   const AudioParameters params = audio_output_parameters();
849   if (params.sample_rate() == 48000 && params.channels() == 2) {
850     file_name = kSpeechFile_16b_s_48k;
851   } else if (params.sample_rate() == 48000 && params.channels() == 1) {
852     file_name = kSpeechFile_16b_m_48k;
853   } else if (params.sample_rate() == 44100 && params.channels() == 2) {
854     file_name = kSpeechFile_16b_s_44k;
855   } else if (params.sample_rate() == 44100 && params.channels() == 1) {
856     file_name = kSpeechFile_16b_m_44k;
857   } else {
858     FAIL() << "This test supports 44.1kHz and 48kHz mono/stereo only.";
859     return;
860   }
861
862   base::WaitableEvent event(false, false);
863   FileAudioSource source(&event, file_name);
864
865   OpenAndStartAudioOutputStreamOnAudioThread(&source);
866   VLOG(0) << ">> Verify that the file is played out correctly...";
867   EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
868   StopAndCloseAudioOutputStreamOnAudioThread();
869 }
870
871 // Start input streaming and run it for ten seconds while recording to a
872 // local audio file.
873 // NOTE: this test requires user interaction and is not designed to run as an
874 // automatized test on bots.
875 TEST_P(AudioAndroidInputTest, DISABLED_RunSimplexInputStreamWithFileAsSink) {
876   AudioParameters params = GetInputStreamParameters();
877   VLOG(1) << params;
878   MakeAudioInputStreamOnAudioThread(params);
879
880   std::string file_name = base::StringPrintf("out_simplex_%d_%d_%d.pcm",
881                                              params.sample_rate(),
882                                              params.frames_per_buffer(),
883                                              params.channels());
884
885   base::WaitableEvent event(false, false);
886   FileAudioSink sink(&event, params, file_name);
887
888   OpenAndStartAudioInputStreamOnAudioThread(&sink);
889   VLOG(0) << ">> Speak into the microphone to record audio...";
890   EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
891   StopAndCloseAudioInputStreamOnAudioThread();
892 }
893
894 // Same test as RunSimplexInputStreamWithFileAsSink but this time output
895 // streaming is active as well (reads zeros only).
896 // NOTE: this test requires user interaction and is not designed to run as an
897 // automatized test on bots.
898 TEST_P(AudioAndroidInputTest, DISABLED_RunDuplexInputStreamWithFileAsSink) {
899   AudioParameters in_params = GetInputStreamParameters();
900   VLOG(1) << in_params;
901   MakeAudioInputStreamOnAudioThread(in_params);
902
903   GetDefaultOutputStreamParametersOnAudioThread();
904   VLOG(1) << audio_output_parameters();
905   MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
906
907   std::string file_name = base::StringPrintf("out_duplex_%d_%d_%d.pcm",
908                                              in_params.sample_rate(),
909                                              in_params.frames_per_buffer(),
910                                              in_params.channels());
911
912   base::WaitableEvent event(false, false);
913   FileAudioSink sink(&event, in_params, file_name);
914   MockAudioSourceCallback source;
915
916   EXPECT_CALL(source, OnMoreData(NotNull(), _))
917       .WillRepeatedly(Invoke(RealOnMoreData));
918   EXPECT_CALL(source, OnError(audio_output_stream_)).Times(0);
919
920   OpenAndStartAudioInputStreamOnAudioThread(&sink);
921   OpenAndStartAudioOutputStreamOnAudioThread(&source);
922   VLOG(0) << ">> Speak into the microphone to record audio";
923   EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
924   StopAndCloseAudioOutputStreamOnAudioThread();
925   StopAndCloseAudioInputStreamOnAudioThread();
926 }
927
928 // Start audio in both directions while feeding captured data into a FIFO so
929 // it can be read directly (in loopback) by the render side. A small extra
930 // delay will be added by the FIFO and an estimate of this delay will be
931 // printed out during the test.
932 // NOTE: this test requires user interaction and is not designed to run as an
933 // automatized test on bots.
934 TEST_P(AudioAndroidInputTest,
935        DISABLED_RunSymmetricInputAndOutputStreamsInFullDuplex) {
936   // Get native audio parameters for the input side.
937   AudioParameters default_input_params = GetInputStreamParameters();
938
939   // Modify the parameters so that both input and output can use the same
940   // parameters by selecting 10ms as buffer size. This will also ensure that
941   // the output stream will be a mono stream since mono is default for input
942   // audio on Android.
943   AudioParameters io_params(default_input_params.format(),
944                             default_input_params.channel_layout(),
945                             ChannelLayoutToChannelCount(
946                                 default_input_params.channel_layout()),
947                             default_input_params.sample_rate(),
948                             default_input_params.bits_per_sample(),
949                             default_input_params.sample_rate() / 100,
950                             default_input_params.effects());
951   VLOG(1) << io_params;
952
953   // Create input and output streams using the common audio parameters.
954   MakeAudioInputStreamOnAudioThread(io_params);
955   MakeAudioOutputStreamOnAudioThread(io_params);
956
957   FullDuplexAudioSinkSource full_duplex(io_params);
958
959   // Start a full duplex audio session and print out estimates of the extra
960   // delay we should expect from the FIFO. If real-time delay measurements are
961   // performed, the result should be reduced by this extra delay since it is
962   // something that has been added by the test.
963   OpenAndStartAudioInputStreamOnAudioThread(&full_duplex);
964   OpenAndStartAudioOutputStreamOnAudioThread(&full_duplex);
965   VLOG(1) << "HINT: an estimate of the extra FIFO delay will be updated "
966           << "once per second during this test.";
967   VLOG(0) << ">> Speak into the mic and listen to the audio in loopback...";
968   fflush(stdout);
969   base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
970   printf("\n");
971   StopAndCloseAudioOutputStreamOnAudioThread();
972   StopAndCloseAudioInputStreamOnAudioThread();
973 }
974
975 INSTANTIATE_TEST_CASE_P(AudioAndroidInputTest, AudioAndroidInputTest,
976     testing::ValuesIn(RunAudioRecordInputPathTests()));
977
978 }  // namespace media