Home | History | Annotate | Download | only in android
      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/files/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().sample_rate(),
    602                            audio_input_parameters().bits_per_sample(),
    603                            audio_input_parameters().frames_per_buffer(),
    604                            effects);
    605     return params;
    606   }
    607 
    608   void GetDefaultInputStreamParametersOnAudioThread() {
    609      RunOnAudioThread(
    610         base::Bind(&AudioAndroidInputTest::GetDefaultInputStreamParameters,
    611                    base::Unretained(this)));
    612   }
    613 
    614   void MakeAudioInputStreamOnAudioThread(const AudioParameters& params) {
    615     RunOnAudioThread(
    616         base::Bind(&AudioAndroidInputTest::MakeInputStream,
    617                    base::Unretained(this),
    618                    params));
    619   }
    620 
    621   void OpenAndCloseAudioInputStreamOnAudioThread() {
    622     RunOnAudioThread(
    623         base::Bind(&AudioAndroidInputTest::OpenAndClose,
    624                    base::Unretained(this)));
    625   }
    626 
    627   void OpenAndStartAudioInputStreamOnAudioThread(
    628       AudioInputStream::AudioInputCallback* sink) {
    629     RunOnAudioThread(
    630         base::Bind(&AudioAndroidInputTest::OpenAndStart,
    631                    base::Unretained(this),
    632                    sink));
    633   }
    634 
    635   void StopAndCloseAudioInputStreamOnAudioThread() {
    636     RunOnAudioThread(
    637         base::Bind(&AudioAndroidInputTest::StopAndClose,
    638                    base::Unretained(this)));
    639   }
    640 
    641   void StartInputStreamCallbacks(const AudioParameters& params) {
    642     double expected_time_between_callbacks_ms =
    643         ExpectedTimeBetweenCallbacks(params);
    644     const int num_callbacks =
    645         (kCallbackTestTimeMs / expected_time_between_callbacks_ms);
    646 
    647     MakeAudioInputStreamOnAudioThread(params);
    648 
    649     int count = 0;
    650     MockAudioInputCallback sink;
    651 
    652     EXPECT_CALL(sink, OnData(audio_input_stream_, NotNull(), _, _))
    653         .Times(AtLeast(num_callbacks))
    654         .WillRepeatedly(
    655             CheckCountAndPostQuitTask(&count, num_callbacks, loop()));
    656     EXPECT_CALL(sink, OnError(audio_input_stream_)).Times(0);
    657 
    658     OpenAndStartAudioInputStreamOnAudioThread(&sink);
    659 
    660     start_time_ = base::TimeTicks::Now();
    661     loop()->Run();
    662     end_time_ = base::TimeTicks::Now();
    663 
    664     StopAndCloseAudioInputStreamOnAudioThread();
    665 
    666     double average_time_between_callbacks_ms =
    667         AverageTimeBetweenCallbacks(num_callbacks);
    668     VLOG(0) << "expected time between callbacks: "
    669             << expected_time_between_callbacks_ms << " ms";
    670     VLOG(0) << "average time between callbacks: "
    671             << average_time_between_callbacks_ms << " ms";
    672     EXPECT_GE(average_time_between_callbacks_ms,
    673               0.70 * expected_time_between_callbacks_ms);
    674     EXPECT_LE(average_time_between_callbacks_ms,
    675               1.30 * expected_time_between_callbacks_ms);
    676   }
    677 
    678   void GetDefaultInputStreamParameters() {
    679     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    680     audio_input_parameters_ = audio_manager()->GetInputStreamParameters(
    681         AudioManagerBase::kDefaultDeviceId);
    682   }
    683 
    684   void MakeInputStream(const AudioParameters& params) {
    685     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    686     audio_input_stream_ = audio_manager()->MakeAudioInputStream(
    687         params, AudioManagerBase::kDefaultDeviceId);
    688     EXPECT_TRUE(audio_input_stream_);
    689   }
    690 
    691   void OpenAndClose() {
    692     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    693     EXPECT_TRUE(audio_input_stream_->Open());
    694     audio_input_stream_->Close();
    695     audio_input_stream_ = NULL;
    696   }
    697 
    698   void OpenAndStart(AudioInputStream::AudioInputCallback* sink) {
    699     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    700     EXPECT_TRUE(audio_input_stream_->Open());
    701     audio_input_stream_->Start(sink);
    702   }
    703 
    704   void StopAndClose() {
    705     DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
    706     audio_input_stream_->Stop();
    707     audio_input_stream_->Close();
    708     audio_input_stream_ = NULL;
    709   }
    710 
    711   AudioInputStream* audio_input_stream_;
    712   AudioParameters audio_input_parameters_;
    713 
    714  private:
    715   DISALLOW_COPY_AND_ASSIGN(AudioAndroidInputTest);
    716 };
    717 
    718 // Get the default audio input parameters and log the result.
    719 TEST_P(AudioAndroidInputTest, GetDefaultInputStreamParameters) {
    720   // We don't go through AudioAndroidInputTest::GetInputStreamParameters() here
    721   // so that we can log the real (non-overridden) values of the effects.
    722   GetDefaultInputStreamParametersOnAudioThread();
    723   EXPECT_TRUE(audio_input_parameters().IsValid());
    724   VLOG(1) << audio_input_parameters();
    725 }
    726 
    727 // Get the default audio output parameters and log the result.
    728 TEST_F(AudioAndroidOutputTest, GetDefaultOutputStreamParameters) {
    729   GetDefaultOutputStreamParametersOnAudioThread();
    730   VLOG(1) << audio_output_parameters();
    731 }
    732 
    733 // Verify input device enumeration.
    734 TEST_F(AudioAndroidInputTest, GetAudioInputDeviceNames) {
    735   if (!audio_manager()->HasAudioInputDevices())
    736     return;
    737   AudioDeviceNames devices;
    738   RunOnAudioThread(
    739       base::Bind(&AudioManager::GetAudioInputDeviceNames,
    740                  base::Unretained(audio_manager()),
    741                  &devices));
    742   CheckDeviceNames(devices);
    743 }
    744 
    745 // Verify output device enumeration.
    746 TEST_F(AudioAndroidOutputTest, GetAudioOutputDeviceNames) {
    747   if (!audio_manager()->HasAudioOutputDevices())
    748     return;
    749   AudioDeviceNames devices;
    750   RunOnAudioThread(
    751       base::Bind(&AudioManager::GetAudioOutputDeviceNames,
    752                  base::Unretained(audio_manager()),
    753                  &devices));
    754   CheckDeviceNames(devices);
    755 }
    756 
    757 // Ensure that a default input stream can be created and closed.
    758 TEST_P(AudioAndroidInputTest, CreateAndCloseInputStream) {
    759   AudioParameters params = GetInputStreamParameters();
    760   MakeAudioInputStreamOnAudioThread(params);
    761   RunOnAudioThread(
    762       base::Bind(&AudioInputStream::Close,
    763                  base::Unretained(audio_input_stream_)));
    764 }
    765 
    766 // Ensure that a default output stream can be created and closed.
    767 // TODO(henrika): should we also verify that this API changes the audio mode
    768 // to communication mode, and calls RegisterHeadsetReceiver, the first time
    769 // it is called?
    770 TEST_F(AudioAndroidOutputTest, CreateAndCloseOutputStream) {
    771   GetDefaultOutputStreamParametersOnAudioThread();
    772   MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
    773   RunOnAudioThread(
    774       base::Bind(&AudioOutputStream::Close,
    775                  base::Unretained(audio_output_stream_)));
    776 }
    777 
    778 // Ensure that a default input stream can be opened and closed.
    779 TEST_P(AudioAndroidInputTest, OpenAndCloseInputStream) {
    780   AudioParameters params = GetInputStreamParameters();
    781   MakeAudioInputStreamOnAudioThread(params);
    782   OpenAndCloseAudioInputStreamOnAudioThread();
    783 }
    784 
    785 // Ensure that a default output stream can be opened and closed.
    786 TEST_F(AudioAndroidOutputTest, OpenAndCloseOutputStream) {
    787   GetDefaultOutputStreamParametersOnAudioThread();
    788   MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
    789   OpenAndCloseAudioOutputStreamOnAudioThread();
    790 }
    791 
    792 // Start input streaming using default input parameters and ensure that the
    793 // callback sequence is sane.
    794 TEST_P(AudioAndroidInputTest, DISABLED_StartInputStreamCallbacks) {
    795   AudioParameters native_params = GetInputStreamParameters();
    796   StartInputStreamCallbacks(native_params);
    797 }
    798 
    799 // Start input streaming using non default input parameters and ensure that the
    800 // callback sequence is sane. The only change we make in this test is to select
    801 // a 10ms buffer size instead of the default size.
    802 TEST_P(AudioAndroidInputTest,
    803        DISABLED_StartInputStreamCallbacksNonDefaultParameters) {
    804   AudioParameters native_params = GetInputStreamParameters();
    805   AudioParameters params(native_params.format(),
    806                          native_params.channel_layout(),
    807                          native_params.sample_rate(),
    808                          native_params.bits_per_sample(),
    809                          native_params.sample_rate() / 100,
    810                          native_params.effects());
    811   StartInputStreamCallbacks(params);
    812 }
    813 
    814 
    815 #if defined(__aarch64__)
    816 // Disable StartOutputStreamCallbacks and
    817 // StartOutputStreamCallbacksNonDefaultParameters on Arm64: crbug.com/418029
    818 #define MAYBE_StartOutputStreamCallbacks DISABLED_StartOutputStreamCallbacks
    819 #define MAYBE_StartOutputStreamCallbacksNonDefaultParameters  \
    820     DISABLED_StartOutputStreamCallbacksNonDefaultParameters
    821 #else
    822 #define MAYBE_StartOutputStreamCallbacks StartOutputStreamCallbacks
    823 #define MAYBE_StartOutputStreamCallbacksNonDefaultParameters  \
    824     StartOutputStreamCallbacksNonDefaultParameters
    825 #endif
    826 
    827 
    828 // Start output streaming using default output parameters and ensure that the
    829 // callback sequence is sane.
    830 TEST_F(AudioAndroidOutputTest, MAYBE_StartOutputStreamCallbacks) {
    831   GetDefaultOutputStreamParametersOnAudioThread();
    832   StartOutputStreamCallbacks(audio_output_parameters());
    833 }
    834 
    835 // Start output streaming using non default output parameters and ensure that
    836 // the callback sequence is sane. The only change we make in this test is to
    837 // select a 10ms buffer size instead of the default size and to open up the
    838 // device in mono.
    839 // TODO(henrika): possibly add support for more variations.
    840 TEST_F(AudioAndroidOutputTest,
    841        MAYBE_StartOutputStreamCallbacksNonDefaultParameters) {
    842   GetDefaultOutputStreamParametersOnAudioThread();
    843   AudioParameters params(audio_output_parameters().format(),
    844                          CHANNEL_LAYOUT_MONO,
    845                          audio_output_parameters().sample_rate(),
    846                          audio_output_parameters().bits_per_sample(),
    847                          audio_output_parameters().sample_rate() / 100);
    848   StartOutputStreamCallbacks(params);
    849 }
    850 
    851 // Play out a PCM file segment in real time and allow the user to verify that
    852 // the rendered audio sounds OK.
    853 // NOTE: this test requires user interaction and is not designed to run as an
    854 // automatized test on bots.
    855 TEST_F(AudioAndroidOutputTest, DISABLED_RunOutputStreamWithFileAsSource) {
    856   GetDefaultOutputStreamParametersOnAudioThread();
    857   VLOG(1) << audio_output_parameters();
    858   MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
    859 
    860   std::string file_name;
    861   const AudioParameters params = audio_output_parameters();
    862   if (params.sample_rate() == 48000 && params.channels() == 2) {
    863     file_name = kSpeechFile_16b_s_48k;
    864   } else if (params.sample_rate() == 48000 && params.channels() == 1) {
    865     file_name = kSpeechFile_16b_m_48k;
    866   } else if (params.sample_rate() == 44100 && params.channels() == 2) {
    867     file_name = kSpeechFile_16b_s_44k;
    868   } else if (params.sample_rate() == 44100 && params.channels() == 1) {
    869     file_name = kSpeechFile_16b_m_44k;
    870   } else {
    871     FAIL() << "This test supports 44.1kHz and 48kHz mono/stereo only.";
    872     return;
    873   }
    874 
    875   base::WaitableEvent event(false, false);
    876   FileAudioSource source(&event, file_name);
    877 
    878   OpenAndStartAudioOutputStreamOnAudioThread(&source);
    879   VLOG(0) << ">> Verify that the file is played out correctly...";
    880   EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
    881   StopAndCloseAudioOutputStreamOnAudioThread();
    882 }
    883 
    884 // Start input streaming and run it for ten seconds while recording to a
    885 // local audio file.
    886 // NOTE: this test requires user interaction and is not designed to run as an
    887 // automatized test on bots.
    888 TEST_P(AudioAndroidInputTest, DISABLED_RunSimplexInputStreamWithFileAsSink) {
    889   AudioParameters params = GetInputStreamParameters();
    890   VLOG(1) << params;
    891   MakeAudioInputStreamOnAudioThread(params);
    892 
    893   std::string file_name = base::StringPrintf("out_simplex_%d_%d_%d.pcm",
    894                                              params.sample_rate(),
    895                                              params.frames_per_buffer(),
    896                                              params.channels());
    897 
    898   base::WaitableEvent event(false, false);
    899   FileAudioSink sink(&event, params, file_name);
    900 
    901   OpenAndStartAudioInputStreamOnAudioThread(&sink);
    902   VLOG(0) << ">> Speak into the microphone to record audio...";
    903   EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
    904   StopAndCloseAudioInputStreamOnAudioThread();
    905 }
    906 
    907 // Same test as RunSimplexInputStreamWithFileAsSink but this time output
    908 // streaming is active as well (reads zeros only).
    909 // NOTE: this test requires user interaction and is not designed to run as an
    910 // automatized test on bots.
    911 TEST_P(AudioAndroidInputTest, DISABLED_RunDuplexInputStreamWithFileAsSink) {
    912   AudioParameters in_params = GetInputStreamParameters();
    913   VLOG(1) << in_params;
    914   MakeAudioInputStreamOnAudioThread(in_params);
    915 
    916   GetDefaultOutputStreamParametersOnAudioThread();
    917   VLOG(1) << audio_output_parameters();
    918   MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
    919 
    920   std::string file_name = base::StringPrintf("out_duplex_%d_%d_%d.pcm",
    921                                              in_params.sample_rate(),
    922                                              in_params.frames_per_buffer(),
    923                                              in_params.channels());
    924 
    925   base::WaitableEvent event(false, false);
    926   FileAudioSink sink(&event, in_params, file_name);
    927   MockAudioSourceCallback source;
    928 
    929   EXPECT_CALL(source, OnMoreData(NotNull(), _))
    930       .WillRepeatedly(Invoke(RealOnMoreData));
    931   EXPECT_CALL(source, OnError(audio_output_stream_)).Times(0);
    932 
    933   OpenAndStartAudioInputStreamOnAudioThread(&sink);
    934   OpenAndStartAudioOutputStreamOnAudioThread(&source);
    935   VLOG(0) << ">> Speak into the microphone to record audio";
    936   EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
    937   StopAndCloseAudioOutputStreamOnAudioThread();
    938   StopAndCloseAudioInputStreamOnAudioThread();
    939 }
    940 
    941 // Start audio in both directions while feeding captured data into a FIFO so
    942 // it can be read directly (in loopback) by the render side. A small extra
    943 // delay will be added by the FIFO and an estimate of this delay will be
    944 // printed out during the test.
    945 // NOTE: this test requires user interaction and is not designed to run as an
    946 // automatized test on bots.
    947 TEST_P(AudioAndroidInputTest,
    948        DISABLED_RunSymmetricInputAndOutputStreamsInFullDuplex) {
    949   // Get native audio parameters for the input side.
    950   AudioParameters default_input_params = GetInputStreamParameters();
    951 
    952   // Modify the parameters so that both input and output can use the same
    953   // parameters by selecting 10ms as buffer size. This will also ensure that
    954   // the output stream will be a mono stream since mono is default for input
    955   // audio on Android.
    956   AudioParameters io_params(default_input_params.format(),
    957                             default_input_params.channel_layout(),
    958                             ChannelLayoutToChannelCount(
    959                                 default_input_params.channel_layout()),
    960                             default_input_params.sample_rate(),
    961                             default_input_params.bits_per_sample(),
    962                             default_input_params.sample_rate() / 100,
    963                             default_input_params.effects());
    964   VLOG(1) << io_params;
    965 
    966   // Create input and output streams using the common audio parameters.
    967   MakeAudioInputStreamOnAudioThread(io_params);
    968   MakeAudioOutputStreamOnAudioThread(io_params);
    969 
    970   FullDuplexAudioSinkSource full_duplex(io_params);
    971 
    972   // Start a full duplex audio session and print out estimates of the extra
    973   // delay we should expect from the FIFO. If real-time delay measurements are
    974   // performed, the result should be reduced by this extra delay since it is
    975   // something that has been added by the test.
    976   OpenAndStartAudioInputStreamOnAudioThread(&full_duplex);
    977   OpenAndStartAudioOutputStreamOnAudioThread(&full_duplex);
    978   VLOG(1) << "HINT: an estimate of the extra FIFO delay will be updated "
    979           << "once per second during this test.";
    980   VLOG(0) << ">> Speak into the mic and listen to the audio in loopback...";
    981   fflush(stdout);
    982   base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
    983   printf("\n");
    984   StopAndCloseAudioOutputStreamOnAudioThread();
    985   StopAndCloseAudioInputStreamOnAudioThread();
    986 }
    987 
    988 INSTANTIATE_TEST_CASE_P(AudioAndroidInputTest, AudioAndroidInputTest,
    989     testing::ValuesIn(RunAudioRecordInputPathTests()));
    990 
    991 }  // namespace media
    992