Reland "Migrate TestAudioDeviceModule on AudioDeviceModuleImpl"

This CL will add AudioDeviceBuffer into the SUT increasing test coverage
for audio quality regression detection.

This reverts commit b035dcc0a274e6cdde3e0fc465244bc0e9e3d70e.

Reason for revert: reland with a fix

Original change's description:
> Revert "Reland "Migrate TestAudioDeviceModule on AudioDeviceModuleImpl""
>
> This reverts commit eeae96299784515f573379a64655eb07a5973a3a.
>
> Reason for revert: breaks WebRTC Chromium FYI ios-device
> https://ci.chromium.org/ui/p/chromium/builders/webrtc.fyi/WebRTC%20Chromium%20FYI%20ios-device/14896/overview
>
> Original change's description:
> > Reland "Migrate TestAudioDeviceModule on AudioDeviceModuleImpl"
> >
> > This reverts commit 69c8d3c843326aff9dee32cc639741c1cd7f8ae9.
> >
> > Reason for revert: Reland with a fix
> >
> > Original change's description:
> > > Revert "Migrate TestAudioDeviceModule on AudioDeviceModuleImpl"
> > >
> > > This reverts commit e42bf81486d2f08b6dcbf1442287202e937ce52b.
> > >
> > > Reason for revert: Breaks iOS simulator bots and thus blocks chromium roll, https://chromium-review.googlesource.com/c/chromium/src/+/4433814
> > >
> > > Original change's description:
> > > > Migrate TestAudioDeviceModule on AudioDeviceModuleImpl
> > > >
> > > > Bug: b/272350185
> > > > Change-Id: Ia3d85d6fa3b0d4809e987a39d60d3eb022687132
> > > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/300363
> > > > Commit-Queue: Artem Titov <titovartem@webrtc.org>
> > > > Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
> > > > Cr-Commit-Position: refs/heads/main@{#39877}
> > >
> > > Bug: b/272350185
> > > Change-Id: I1e3b542fc1278797f283afedeae01cbb7412d353
> > > No-Presubmit: true
> > > No-Tree-Checks: true
> > > No-Try: true
> > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/301701
> > > Commit-Queue: Jeremy Leconte <jleconte@google.com>
> > > Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
> > > Reviewed-by: Jeremy Leconte <jleconte@google.com>
> > > Auto-Submit: Christoffer Jansson <jansson@google.com>
> > > Owners-Override: Christoffer Jansson <jansson@google.com>
> > > Cr-Commit-Position: refs/heads/main@{#39881}
> >
> > Bug: b/272350185
> > Change-Id: I809466306b2e1fd54c44b90311059c98a53ef8ee
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/301704
> > Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
> > Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
> > Commit-Queue: Artem Titov <titovartem@webrtc.org>
> > Cr-Commit-Position: refs/heads/main@{#39936}
>
> Bug: b/272350185
> Change-Id: If0a10717bf14a0a618e52728fc3a61b9c55f3bd2
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/303460
> Commit-Queue: Jeremy Leconte <jleconte@google.com>
> Owners-Override: Jeremy Leconte <jleconte@google.com>
> Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
> Cr-Commit-Position: refs/heads/main@{#39947}

Bug: b/272350185
Change-Id: I7cf7c6bc25561f4eb722957f318c2af9ce20726d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/311101
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40387}
diff --git a/modules/audio_device/test_audio_device_impl_test.cc b/modules/audio_device/test_audio_device_impl_test.cc
new file mode 100644
index 0000000..e81bb2f
--- /dev/null
+++ b/modules/audio_device/test_audio_device_impl_test.cc
@@ -0,0 +1,275 @@
+/*
+ *  Copyright (c) 2023 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/audio_device/test_audio_device_impl.h"
+
+#include <memory>
+#include <utility>
+
+#include "absl/types/optional.h"
+#include "api/task_queue/task_queue_factory.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
+#include "modules/audio_device/audio_device_buffer.h"
+#include "modules/audio_device/audio_device_generic.h"
+#include "modules/audio_device/include/audio_device.h"
+#include "modules/audio_device/include/audio_device_defines.h"
+#include "modules/audio_device/include/test_audio_device.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/synchronization/mutex.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/time_controller/simulated_time_controller.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::ElementsAre;
+
+constexpr Timestamp kStartTime = Timestamp::Millis(10000);
+
+class TestAudioTransport : public AudioTransport {
+ public:
+  enum class Mode { kPlaying, kRecording };
+
+  explicit TestAudioTransport(Mode mode) : mode_(mode) {}
+  ~TestAudioTransport() override = default;
+
+  int32_t RecordedDataIsAvailable(
+      const void* audioSamples,
+      size_t samples_per_channel,
+      size_t bytes_per_sample,
+      size_t number_of_channels,
+      uint32_t samples_per_second,
+      uint32_t total_delay_ms,
+      int32_t clock_drift,
+      uint32_t current_mic_level,
+      bool key_pressed,
+      uint32_t& new_mic_level,
+      absl::optional<int64_t> estimated_capture_time_ns) override {
+    new_mic_level = 1;
+
+    if (mode_ != Mode::kRecording) {
+      EXPECT_TRUE(false) << "RecordedDataIsAvailable mustn't be called when "
+                            "mode isn't kRecording";
+      return -1;
+    }
+
+    MutexLock lock(&mutex_);
+    samples_per_channel_.push_back(samples_per_channel);
+    number_of_channels_.push_back(number_of_channels);
+    bytes_per_sample_.push_back(bytes_per_sample);
+    samples_per_second_.push_back(samples_per_second);
+    return 0;
+  }
+
+  int32_t NeedMorePlayData(size_t samples_per_channel,
+                           size_t bytes_per_sample,
+                           size_t number_of_channels,
+                           uint32_t samples_per_second,
+                           void* audio_samples,
+                           size_t& samples_out,
+                           int64_t* elapsed_time_ms,
+                           int64_t* ntp_time_ms) override {
+    const size_t num_bytes = samples_per_channel * number_of_channels;
+    std::memset(audio_samples, 1, num_bytes);
+    samples_out = samples_per_channel * number_of_channels;
+    *elapsed_time_ms = 0;
+    *ntp_time_ms = 0;
+
+    if (mode_ != Mode::kPlaying) {
+      EXPECT_TRUE(false)
+          << "NeedMorePlayData mustn't be called when mode isn't kPlaying";
+      return -1;
+    }
+
+    MutexLock lock(&mutex_);
+    samples_per_channel_.push_back(samples_per_channel);
+    number_of_channels_.push_back(number_of_channels);
+    bytes_per_sample_.push_back(bytes_per_sample);
+    samples_per_second_.push_back(samples_per_second);
+    return 0;
+  }
+
+  int32_t RecordedDataIsAvailable(const void* audio_samples,
+                                  size_t samples_per_channel,
+                                  size_t bytes_per_sample,
+                                  size_t number_of_channels,
+                                  uint32_t samples_per_second,
+                                  uint32_t total_delay_ms,
+                                  int32_t clockDrift,
+                                  uint32_t current_mic_level,
+                                  bool key_pressed,
+                                  uint32_t& new_mic_level) override {
+    RTC_CHECK(false) << "This methods should be never executed";
+  }
+
+  void PullRenderData(int bits_per_sample,
+                      int sample_rate,
+                      size_t number_of_channels,
+                      size_t number_of_frames,
+                      void* audio_data,
+                      int64_t* elapsed_time_ms,
+                      int64_t* ntp_time_ms) override {
+    RTC_CHECK(false) << "This methods should be never executed";
+  }
+
+  std::vector<size_t> samples_per_channel() const {
+    MutexLock lock(&mutex_);
+    return samples_per_channel_;
+  }
+  std::vector<size_t> number_of_channels() const {
+    MutexLock lock(&mutex_);
+    return number_of_channels_;
+  }
+  std::vector<size_t> bytes_per_sample() const {
+    MutexLock lock(&mutex_);
+    return bytes_per_sample_;
+  }
+  std::vector<size_t> samples_per_second() const {
+    MutexLock lock(&mutex_);
+    return samples_per_second_;
+  }
+
+ private:
+  const Mode mode_;
+
+  mutable Mutex mutex_;
+  std::vector<size_t> samples_per_channel_ RTC_GUARDED_BY(mutex_);
+  std::vector<size_t> number_of_channels_ RTC_GUARDED_BY(mutex_);
+  std::vector<size_t> bytes_per_sample_ RTC_GUARDED_BY(mutex_);
+  std::vector<size_t> samples_per_second_ RTC_GUARDED_BY(mutex_);
+};
+
+TEST(TestAudioDeviceTest, EnablingRecordingProducesAudio) {
+  GlobalSimulatedTimeController time_controller(kStartTime);
+  TestAudioTransport audio_transport(TestAudioTransport::Mode::kRecording);
+  AudioDeviceBuffer audio_buffer(time_controller.GetTaskQueueFactory());
+  ASSERT_EQ(audio_buffer.RegisterAudioCallback(&audio_transport), 0);
+  std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer> capturer =
+      TestAudioDeviceModule::CreatePulsedNoiseCapturer(
+          /*max_amplitude=*/1000,
+          /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2);
+
+  TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(),
+                               std::move(capturer),
+                               /*renderer=*/nullptr);
+  ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK);
+  audio_device.AttachAudioBuffer(&audio_buffer);
+
+  EXPECT_FALSE(audio_device.RecordingIsInitialized());
+  ASSERT_EQ(audio_device.InitRecording(), 0);
+  EXPECT_TRUE(audio_device.RecordingIsInitialized());
+  audio_buffer.StartRecording();
+  ASSERT_EQ(audio_device.StartRecording(), 0);
+  time_controller.AdvanceTime(TimeDelta::Millis(10));
+  ASSERT_TRUE(audio_device.Recording());
+  time_controller.AdvanceTime(TimeDelta::Millis(10));
+  ASSERT_EQ(audio_device.StopRecording(), 0);
+  audio_buffer.StopRecording();
+
+  EXPECT_THAT(audio_transport.samples_per_channel(),
+              ElementsAre(480, 480, 480));
+  EXPECT_THAT(audio_transport.number_of_channels(), ElementsAre(2, 2, 2));
+  EXPECT_THAT(audio_transport.bytes_per_sample(), ElementsAre(4, 4, 4));
+  EXPECT_THAT(audio_transport.samples_per_second(),
+              ElementsAre(48000, 48000, 48000));
+}
+
+TEST(TestAudioDeviceTest, RecordingIsAvailableWhenCapturerIsSet) {
+  GlobalSimulatedTimeController time_controller(kStartTime);
+  std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer> capturer =
+      TestAudioDeviceModule::CreatePulsedNoiseCapturer(
+          /*max_amplitude=*/1000,
+          /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2);
+
+  TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(),
+                               std::move(capturer),
+                               /*renderer=*/nullptr);
+  ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK);
+
+  bool available;
+  EXPECT_EQ(audio_device.RecordingIsAvailable(available), 0);
+  EXPECT_TRUE(available);
+}
+
+TEST(TestAudioDeviceTest, RecordingIsNotAvailableWhenCapturerIsNotSet) {
+  GlobalSimulatedTimeController time_controller(kStartTime);
+  TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(),
+                               /*capturer=*/nullptr,
+                               /*renderer=*/nullptr);
+  ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK);
+
+  bool available;
+  EXPECT_EQ(audio_device.RecordingIsAvailable(available), 0);
+  EXPECT_FALSE(available);
+}
+
+TEST(TestAudioDeviceTest, EnablingPlayoutProducesAudio) {
+  GlobalSimulatedTimeController time_controller(kStartTime);
+  TestAudioTransport audio_transport(TestAudioTransport::Mode::kPlaying);
+  AudioDeviceBuffer audio_buffer(time_controller.GetTaskQueueFactory());
+  ASSERT_EQ(audio_buffer.RegisterAudioCallback(&audio_transport), 0);
+  std::unique_ptr<TestAudioDeviceModule::Renderer> renderer =
+      TestAudioDeviceModule::CreateDiscardRenderer(
+          /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2);
+
+  TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(),
+                               /*capturer=*/nullptr, std::move(renderer));
+  ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK);
+  audio_device.AttachAudioBuffer(&audio_buffer);
+
+  EXPECT_FALSE(audio_device.PlayoutIsInitialized());
+  ASSERT_EQ(audio_device.InitPlayout(), 0);
+  EXPECT_TRUE(audio_device.PlayoutIsInitialized());
+  audio_buffer.StartPlayout();
+  ASSERT_EQ(audio_device.StartPlayout(), 0);
+  time_controller.AdvanceTime(TimeDelta::Millis(10));
+  ASSERT_TRUE(audio_device.Playing());
+  time_controller.AdvanceTime(TimeDelta::Millis(10));
+  ASSERT_EQ(audio_device.StopPlayout(), 0);
+  audio_buffer.StopPlayout();
+
+  EXPECT_THAT(audio_transport.samples_per_channel(),
+              ElementsAre(480, 480, 480));
+  EXPECT_THAT(audio_transport.number_of_channels(), ElementsAre(2, 2, 2));
+  EXPECT_THAT(audio_transport.bytes_per_sample(), ElementsAre(4, 4, 4));
+  EXPECT_THAT(audio_transport.samples_per_second(),
+              ElementsAre(48000, 48000, 48000));
+}
+
+TEST(TestAudioDeviceTest, PlayoutIsAvailableWhenRendererIsSet) {
+  GlobalSimulatedTimeController time_controller(kStartTime);
+  std::unique_ptr<TestAudioDeviceModule::Renderer> renderer =
+      TestAudioDeviceModule::CreateDiscardRenderer(
+          /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2);
+
+  TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(),
+                               /*capturer=*/nullptr, std::move(renderer));
+  ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK);
+
+  bool available;
+  EXPECT_EQ(audio_device.PlayoutIsAvailable(available), 0);
+  EXPECT_TRUE(available);
+}
+
+TEST(TestAudioDeviceTest, PlayoutIsNotAvailableWhenRendererIsNotSet) {
+  GlobalSimulatedTimeController time_controller(kStartTime);
+  TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(),
+                               /*capturer=*/nullptr,
+                               /*renderer=*/nullptr);
+  ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK);
+
+  bool available;
+  EXPECT_EQ(audio_device.PlayoutIsAvailable(available), 0);
+  EXPECT_FALSE(available);
+}
+
+}  // namespace
+}  // namespace webrtc