1474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org/*
2474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org *
4474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org *  Use of this source code is governed by a BSD-style license
5474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org *  that can be found in the LICENSE file in the root of the source
6474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org *  tree. An additional intellectual property rights grant can be found
7474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org *  in the file PATENTS.  All contributing project authors may
8474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org */
10474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
11ee369e4277e48624bb557f0264644ed19a40dd67henrika#include <algorithm>
12ee369e4277e48624bb557f0264644ed19a40dd67henrika#include <limits>
1380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org#include <list>
1480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org#include <numeric>
15ee369e4277e48624bb557f0264644ed19a40dd67henrika#include <string>
16ee369e4277e48624bb557f0264644ed19a40dd67henrika#include <vector>
1780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
18474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#include "testing/gmock/include/gmock/gmock.h"
19474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
20b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika#include "webrtc/base/arraysize.h"
2180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org#include "webrtc/base/criticalsection.h"
22dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting#include "webrtc/base/format_macros.h"
23474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#include "webrtc/base/scoped_ptr.h"
2426b08605e2b99136fcc1cab0800234f469d6e236Peter Boström#include "webrtc/base/scoped_ref_ptr.h"
25b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika#include "webrtc/modules/audio_device/android/audio_common.h"
26b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika#include "webrtc/modules/audio_device/android/audio_manager.h"
27523183b4aa2118b483967fccfdbe5b848c3eb18dhenrika#include "webrtc/modules/audio_device/android/build_info.h"
28474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#include "webrtc/modules/audio_device/android/ensure_initialized.h"
29474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#include "webrtc/modules/audio_device/audio_device_impl.h"
30474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#include "webrtc/modules/audio_device/include/audio_device.h"
3198f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/clock.h"
3298f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/event_wrapper.h"
3398f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/sleep.h"
34474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#include "webrtc/test/testsupport/fileutils.h"
35474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
36474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing std::cout;
37474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing std::endl;
38474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing ::testing::_;
39474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing ::testing::AtLeast;
40474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing ::testing::Gt;
41474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing ::testing::Invoke;
42474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing ::testing::NiceMock;
43474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing ::testing::NotNull;
44474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing ::testing::Return;
45474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgusing ::testing::TestWithParam;
46474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
4780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// #define ENABLE_DEBUG_PRINTF
4880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org#ifdef ENABLE_DEBUG_PRINTF
4980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org#define PRINTD(...) fprintf(stderr, __VA_ARGS__);
50474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#else
5180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org#define PRINTD(...) ((void)0)
52474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#endif
5380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org#define PRINT(...) fprintf(stderr, __VA_ARGS__);
54474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
55474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgnamespace webrtc {
56474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
57474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// Number of callbacks (input or output) the tests waits for before we set
58474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// an event indicating that the test was OK.
59dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kNumCallbacks = 10;
60474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// Max amount of time we wait for an event to be set while counting callbacks.
61474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgstatic const int kTestTimeOutInMilliseconds = 10 * 1000;
62474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// Average number of audio callbacks per second assuming 10ms packet size.
63dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kNumCallbacksPerSecond = 100;
64474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// Play out a test file during this time (unit is in seconds).
6580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgstatic const int kFilePlayTimeInSec = 5;
66dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kBitsPerSample = 16;
67dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kBytesPerSample = kBitsPerSample / 8;
6880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Run the full-duplex test during this time (unit is in seconds).
6980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Note that first |kNumIgnoreFirstCallbacks| are ignored.
708324b525dce2c502bbd24b3946bbae207645cde9henrikastatic const int kFullDuplexTimeInSec = 5;
7180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Wait for the callback sequence to stabilize by ignoring this amount of the
7280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// initial callbacks (avoids initial FIFO access).
7380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Only used in the RunPlayoutAndRecordingInFullDuplex test.
74dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingstatic const size_t kNumIgnoreFirstCallbacks = 50;
7580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Sets the number of impulses per second in the latency test.
7680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgstatic const int kImpulseFrequencyInHz = 1;
7780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Length of round-trip latency measurements. Number of transmitted impulses
7880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// is kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1.
7980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgstatic const int kMeasureLatencyTimeInSec = 11;
8080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Utilized in round-trip latency measurements to avoid capturing noise samples.
81b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikastatic const int kImpulseThreshold = 1000;
8280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgstatic const char kTag[] = "[..........] ";
83474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
84474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.orgenum TransportType {
85474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  kPlayout = 0x1,
86474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  kRecording = 0x2,
87474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org};
88474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
8980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Interface for processing the audio stream. Real implementations can e.g.
9080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// run audio in loopback, read audio from a file or perform latency
9180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// measurements.
9280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgclass AudioStreamInterface {
93474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org public:
94dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  virtual void Write(const void* source, size_t num_frames) = 0;
95dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  virtual void Read(void* destination, size_t num_frames) = 0;
9680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org protected:
9780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  virtual ~AudioStreamInterface() {}
9880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org};
9980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
10080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Reads audio samples from a PCM file where the file is stored in memory at
10180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// construction.
10280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgclass FileAudioStream : public AudioStreamInterface {
10380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org public:
10480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  FileAudioStream(
105dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      size_t num_callbacks, const std::string& file_name, int sample_rate)
10680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      : file_size_in_bytes_(0),
10780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        sample_rate_(sample_rate),
10880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        file_pos_(0) {
109474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    file_size_in_bytes_ = test::GetFileSize(file_name);
110474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    sample_rate_ = sample_rate;
11180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    EXPECT_GE(file_size_in_callbacks(), num_callbacks)
11274d4792af574a90c4a13b3e57195883e2a546cbehenrika@webrtc.org        << "Size of test file is not large enough to last during the test.";
113dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const size_t num_16bit_samples =
114474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org        test::GetFileSize(file_name) / kBytesPerSample;
115474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    file_.reset(new int16_t[num_16bit_samples]);
116474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    FILE* audio_file = fopen(file_name.c_str(), "rb");
117474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_NE(audio_file, nullptr);
118dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    size_t num_samples_read = fread(
119474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org        file_.get(), sizeof(int16_t), num_16bit_samples, audio_file);
120474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(num_samples_read, num_16bit_samples);
121474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    fclose(audio_file);
122474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
123474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
12480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // AudioStreamInterface::Write() is not implemented.
125dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Write(const void* source, size_t num_frames) override {}
12680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
12780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Read samples from file stored in memory (at construction) and copy
12880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // |num_frames| (<=> 10ms) to the |destination| byte buffer.
129dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Read(void* destination, size_t num_frames) override {
13080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    memcpy(destination,
13180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org           static_cast<int16_t*> (&file_[file_pos_]),
13280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org           num_frames * sizeof(int16_t));
13380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    file_pos_ += num_frames;
13480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
13580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
13680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  int file_size_in_seconds() const {
137dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    return static_cast<int>(
138dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting        file_size_in_bytes_ / (kBytesPerSample * sample_rate_));
13980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
140dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t file_size_in_callbacks() const {
14180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    return file_size_in_seconds() * kNumCallbacksPerSecond;
14280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
14380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
14480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org private:
145dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t file_size_in_bytes_;
14680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  int sample_rate_;
14780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  rtc::scoped_ptr<int16_t[]> file_;
148dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t file_pos_;
14980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org};
15080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
15180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Simple first in first out (FIFO) class that wraps a list of 16-bit audio
15280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// buffers of fixed size and allows Write and Read operations. The idea is to
15380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// store recorded audio buffers (using Write) and then read (using Read) these
15480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// stored buffers with as short delay as possible when the audio layer needs
15580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// data to play out. The number of buffers in the FIFO will stabilize under
15680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// normal conditions since there will be a balance between Write and Read calls.
15780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// The container is a std::list container and access is protected with a lock
15880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// since both sides (playout and recording) are driven by its own thread.
15980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgclass FifoAudioStream : public AudioStreamInterface {
16080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org public:
161dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  explicit FifoAudioStream(size_t frames_per_buffer)
16280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      : frames_per_buffer_(frames_per_buffer),
16380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
16480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        fifo_(new AudioBufferList),
16580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        largest_size_(0),
16680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        total_written_elements_(0),
16780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        write_count_(0) {
16880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    EXPECT_NE(fifo_.get(), nullptr);
16980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
17080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
17180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  ~FifoAudioStream() {
17280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    Flush();
17380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
17480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
17580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Allocate new memory, copy |num_frames| samples from |source| into memory
17680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // and add pointer to the memory location to end of the list.
17780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Increases the size of the FIFO by one element.
178dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Write(const void* source, size_t num_frames) override {
17980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    ASSERT_EQ(num_frames, frames_per_buffer_);
18080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    PRINTD("+");
18180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (write_count_++ < kNumIgnoreFirstCallbacks) {
18280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      return;
18380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
18480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    int16_t* memory = new int16_t[frames_per_buffer_];
18580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    memcpy(static_cast<int16_t*> (&memory[0]),
18680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org           source,
18780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org           bytes_per_buffer_);
18880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    rtc::CritScope lock(&lock_);
18980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    fifo_->push_back(memory);
190dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const size_t size = fifo_->size();
19180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (size > largest_size_) {
19280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      largest_size_ = size;
193dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      PRINTD("(%" PRIuS ")", largest_size_);
19480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
19580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    total_written_elements_ += size;
19680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
19780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
19880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Read pointer to data buffer from front of list, copy |num_frames| of stored
19980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // data into |destination| and delete the utilized memory allocation.
20080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Decreases the size of the FIFO by one element.
201dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Read(void* destination, size_t num_frames) override {
20280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    ASSERT_EQ(num_frames, frames_per_buffer_);
20380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    PRINTD("-");
20480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    rtc::CritScope lock(&lock_);
20580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (fifo_->empty()) {
20680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      memset(destination, 0, bytes_per_buffer_);
20780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    } else {
20880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      int16_t* memory = fifo_->front();
20980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      fifo_->pop_front();
21080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      memcpy(destination,
21180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org             static_cast<int16_t*> (&memory[0]),
21280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org             bytes_per_buffer_);
21380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      delete memory;
21480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
21580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
21680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
217dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t size() const {
21880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    return fifo_->size();
21980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
22080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
221dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t largest_size() const {
22280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    return largest_size_;
22380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
22480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
225dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t average_size() const {
22680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    return (total_written_elements_ == 0) ? 0.0 : 0.5 + static_cast<float> (
22780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      total_written_elements_) / (write_count_ - kNumIgnoreFirstCallbacks);
22880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
22980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
23080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org private:
23180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  void Flush() {
23280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    for (auto it = fifo_->begin(); it != fifo_->end(); ++it) {
23380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      delete *it;
23480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
23580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    fifo_->clear();
23680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
23780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
23880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  using AudioBufferList = std::list<int16_t*>;
23980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  rtc::CriticalSection lock_;
240dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t frames_per_buffer_;
241dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t bytes_per_buffer_;
24280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  rtc::scoped_ptr<AudioBufferList> fifo_;
243dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t largest_size_;
244dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t total_written_elements_;
245dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t write_count_;
24680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org};
24780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
24880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Inserts periodic impulses and measures the latency between the time of
24980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// transmission and time of receiving the same impulse.
25080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Usage requires a special hardware called Audio Loopback Dongle.
25180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// See http://source.android.com/devices/audio/loopback.html for details.
25280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgclass LatencyMeasuringAudioStream : public AudioStreamInterface {
25380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org public:
254dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  explicit LatencyMeasuringAudioStream(size_t frames_per_buffer)
25580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      : clock_(Clock::GetRealTimeClock()),
25680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        frames_per_buffer_(frames_per_buffer),
25780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
25880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        play_count_(0),
25980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        rec_count_(0),
26080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        pulse_time_(0) {
26180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
26280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
26380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Insert periodic impulses in first two samples of |destination|.
264dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Read(void* destination, size_t num_frames) override {
26580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    ASSERT_EQ(num_frames, frames_per_buffer_);
26680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (play_count_ == 0) {
26780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      PRINT("[");
26880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
26980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    play_count_++;
27080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    memset(destination, 0, bytes_per_buffer_);
27180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) {
27280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      if (pulse_time_ == 0) {
27380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        pulse_time_ = clock_->TimeInMilliseconds();
27480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      }
27580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      PRINT(".");
27680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      const int16_t impulse = std::numeric_limits<int16_t>::max();
27780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      int16_t* ptr16 = static_cast<int16_t*> (destination);
278dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      for (size_t i = 0; i < 2; ++i) {
279dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting        ptr16[i] = impulse;
28080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      }
28180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
28280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
28380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
28480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Detect received impulses in |source|, derive time between transmission and
28580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // detection and add the calculated delay to list of latencies.
286dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void Write(const void* source, size_t num_frames) override {
28780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    ASSERT_EQ(num_frames, frames_per_buffer_);
28880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    rec_count_++;
28980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (pulse_time_ == 0) {
29080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      // Avoid detection of new impulse response until a new impulse has
29180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      // been transmitted (sets |pulse_time_| to value larger than zero).
29280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      return;
29380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
29480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    const int16_t* ptr16 = static_cast<const int16_t*> (source);
29580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    std::vector<int16_t> vec(ptr16, ptr16 + num_frames);
29680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    // Find max value in the audio buffer.
29780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    int max = *std::max_element(vec.begin(), vec.end());
29880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    // Find index (element position in vector) of the max element.
29980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    int index_of_max = std::distance(vec.begin(),
30080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                                     std::find(vec.begin(), vec.end(),
30180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                                     max));
30280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (max > kImpulseThreshold) {
30380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      PRINTD("(%d,%d)", max, index_of_max);
30480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      int64_t now_time = clock_->TimeInMilliseconds();
30580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      int extra_delay = IndexToMilliseconds(static_cast<double> (index_of_max));
30680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      PRINTD("[%d]", static_cast<int> (now_time - pulse_time_));
30780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      PRINTD("[%d]", extra_delay);
30880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      // Total latency is the difference between transmit time and detection
30980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      // tome plus the extra delay within the buffer in which we detected the
31080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      // received impulse. It is transmitted at sample 0 but can be received
31180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      // at sample N where N > 0. The term |extra_delay| accounts for N and it
31280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      // is a value between 0 and 10ms.
31380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      latencies_.push_back(now_time - pulse_time_ + extra_delay);
31480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      pulse_time_ = 0;
31580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    } else {
31680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      PRINTD("-");
31780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
31880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
31980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
320dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t num_latency_values() const {
32180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    return latencies_.size();
32280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
32380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
32480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  int min_latency() const {
32580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (latencies_.empty())
32680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      return 0;
32780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    return *std::min_element(latencies_.begin(), latencies_.end());
32880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
32980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
33080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  int max_latency() const {
33180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (latencies_.empty())
33280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      return 0;
33380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    return *std::max_element(latencies_.begin(), latencies_.end());
33480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
33580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
33680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  int average_latency() const {
33780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (latencies_.empty())
33880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      return 0;
33980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    return 0.5 + static_cast<double> (
34080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        std::accumulate(latencies_.begin(), latencies_.end(), 0)) /
34180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        latencies_.size();
34280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
34380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
34480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  void PrintResults() const {
34580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    PRINT("] ");
34680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    for (auto it = latencies_.begin(); it != latencies_.end(); ++it) {
34780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      PRINT("%d ", *it);
34880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
34980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    PRINT("\n");
35080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag,
35180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        min_latency(), max_latency(), average_latency());
35280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
35380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
35480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  int IndexToMilliseconds(double index) const {
355b297c5a01f88219da26cffe433804963d1b70f0fpkasting    return static_cast<int>(10.0 * (index / frames_per_buffer_) + 0.5);
35680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  }
35780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
35880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org private:
35980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  Clock* clock_;
360dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t frames_per_buffer_;
361dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t bytes_per_buffer_;
362dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t play_count_;
363dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t rec_count_;
36480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  int64_t pulse_time_;
36580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  std::vector<int> latencies_;
36680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org};
36780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
36880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Mocks the AudioTransport object and proxies actions for the two callbacks
36980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// (RecordedDataIsAvailable and NeedMorePlayData) to different implementations
37080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// of AudioStreamInterface.
37180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.orgclass MockAudioTransport : public AudioTransport {
37280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org public:
37380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  explicit MockAudioTransport(int type)
37480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      : num_callbacks_(0),
37580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        type_(type),
37680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        play_count_(0),
37780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        rec_count_(0),
37880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org        audio_stream_(nullptr) {}
37980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
38080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  virtual ~MockAudioTransport() {}
38180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
382474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  MOCK_METHOD10(RecordedDataIsAvailable,
383474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                int32_t(const void* audioSamples,
384dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                        const size_t nSamples,
385dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                        const size_t nBytesPerSample,
3866955870806624479723addfae6dcf5d13968796cPeter Kasting                        const size_t nChannels,
387474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                        const uint32_t samplesPerSec,
388474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                        const uint32_t totalDelayMS,
389474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                        const int32_t clockDrift,
390474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                        const uint32_t currentMicLevel,
391474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                        const bool keyPressed,
392474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                        uint32_t& newMicLevel));
393474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  MOCK_METHOD8(NeedMorePlayData,
394dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting               int32_t(const size_t nSamples,
395dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                       const size_t nBytesPerSample,
3966955870806624479723addfae6dcf5d13968796cPeter Kasting                       const size_t nChannels,
397474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                       const uint32_t samplesPerSec,
398474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                       void* audioSamples,
399dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                       size_t& nSamplesOut,
400474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                       int64_t* elapsed_time_ms,
401474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                       int64_t* ntp_time_ms));
402474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
40380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Set default actions of the mock object. We are delegating to fake
40480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // implementations (of AudioStreamInterface) here.
40580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  void HandleCallbacks(EventWrapper* test_is_done,
40680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                       AudioStreamInterface* audio_stream,
40780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                       int num_callbacks) {
408474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    test_is_done_ = test_is_done;
40980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    audio_stream_ = audio_stream;
410474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    num_callbacks_ = num_callbacks;
411474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    if (play_mode()) {
412474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _))
413474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org          .WillByDefault(
414474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org              Invoke(this, &MockAudioTransport::RealNeedMorePlayData));
415474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    }
416474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    if (rec_mode()) {
417474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _))
418474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org          .WillByDefault(
419474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org              Invoke(this, &MockAudioTransport::RealRecordedDataIsAvailable));
420474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    }
421474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
422474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
423474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  int32_t RealRecordedDataIsAvailable(const void* audioSamples,
424dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                                      const size_t nSamples,
425dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                                      const size_t nBytesPerSample,
4266955870806624479723addfae6dcf5d13968796cPeter Kasting                                      const size_t nChannels,
427474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                      const uint32_t samplesPerSec,
428474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                      const uint32_t totalDelayMS,
429474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                      const int32_t clockDrift,
430474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                      const uint32_t currentMicLevel,
431474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                      const bool keyPressed,
432474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                      uint32_t& newMicLevel) {
43374d4792af574a90c4a13b3e57195883e2a546cbehenrika@webrtc.org    EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks.";
434474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    rec_count_++;
43580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    // Process the recorded audio stream if an AudioStreamInterface
43680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    // implementation exists.
43780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (audio_stream_) {
43880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      audio_stream_->Write(audioSamples, nSamples);
43980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
44080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (ReceivedEnoughCallbacks()) {
441474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      test_is_done_->Set();
44280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
443474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    return 0;
444474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
445474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
446dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  int32_t RealNeedMorePlayData(const size_t nSamples,
447dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                               const size_t nBytesPerSample,
4486955870806624479723addfae6dcf5d13968796cPeter Kasting                               const size_t nChannels,
449474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                               const uint32_t samplesPerSec,
450474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                               void* audioSamples,
451dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                               size_t& nSamplesOut,
452474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                               int64_t* elapsed_time_ms,
453474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                               int64_t* ntp_time_ms) {
45474d4792af574a90c4a13b3e57195883e2a546cbehenrika@webrtc.org    EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks.";
45580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    play_count_++;
456474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    nSamplesOut = nSamples;
45780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    // Read (possibly processed) audio stream samples to be played out if an
45880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    // AudioStreamInterface implementation exists.
45980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (audio_stream_) {
46080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      audio_stream_->Read(audioSamples, nSamples);
461474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    }
46280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    if (ReceivedEnoughCallbacks()) {
463474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      test_is_done_->Set();
46480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org    }
465474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    return 0;
466474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
467474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
468474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  bool ReceivedEnoughCallbacks() {
469474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    bool recording_done = false;
470474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    if (rec_mode())
471474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      recording_done = rec_count_ >= num_callbacks_;
472474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    else
473474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      recording_done = true;
474474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
475474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    bool playout_done = false;
476474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    if (play_mode())
477474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      playout_done = play_count_ >= num_callbacks_;
478474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    else
479474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      playout_done = true;
480474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
481474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    return recording_done && playout_done;
482474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
483474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
484474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  bool play_mode() const { return type_ & kPlayout; }
485474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  bool rec_mode() const { return type_ & kRecording; }
486474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
487474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org private:
488474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EventWrapper* test_is_done_;
489dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t num_callbacks_;
490474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  int type_;
491dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t play_count_;
492dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t rec_count_;
49380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  AudioStreamInterface* audio_stream_;
49480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream_;
495474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org};
496474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
497b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// AudioDeviceTest test fixture.
498b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaclass AudioDeviceTest : public ::testing::Test {
499474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org protected:
500474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  AudioDeviceTest()
501474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      : test_is_done_(EventWrapper::Create()) {
502474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    // One-time initialization of JVM and application context. Ensures that we
503474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    // can do calls between C++ and Java. Initializes both Java and OpenSL ES
504474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    // implementations.
505474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    webrtc::audiodevicemodule::EnsureInitialized();
506b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    // Creates an audio device using a default audio layer.
507b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    audio_device_ = CreateAudioDevice(AudioDeviceModule::kPlatformDefaultAudio);
508474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_NE(audio_device_.get(), nullptr);
509474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(0, audio_device_->Init());
510b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    playout_parameters_ = audio_manager()->GetPlayoutAudioParameters();
511b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    record_parameters_ = audio_manager()->GetRecordAudioParameters();
512523183b4aa2118b483967fccfdbe5b848c3eb18dhenrika    build_info_.reset(new BuildInfo());
513474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
514474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  virtual ~AudioDeviceTest() {
515474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(0, audio_device_->Terminate());
516474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
517474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
518474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  int playout_sample_rate() const {
519b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return playout_parameters_.sample_rate();
520474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
521b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  int record_sample_rate() const {
522b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return record_parameters_.sample_rate();
523474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
5246955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t playout_channels() const {
525b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return playout_parameters_.channels();
526474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
5276955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t record_channels() const {
528b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return record_parameters_.channels();
529474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
530dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t playout_frames_per_10ms_buffer() const {
531b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return playout_parameters_.frames_per_10ms_buffer();
532474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
533dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t record_frames_per_10ms_buffer() const {
534b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return record_parameters_.frames_per_10ms_buffer();
535b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
536b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
537b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  int total_delay_ms() const {
538b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return audio_manager()->GetDelayEstimateInMilliseconds();
539474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
540474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
54126b08605e2b99136fcc1cab0800234f469d6e236Peter Boström  rtc::scoped_refptr<AudioDeviceModule> audio_device() const {
542474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    return audio_device_;
543474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
544474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
545b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceModuleImpl* audio_device_impl() const {
546b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return static_cast<AudioDeviceModuleImpl*>(audio_device_.get());
547b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
548b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
549b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioManager* audio_manager() const {
550b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return audio_device_impl()->GetAndroidAudioManagerForTest();
551474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
552474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
553b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioManager* GetAudioManager(AudioDeviceModule* adm) const {
554b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return static_cast<AudioDeviceModuleImpl*>(adm)->
555b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika        GetAndroidAudioManagerForTest();
556b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
557b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
558b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceBuffer* audio_device_buffer() const {
559b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return audio_device_impl()->GetAudioDeviceBuffer();
560b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
561b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
56226b08605e2b99136fcc1cab0800234f469d6e236Peter Boström  rtc::scoped_refptr<AudioDeviceModule> CreateAudioDevice(
563b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      AudioDeviceModule::AudioLayer audio_layer) {
56426b08605e2b99136fcc1cab0800234f469d6e236Peter Boström    rtc::scoped_refptr<AudioDeviceModule> module(
565b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika        AudioDeviceModuleImpl::Create(0, audio_layer));
566b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return module;
567474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
568474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
56980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Returns file name relative to the resource root given a sample rate.
570474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  std::string GetFileName(int sample_rate) {
571474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100);
572474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    char fname[64];
573474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    snprintf(fname,
574474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org             sizeof(fname),
575474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org             "audio_device/audio_short%d",
576474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org             sample_rate / 1000);
577474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    std::string file_name(webrtc::test::ResourcePath(fname, "pcm"));
578474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_TRUE(test::FileExists(file_name));
579474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#ifdef ENABLE_PRINTF
580474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    PRINT("file name: %s\n", file_name.c_str());
581dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const size_t bytes = test::GetFileSize(file_name);
582dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    PRINT("file size: %" PRIuS " [bytes]\n", bytes);
583dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    PRINT("file size: %" PRIuS " [samples]\n", bytes / kBytesPerSample);
584dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const int seconds =
585dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting        static_cast<int>(bytes / (sample_rate * kBytesPerSample));
586474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    PRINT("file size: %d [secs]\n", seconds);
587dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    PRINT("file size: %" PRIuS " [callbacks]\n",
588dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting          seconds * kNumCallbacksPerSecond);
589474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org#endif
590474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    return file_name;
591474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
592474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
593b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceModule::AudioLayer GetActiveAudioLayer() const {
594b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    AudioDeviceModule::AudioLayer audio_layer;
595b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    EXPECT_EQ(0, audio_device()->ActiveAudioLayer(&audio_layer));
596b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return audio_layer;
597b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
598b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
599b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  int TestDelayOnAudioLayer(
600b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      const AudioDeviceModule::AudioLayer& layer_to_test) {
60126b08605e2b99136fcc1cab0800234f469d6e236Peter Boström    rtc::scoped_refptr<AudioDeviceModule> audio_device;
602b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    audio_device = CreateAudioDevice(layer_to_test);
603b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    EXPECT_NE(audio_device.get(), nullptr);
604b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    AudioManager* audio_manager = GetAudioManager(audio_device.get());
605b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    EXPECT_NE(audio_manager, nullptr);
606b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return audio_manager->GetDelayEstimateInMilliseconds();
607b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
608b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
609b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceModule::AudioLayer TestActiveAudioLayer(
610b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      const AudioDeviceModule::AudioLayer& layer_to_test) {
61126b08605e2b99136fcc1cab0800234f469d6e236Peter Boström    rtc::scoped_refptr<AudioDeviceModule> audio_device;
612b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    audio_device = CreateAudioDevice(layer_to_test);
613b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    EXPECT_NE(audio_device.get(), nullptr);
614b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    AudioDeviceModule::AudioLayer active;
615b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    EXPECT_EQ(0, audio_device->ActiveAudioLayer(&active));
616b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return active;
617b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
618b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
619523183b4aa2118b483967fccfdbe5b848c3eb18dhenrika  bool DisableTestForThisDevice(const std::string& model) {
620523183b4aa2118b483967fccfdbe5b848c3eb18dhenrika    return (build_info_->GetDeviceModel() == model);
621523183b4aa2118b483967fccfdbe5b848c3eb18dhenrika  }
622523183b4aa2118b483967fccfdbe5b848c3eb18dhenrika
623b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // Volume control is currently only supported for the Java output audio layer.
624b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // For OpenSL ES, the internal stream volume is always on max level and there
625b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // is no need for this test to set it to max.
626b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  bool AudioLayerSupportsVolumeControl() const {
627b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return GetActiveAudioLayer() == AudioDeviceModule::kAndroidJavaAudio;
628b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
629b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
6308324b525dce2c502bbd24b3946bbae207645cde9henrika  void SetMaxPlayoutVolume() {
631b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    if (!AudioLayerSupportsVolumeControl())
632b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      return;
6338324b525dce2c502bbd24b3946bbae207645cde9henrika    uint32_t max_volume;
6348324b525dce2c502bbd24b3946bbae207645cde9henrika    EXPECT_EQ(0, audio_device()->MaxSpeakerVolume(&max_volume));
6358324b525dce2c502bbd24b3946bbae207645cde9henrika    EXPECT_EQ(0, audio_device()->SetSpeakerVolume(max_volume));
6368324b525dce2c502bbd24b3946bbae207645cde9henrika  }
6378324b525dce2c502bbd24b3946bbae207645cde9henrika
638b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  void DisableBuiltInAECIfAvailable() {
639b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    if (audio_device()->BuiltInAECIsAvailable()) {
640b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      EXPECT_EQ(0, audio_device()->EnableBuiltInAEC(false));
641b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    }
642b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  }
643b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
644474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  void StartPlayout() {
645474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
646474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_FALSE(audio_device()->Playing());
647474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(0, audio_device()->InitPlayout());
648474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_TRUE(audio_device()->PlayoutIsInitialized());
649474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(0, audio_device()->StartPlayout());
650474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_TRUE(audio_device()->Playing());
651474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
652474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
653474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  void StopPlayout() {
654474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(0, audio_device()->StopPlayout());
655474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_FALSE(audio_device()->Playing());
656b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
657474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
658474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
659474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  void StartRecording() {
660474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_FALSE(audio_device()->RecordingIsInitialized());
661474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_FALSE(audio_device()->Recording());
662474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(0, audio_device()->InitRecording());
663474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_TRUE(audio_device()->RecordingIsInitialized());
664474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(0, audio_device()->StartRecording());
665474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_TRUE(audio_device()->Recording());
666474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
667474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
668474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  void StopRecording() {
669474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_EQ(0, audio_device()->StopRecording());
670474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org    EXPECT_FALSE(audio_device()->Recording());
671474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  }
672474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
6738324b525dce2c502bbd24b3946bbae207645cde9henrika  int GetMaxSpeakerVolume() const {
6748324b525dce2c502bbd24b3946bbae207645cde9henrika    uint32_t max_volume(0);
6758324b525dce2c502bbd24b3946bbae207645cde9henrika    EXPECT_EQ(0, audio_device()->MaxSpeakerVolume(&max_volume));
6768324b525dce2c502bbd24b3946bbae207645cde9henrika    return max_volume;
6778324b525dce2c502bbd24b3946bbae207645cde9henrika  }
6788324b525dce2c502bbd24b3946bbae207645cde9henrika
6798324b525dce2c502bbd24b3946bbae207645cde9henrika  int GetMinSpeakerVolume() const {
6808324b525dce2c502bbd24b3946bbae207645cde9henrika    uint32_t min_volume(0);
6818324b525dce2c502bbd24b3946bbae207645cde9henrika    EXPECT_EQ(0, audio_device()->MinSpeakerVolume(&min_volume));
6828324b525dce2c502bbd24b3946bbae207645cde9henrika    return min_volume;
6838324b525dce2c502bbd24b3946bbae207645cde9henrika  }
6848324b525dce2c502bbd24b3946bbae207645cde9henrika
6858324b525dce2c502bbd24b3946bbae207645cde9henrika  int GetSpeakerVolume() const {
6868324b525dce2c502bbd24b3946bbae207645cde9henrika    uint32_t volume(0);
6878324b525dce2c502bbd24b3946bbae207645cde9henrika    EXPECT_EQ(0, audio_device()->SpeakerVolume(&volume));
6888324b525dce2c502bbd24b3946bbae207645cde9henrika    return volume;
6898324b525dce2c502bbd24b3946bbae207645cde9henrika  }
6908324b525dce2c502bbd24b3946bbae207645cde9henrika
691474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  rtc::scoped_ptr<EventWrapper> test_is_done_;
69226b08605e2b99136fcc1cab0800234f469d6e236Peter Boström  rtc::scoped_refptr<AudioDeviceModule> audio_device_;
693b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioParameters playout_parameters_;
694b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioParameters record_parameters_;
695523183b4aa2118b483967fccfdbe5b848c3eb18dhenrika  rtc::scoped_ptr<BuildInfo> build_info_;
696474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org};
697474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
698b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, ConstructDestruct) {
699474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  // Using the test fixture to create and destruct the audio device module.
700474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
701474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
702b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// We always ask for a default audio layer when the ADM is constructed. But the
703b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// ADM will then internally set the best suitable combination of audio layers,
704b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// for input and output based on if low-latency output audio in combination
705b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// with OpenSL ES is supported or not. This test ensures that the correct
706b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// selection is done.
707b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, VerifyDefaultAudioLayer) {
708b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  const AudioDeviceModule::AudioLayer audio_layer = GetActiveAudioLayer();
709b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  bool low_latency_output = audio_manager()->IsLowLatencyPlayoutSupported();
710b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceModule::AudioLayer expected_audio_layer = low_latency_output ?
711b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio :
712b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      AudioDeviceModule::kAndroidJavaAudio;
713b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(expected_audio_layer, audio_layer);
714474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
715474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
716b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// Verify that it is possible to explicitly create the two types of supported
717b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// ADMs. These two tests overrides the default selection of native audio layer
718b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// by ignoring if the device supports low-latency output or not.
719b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, CorrectAudioLayerIsUsedForCombinedJavaOpenSLCombo) {
720b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceModule::AudioLayer expected_layer =
721b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio;
722b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceModule::AudioLayer active_layer = TestActiveAudioLayer(
723b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      expected_layer);
724b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(expected_layer, active_layer);
725b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika}
726b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
727b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, CorrectAudioLayerIsUsedForJavaInBothDirections) {
728b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceModule::AudioLayer expected_layer =
729b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      AudioDeviceModule::kAndroidJavaAudio;
730b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  AudioDeviceModule::AudioLayer active_layer = TestActiveAudioLayer(
731b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      expected_layer);
732b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(expected_layer, active_layer);
733b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika}
734b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
735b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// The Android ADM supports two different delay reporting modes. One for the
736b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// low-latency output path (in combination with OpenSL ES), and one for the
737b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// high-latency output path (Java backends in both directions). These two tests
738b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// verifies that the audio manager reports correct delay estimate given the
739b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// selected audio layer. Note that, this delay estimate will only be utilized
740b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// if the HW AEC is disabled.
741b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, UsesCorrectDelayEstimateForHighLatencyOutputPath) {
742b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(kHighLatencyModeDelayEstimateInMilliseconds,
743b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika            TestDelayOnAudioLayer(AudioDeviceModule::kAndroidJavaAudio));
744b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika}
745b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
746b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, UsesCorrectDelayEstimateForLowLatencyOutputPath) {
747b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(kLowLatencyModeDelayEstimateInMilliseconds,
748b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika            TestDelayOnAudioLayer(
749b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio));
750b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika}
751b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
752b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// Ensure that the ADM internal audio device buffer is configured to use the
753b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// correct set of parameters.
754b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, VerifyAudioDeviceBufferParameters) {
755b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(playout_parameters_.sample_rate(),
756b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika            audio_device_buffer()->PlayoutSampleRate());
757b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(record_parameters_.sample_rate(),
758b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika            audio_device_buffer()->RecordingSampleRate());
759b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(playout_parameters_.channels(),
760b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika            audio_device_buffer()->PlayoutChannels());
761b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(record_parameters_.channels(),
762b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika            audio_device_buffer()->RecordingChannels());
763b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika}
764b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
765b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
766b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, InitTerminate) {
767474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  // Initialization is part of the test fixture.
768474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_TRUE(audio_device()->Initialized());
769474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_EQ(0, audio_device()->Terminate());
770474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_FALSE(audio_device()->Initialized());
771474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
772474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
773b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, Devices) {
774474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  // Device enumeration is not supported. Verify fixed values only.
775474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_EQ(1, audio_device()->PlayoutDevices());
776474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_EQ(1, audio_device()->RecordingDevices());
777474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
778474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
779b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, SpeakerVolumeShouldBeAvailable) {
780b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // The OpenSL ES output audio path does not support volume control.
781b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  if (!AudioLayerSupportsVolumeControl())
782b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return;
7838324b525dce2c502bbd24b3946bbae207645cde9henrika  bool available;
7848324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_EQ(0, audio_device()->SpeakerVolumeIsAvailable(&available));
7858324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_TRUE(available);
7868324b525dce2c502bbd24b3946bbae207645cde9henrika}
7878324b525dce2c502bbd24b3946bbae207645cde9henrika
788b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, MaxSpeakerVolumeIsPositive) {
789b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // The OpenSL ES output audio path does not support volume control.
790b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  if (!AudioLayerSupportsVolumeControl())
791b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return;
792b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  StartPlayout();
7938324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_GT(GetMaxSpeakerVolume(), 0);
794b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  StopPlayout();
7958324b525dce2c502bbd24b3946bbae207645cde9henrika}
7968324b525dce2c502bbd24b3946bbae207645cde9henrika
797b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, MinSpeakerVolumeIsZero) {
798b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // The OpenSL ES output audio path does not support volume control.
799b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  if (!AudioLayerSupportsVolumeControl())
800b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return;
8018324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_EQ(GetMinSpeakerVolume(), 0);
8028324b525dce2c502bbd24b3946bbae207645cde9henrika}
8038324b525dce2c502bbd24b3946bbae207645cde9henrika
804b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, DefaultSpeakerVolumeIsWithinMinMax) {
805b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // The OpenSL ES output audio path does not support volume control.
806b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  if (!AudioLayerSupportsVolumeControl())
807b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return;
8088324b525dce2c502bbd24b3946bbae207645cde9henrika  const int default_volume = GetSpeakerVolume();
8098324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_GE(default_volume, GetMinSpeakerVolume());
8108324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_LE(default_volume, GetMaxSpeakerVolume());
8118324b525dce2c502bbd24b3946bbae207645cde9henrika}
8128324b525dce2c502bbd24b3946bbae207645cde9henrika
813b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, SetSpeakerVolumeActuallySetsVolume) {
814b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // The OpenSL ES output audio path does not support volume control.
815b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  if (!AudioLayerSupportsVolumeControl())
816b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika    return;
8178324b525dce2c502bbd24b3946bbae207645cde9henrika  const int default_volume = GetSpeakerVolume();
8188324b525dce2c502bbd24b3946bbae207645cde9henrika  const int max_volume = GetMaxSpeakerVolume();
8198324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_EQ(0, audio_device()->SetSpeakerVolume(max_volume));
8208324b525dce2c502bbd24b3946bbae207645cde9henrika  int new_volume = GetSpeakerVolume();
8218324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_EQ(new_volume, max_volume);
8228324b525dce2c502bbd24b3946bbae207645cde9henrika  EXPECT_EQ(0, audio_device()->SetSpeakerVolume(default_volume));
8238324b525dce2c502bbd24b3946bbae207645cde9henrika}
8248324b525dce2c502bbd24b3946bbae207645cde9henrika
825b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// Tests that playout can be initiated, started and stopped. No audio callback
826b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// is registered in this test.
8279359b5b97810238e506350fdd0cb3d60001525f3Henrik Kjellander// Flaky on our trybots makes this test unusable.
8289359b5b97810238e506350fdd0cb3d60001525f3Henrik Kjellander// https://code.google.com/p/webrtc/issues/detail?id=5046
8299359b5b97810238e506350fdd0cb3d60001525f3Henrik KjellanderTEST_F(AudioDeviceTest, DISABLED_StartStopPlayout) {
830474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StartPlayout();
831474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StopPlayout();
832b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  StartPlayout();
833b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  StopPlayout();
834b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika}
835b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika
83682e20554cbf8152d67915e3ef764bad8064b6541henrika// Tests that recording can be initiated, started and stopped. No audio callback
83782e20554cbf8152d67915e3ef764bad8064b6541henrika// is registered in this test.
83882e20554cbf8152d67915e3ef764bad8064b6541henrikaTEST_F(AudioDeviceTest, StartStopRecording) {
83982e20554cbf8152d67915e3ef764bad8064b6541henrika  StartRecording();
84082e20554cbf8152d67915e3ef764bad8064b6541henrika  StopRecording();
84182e20554cbf8152d67915e3ef764bad8064b6541henrika  StartRecording();
84282e20554cbf8152d67915e3ef764bad8064b6541henrika  StopRecording();
84382e20554cbf8152d67915e3ef764bad8064b6541henrika}
84482e20554cbf8152d67915e3ef764bad8064b6541henrika
845b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// Verify that calling StopPlayout() will leave us in an uninitialized state
846b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika// which will require a new call to InitPlayout(). This test does not call
84791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg// StartPlayout() while being uninitialized since doing so will hit a
84891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg// RTC_DCHECK.
849b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, StopPlayoutRequiresInitToRestart) {
850b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(0, audio_device()->InitPlayout());
851b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(0, audio_device()->StartPlayout());
852b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(0, audio_device()->StopPlayout());
853b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
854474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
855474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
856474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// Start playout and verify that the native audio layer starts asking for real
857474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// audio samples to play out using the NeedMorePlayData callback.
858b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, StartPlayoutVerifyCallbacks) {
859474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  MockAudioTransport mock(kPlayout);
86080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
861b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_10ms_buffer(),
862474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     kBytesPerSample,
863474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     playout_channels(),
864474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     playout_sample_rate(),
865474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     NotNull(),
866474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     _, _, _))
867474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      .Times(AtLeast(kNumCallbacks));
868474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
869474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StartPlayout();
870474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  test_is_done_->Wait(kTestTimeOutInMilliseconds);
871474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StopPlayout();
872474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
873474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
874474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// Start recording and verify that the native audio layer starts feeding real
875474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// audio samples via the RecordedDataIsAvailable callback.
876b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, StartRecordingVerifyCallbacks) {
877474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  MockAudioTransport mock(kRecording);
87880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
879474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_CALL(mock, RecordedDataIsAvailable(NotNull(),
880b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika                                            record_frames_per_10ms_buffer(),
881474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            kBytesPerSample,
882b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika                                            record_channels(),
883b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika                                            record_sample_rate(),
884b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika                                            total_delay_ms(),
885474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            0,
886474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            0,
887474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            false,
888474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            _))
889474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      .Times(AtLeast(kNumCallbacks));
890474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
891474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
892474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StartRecording();
893474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  test_is_done_->Wait(kTestTimeOutInMilliseconds);
894474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StopRecording();
895474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
896474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
897474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
898474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// Start playout and recording (full-duplex audio) and verify that audio is
899474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// active in both directions.
900b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, StartPlayoutAndRecordingVerifyCallbacks) {
901474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  MockAudioTransport mock(kPlayout | kRecording);
90280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  mock.HandleCallbacks(test_is_done_.get(), nullptr,  kNumCallbacks);
903b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_10ms_buffer(),
904474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     kBytesPerSample,
905474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     playout_channels(),
906474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     playout_sample_rate(),
907474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     NotNull(),
908474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                     _, _, _))
909474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      .Times(AtLeast(kNumCallbacks));
910474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_CALL(mock, RecordedDataIsAvailable(NotNull(),
911b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika                                            record_frames_per_10ms_buffer(),
912474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            kBytesPerSample,
913b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika                                            record_channels(),
914b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika                                            record_sample_rate(),
915b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika                                            total_delay_ms(),
916474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            0,
917474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            0,
918474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            false,
919474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org                                            _))
920474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org      .Times(AtLeast(kNumCallbacks));
921474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
922474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StartPlayout();
923474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StartRecording();
924474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  test_is_done_->Wait(kTestTimeOutInMilliseconds);
925474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StopRecording();
926474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StopPlayout();
927474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
928474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
929474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// Start playout and read audio from an external PCM file when the audio layer
930474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// asks for data to play out. Real audio is played out in this test but it does
931474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org// not contain any explicit verification that the audio quality is perfect.
932b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, RunPlayoutWithFileAsSource) {
933474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  // TODO(henrika): extend test when mono output is supported.
9346955870806624479723addfae6dcf5d13968796cPeter Kasting  EXPECT_EQ(1u, playout_channels());
935474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  NiceMock<MockAudioTransport> mock(kPlayout);
93680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  const int num_callbacks = kFilePlayTimeInSec * kNumCallbacksPerSecond;
93774d4792af574a90c4a13b3e57195883e2a546cbehenrika@webrtc.org  std::string file_name = GetFileName(playout_sample_rate());
93880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  rtc::scoped_ptr<FileAudioStream> file_audio_stream(
93980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org      new FileAudioStream(num_callbacks, file_name, playout_sample_rate()));
94080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  mock.HandleCallbacks(test_is_done_.get(),
94180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                       file_audio_stream.get(),
94280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                       num_callbacks);
943b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  // SetMaxPlayoutVolume();
944474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
945474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StartPlayout();
946474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  test_is_done_->Wait(kTestTimeOutInMilliseconds);
947474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org  StopPlayout();
948474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}
949474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org
95080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Start playout and recording and store recorded data in an intermediate FIFO
95180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// buffer from which the playout side then reads its samples in the same order
95280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// as they were stored. Under ideal circumstances, a callback sequence would
95380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// look like: ...+-+-+-+-+-+-+-..., where '+' means 'packet recorded' and '-'
95480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// means 'packet played'. Under such conditions, the FIFO would only contain
95580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// one packet on average. However, under more realistic conditions, the size
95680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// of the FIFO will vary more due to an unbalance between the two sides.
95780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// This test tries to verify that the device maintains a balanced callback-
95880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// sequence by running in loopback for ten seconds while measuring the size
95980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// (max and average) of the FIFO. The size of the FIFO is increased by the
96080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// recording side and decreased by the playout side.
96180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// TODO(henrika): tune the final test parameters after running tests on several
96280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// different devices.
963b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, RunPlayoutAndRecordingInFullDuplex) {
964b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(record_channels(), playout_channels());
965b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(record_sample_rate(), playout_sample_rate());
96680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  NiceMock<MockAudioTransport> mock(kPlayout | kRecording);
96780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  rtc::scoped_ptr<FifoAudioStream> fifo_audio_stream(
968b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      new FifoAudioStream(playout_frames_per_10ms_buffer()));
96980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  mock.HandleCallbacks(test_is_done_.get(),
97080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                       fifo_audio_stream.get(),
97180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                       kFullDuplexTimeInSec * kNumCallbacksPerSecond);
9728324b525dce2c502bbd24b3946bbae207645cde9henrika  SetMaxPlayoutVolume();
97380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
97480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  StartRecording();
97580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  StartPlayout();
97680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds,
97780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                               1000 * kFullDuplexTimeInSec));
97880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  StopPlayout();
97980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  StopRecording();
980dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  EXPECT_LE(fifo_audio_stream->average_size(), 10u);
981dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  EXPECT_LE(fifo_audio_stream->largest_size(), 20u);
98280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org}
98380d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
98480d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// Measures loopback latency and reports the min, max and average values for
98580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// a full duplex audio session.
98680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// The latency is measured like so:
98780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// - Insert impulses periodically on the output side.
98880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// - Detect the impulses on the input side.
98980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// - Measure the time difference between the transmit time and receive time.
99080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// - Store time differences in a vector and calculate min, max and average.
99180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// This test requires a special hardware called Audio Loopback Dongle.
99280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org// See http://source.android.com/devices/audio/loopback.html for details.
993b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrikaTEST_F(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) {
994b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(record_channels(), playout_channels());
995b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  EXPECT_EQ(record_sample_rate(), playout_sample_rate());
99680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  NiceMock<MockAudioTransport> mock(kPlayout | kRecording);
99780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream(
998b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika      new LatencyMeasuringAudioStream(playout_frames_per_10ms_buffer()));
99980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  mock.HandleCallbacks(test_is_done_.get(),
100080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                       latency_audio_stream.get(),
100180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                       kMeasureLatencyTimeInSec * kNumCallbacksPerSecond);
100280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
10038324b525dce2c502bbd24b3946bbae207645cde9henrika  SetMaxPlayoutVolume();
1004b26198972c1fcb4aa7abaf3895b007e301e7d5dchenrika  DisableBuiltInAECIfAvailable();
100580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  StartRecording();
100680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  StartPlayout();
100780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  test_is_done_->Wait(std::max(kTestTimeOutInMilliseconds,
100880d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org                               1000 * kMeasureLatencyTimeInSec));
100980d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  StopPlayout();
101080d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  StopRecording();
101180d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  // Verify that the correct number of transmitted impulses are detected.
101280d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  EXPECT_EQ(latency_audio_stream->num_latency_values(),
1013dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting            static_cast<size_t>(
1014dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1));
101580d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org  latency_audio_stream->PrintResults();
101680d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org}
101780d9aeeda530aaf7e1851b381f1f7545a876d75ehenrika@webrtc.org
1018474d1eb22376898b36bcd04b0ce3860fa12fd984henrika@webrtc.org}  // namespace webrtc
1019