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