#include "services/audio/loopback_reference_manager.h"
#include <memory>
#include "base/synchronization/waitable_event.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "input_controller.h"
#include "input_stream.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_io.h"
#include "media/audio/mock_audio_manager.h"
#include "media/audio/test_audio_thread.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_parameters.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::Eq;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::StrictMock;
namespace audio {
namespace {
using ReferenceOpenOutcome = ReferenceSignalProvider::ReferenceOpenOutcome;
using OpenOutcome = media::AudioInputStream::OpenOutcome;
using AudioInputCallback = media::AudioInputStream::AudioInputCallback;
class MockAudioLog : public media::AudioLog {
public:
MockAudioLog() {}
MOCK_METHOD2(OnCreated,
void(const media::AudioParameters& params,
const std::string& device_id));
MOCK_METHOD0(OnStarted, void());
MOCK_METHOD0(OnStopped, void());
MOCK_METHOD0(OnClosed, void());
MOCK_METHOD0(OnError, void());
MOCK_METHOD1(OnSetVolume, void(double));
MOCK_METHOD1(OnProcessingStateChanged, void(const std::string&));
void OnLogMessage(const std::string& message) override {
logged_messages += message;
}
std::string logged_messages = "";
};
class MockAudioInputStream : public media::AudioInputStream {
public:
MOCK_METHOD0(Open, OpenOutcome());
MOCK_METHOD0(Stop, void());
MOCK_METHOD0(Close, void());
MOCK_METHOD0(GetMaxVolume, double());
MOCK_METHOD1(SetVolume, void(double volume));
MOCK_METHOD0(GetVolume, double());
MOCK_METHOD1(SetAutomaticGainControl, bool(bool enabled));
MOCK_METHOD0(GetAutomaticGainControl, bool());
MOCK_METHOD0(IsMuted, bool());
MOCK_METHOD1(SetOutputDeviceForAec,
void(const std::string& output_device_id));
void Start(AudioInputCallback* callback) override {
captured_callback_ = callback;
}
std::optional<AudioInputCallback*> captured_callback_;
};
class LocalMockAudioManager : public media::MockAudioManager {
public:
LocalMockAudioManager()
: media::MockAudioManager(
std::make_unique<media::TestAudioThread>(false)) {}
~LocalMockAudioManager() override = default;
MOCK_METHOD(media::AudioParameters,
GetInputStreamParameters,
(const std::string& device_id),
(override));
MOCK_METHOD(media::AudioInputStream*,
MakeAudioInputStream,
(const media::AudioParameters& params,
const std::string& device_id,
const LogCallback& log_callback),
(override));
MOCK_METHOD(std::unique_ptr<media::AudioLog>,
CreateAudioLog,
(media::AudioLogFactory::AudioComponent component,
int component_id),
(override));
};
class MockListener : public ReferenceOutput::Listener {
public:
MockListener() = default;
~MockListener() override = default;
MOCK_METHOD(void,
OnPlayoutData,
(const media::AudioBus&, int, base::TimeDelta),
(override));
MOCK_METHOD(void, OnReferenceStreamError, (), (override));
};
class LoopbackReferenceManagerTest : public ::testing::Test {
public:
LoopbackReferenceManagerTest()
: loopback_reference_manager_(
std::make_unique<LoopbackReferenceManager>(&audio_manager_)) {}
LoopbackReferenceManagerTest(const LoopbackReferenceManagerTest&) = delete;
LoopbackReferenceManagerTest& operator=(const LoopbackReferenceManagerTest&) =
delete;
~LoopbackReferenceManagerTest() override {
loopback_reference_manager_.reset();
audio_manager_.Shutdown();
}
protected:
std::unique_ptr<StrictMock<MockAudioInputStream>> ExpectCreateLoopbackStream(
int component_id);
void TestStreamOpenError(
OpenOutcome loopback_open_outcome,
ReferenceOpenOutcome expected_reference_open_outcome);
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_ =
base::SingleThreadTaskRunner::GetCurrentDefault();
scoped_refptr<base::SingleThreadTaskRunner> audio_thread_task_runner_ =
base::ThreadPool::CreateSingleThreadTaskRunner(
{},
base::SingleThreadTaskRunnerThreadMode::DEDICATED);
StrictMock<LocalMockAudioManager> audio_manager_;
std::unique_ptr<LoopbackReferenceManager> loopback_reference_manager_;
const media::AudioParameters loopback_params_ =
media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::ChannelLayoutConfig::Stereo(),
48000,
480);
const std::string loopback_device_id_ =
media::AudioDeviceDescription::kLoopbackAllDevicesId;
const std::string output_device_id_ =
media::AudioDeviceDescription::kDefaultDeviceId;
};
MATCHER_P(FirstSampleEquals, sample_value, "") {
return arg.channel_span(0)[0] == sample_value;
}
MATCHER_P(AudioParamsMatches, expected, "") {
return !(arg < expected) && !(expected < arg);
}
MATCHER_P(RunLogCallback, test_message, "") {
arg.Run(test_message);
return true;
}
std::unique_ptr<StrictMock<MockAudioInputStream>>
LoopbackReferenceManagerTest::ExpectCreateLoopbackStream(int component_id) {
auto mock_input_stream = std::make_unique<StrictMock<MockAudioInputStream>>();
EXPECT_CALL(audio_manager_, GetInputStreamParameters(loopback_device_id_))
.WillOnce(Return(loopback_params_));
EXPECT_CALL(audio_manager_,
CreateAudioLog(
media::AudioLogFactory::AudioComponent::kAudioInputController,
component_id))
.WillOnce(Return(std::make_unique<NiceMock<MockAudioLog>>()));
EXPECT_CALL(audio_manager_,
MakeAudioInputStream(AudioParamsMatches(loopback_params_),
loopback_device_id_, _))
.WillOnce(Return(mock_input_stream.get()));
EXPECT_CALL(*mock_input_stream, Open())
.WillOnce(Return(media::AudioInputStream::OpenOutcome::kSuccess));
EXPECT_CALL(*mock_input_stream, Stop());
EXPECT_CALL(*mock_input_stream, Close());
return mock_input_stream;
}
TEST_F(LoopbackReferenceManagerTest, DistributesAudioToListenersSameProvider) {
StrictMock<MockAudioInputStream> mock_input_stream;
std::unique_ptr<StrictMock<MockAudioLog>> mock_audio_log =
std::make_unique<StrictMock<MockAudioLog>>();
StrictMock<MockAudioLog>* mock_audio_log_raw_ptr = mock_audio_log.get();
std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(loopback_params_);
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider =
loopback_reference_manager_->GetReferenceSignalProvider();
EXPECT_CALL(audio_manager_, GetInputStreamParameters(loopback_device_id_))
.WillOnce(Return(loopback_params_));
EXPECT_CALL(audio_manager_,
CreateAudioLog(
media::AudioLogFactory::AudioComponent::kAudioInputController,
1000000))
.WillOnce(Return(std::move(mock_audio_log)));
EXPECT_CALL(audio_manager_,
MakeAudioInputStream(AudioParamsMatches(loopback_params_),
loopback_device_id_,
RunLogCallback("LOG CALLBACK TEST MESSAGE")))
.WillOnce(Return(&mock_input_stream));
EXPECT_CALL(mock_input_stream, Open())
.WillOnce(Return(media::AudioInputStream::OpenOutcome::kSuccess));
EXPECT_CALL(
*mock_audio_log_raw_ptr,
OnCreated(AudioParamsMatches(loopback_params_), loopback_device_id_));
EXPECT_CALL(*mock_audio_log_raw_ptr, OnStarted());
StrictMock<MockListener> mock_listener_1;
reference_signal_provider->StartListening(&mock_listener_1,
output_device_id_);
EXPECT_THAT(mock_audio_log_raw_ptr->logged_messages,
::testing::HasSubstr("LOG CALLBACK TEST MESSAGE"));
CHECK(mock_input_stream.captured_callback_);
AudioInputCallback* audio_callback = *(mock_input_stream.captured_callback_);
EXPECT_CALL(mock_listener_1,
OnPlayoutData(FirstSampleEquals(111),
loopback_params_.sample_rate(), base::TimeDelta()));
audio_bus->channel_span(0)[0] = 111;
audio_callback->OnData(audio_bus.get(), base::TimeTicks::Now(), 0, {});
StrictMock<MockListener> mock_listener_2;
reference_signal_provider->StartListening(&mock_listener_2,
output_device_id_);
EXPECT_CALL(mock_listener_1,
OnPlayoutData(FirstSampleEquals(222),
loopback_params_.sample_rate(), base::TimeDelta()));
EXPECT_CALL(mock_listener_2,
OnPlayoutData(FirstSampleEquals(222),
loopback_params_.sample_rate(), base::TimeDelta()));
audio_bus->channel_span(0)[0] = 222;
audio_callback->OnData(audio_bus.get(), base::TimeTicks::Now(), 0, {});
reference_signal_provider->StopListening(&mock_listener_1);
EXPECT_CALL(mock_listener_2,
OnPlayoutData(FirstSampleEquals(333),
loopback_params_.sample_rate(), base::TimeDelta()));
audio_bus->channel_span(0)[0] = 333;
audio_callback->OnData(audio_bus.get(), base::TimeTicks::Now(), 0, {});
EXPECT_CALL(mock_input_stream, Stop());
EXPECT_CALL(*mock_audio_log_raw_ptr, OnStopped());
EXPECT_CALL(mock_input_stream, Close());
EXPECT_CALL(*mock_audio_log_raw_ptr, OnClosed());
reference_signal_provider->StopListening(&mock_listener_2);
reference_signal_provider->StopListening(&mock_listener_2);
}
TEST_F(LoopbackReferenceManagerTest,
DistributesAudioToListenersSeparateProviders) {
std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(loopback_params_);
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider_1 =
loopback_reference_manager_->GetReferenceSignalProvider();
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider_2 =
loopback_reference_manager_->GetReferenceSignalProvider();
std::unique_ptr<StrictMock<MockAudioInputStream>> mock_input_stream =
ExpectCreateLoopbackStream(1000000);
StrictMock<MockListener> mock_listener_1;
reference_signal_provider_1->StartListening(&mock_listener_1,
output_device_id_);
CHECK(mock_input_stream->captured_callback_);
AudioInputCallback* audio_callback = *(mock_input_stream->captured_callback_);
EXPECT_CALL(mock_listener_1,
OnPlayoutData(FirstSampleEquals(111),
loopback_params_.sample_rate(), base::TimeDelta()));
audio_bus->channel_span(0)[0] = 111;
audio_callback->OnData(audio_bus.get(), base::TimeTicks::Now(), 0, {});
StrictMock<MockListener> mock_listener_2;
reference_signal_provider_2->StartListening(&mock_listener_2,
output_device_id_);
EXPECT_CALL(mock_listener_1,
OnPlayoutData(FirstSampleEquals(222),
loopback_params_.sample_rate(), base::TimeDelta()));
EXPECT_CALL(mock_listener_2,
OnPlayoutData(FirstSampleEquals(222),
loopback_params_.sample_rate(), base::TimeDelta()));
audio_bus->channel_span(0)[0] = 222;
audio_callback->OnData(audio_bus.get(), base::TimeTicks::Now(), 0, {});
reference_signal_provider_1->StopListening(&mock_listener_1);
EXPECT_CALL(mock_listener_2,
OnPlayoutData(FirstSampleEquals(333),
loopback_params_.sample_rate(), base::TimeDelta()));
audio_bus->channel_span(0)[0] = 333;
audio_callback->OnData(audio_bus.get(), base::TimeTicks::Now(), 0, {});
reference_signal_provider_2->StopListening(&mock_listener_2);
}
TEST_F(LoopbackReferenceManagerTest,
OpensAndClosesStreamWithMultipleListenCycles) {
std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(loopback_params_);
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider =
loopback_reference_manager_->GetReferenceSignalProvider();
StrictMock<MockListener> mock_listener;
std::unique_ptr<StrictMock<MockAudioInputStream>> mock_input_stream_1 =
ExpectCreateLoopbackStream(1000000);
reference_signal_provider->StartListening(&mock_listener, output_device_id_);
CHECK(mock_input_stream_1->captured_callback_);
AudioInputCallback* audio_callback_1 =
*(mock_input_stream_1->captured_callback_);
EXPECT_CALL(mock_listener,
OnPlayoutData(FirstSampleEquals(111),
loopback_params_.sample_rate(), base::TimeDelta()));
audio_bus->channel_span(0)[0] = 111;
audio_callback_1->OnData(audio_bus.get(), base::TimeTicks::Now(), 0, {});
reference_signal_provider->StopListening(&mock_listener);
std::unique_ptr<StrictMock<MockAudioInputStream>> mock_input_stream_2 =
ExpectCreateLoopbackStream(1000001);
reference_signal_provider->StartListening(&mock_listener, output_device_id_);
CHECK(mock_input_stream_2->captured_callback_);
AudioInputCallback* audio_callback_2 =
*(mock_input_stream_2->captured_callback_);
EXPECT_CALL(mock_listener,
OnPlayoutData(FirstSampleEquals(222),
loopback_params_.sample_rate(), base::TimeDelta()));
audio_bus->channel_span(0)[0] = 222;
audio_callback_2->OnData(audio_bus.get(), base::TimeTicks::Now(), 0, {});
reference_signal_provider->StopListening(&mock_listener);
}
TEST_F(LoopbackReferenceManagerTest, StreamCreateError) {
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider =
loopback_reference_manager_->GetReferenceSignalProvider();
base::HistogramTester histogram_tester;
EXPECT_CALL(audio_manager_, GetInputStreamParameters(loopback_device_id_))
.WillOnce(Return(loopback_params_));
EXPECT_CALL(audio_manager_,
CreateAudioLog(
media::AudioLogFactory::AudioComponent::kAudioInputController,
1000000))
.WillOnce(Return(std::make_unique<NiceMock<MockAudioLog>>()));
EXPECT_CALL(audio_manager_,
MakeAudioInputStream(AudioParamsMatches(loopback_params_),
loopback_device_id_, _))
.WillOnce(Return(nullptr));
StrictMock<MockListener> mock_listener;
ReferenceOpenOutcome outcome = reference_signal_provider->StartListening(
&mock_listener, output_device_id_);
EXPECT_EQ(outcome, ReferenceOpenOutcome::STREAM_CREATE_ERROR);
histogram_tester.ExpectUniqueSample(
"Media.Audio.LoopbackReference.OpenResult",
static_cast<int>(ReferenceOpenOutcome::STREAM_CREATE_ERROR), 1);
histogram_tester.ExpectTotalCount(
"Media.Audio.LoopbackReference.HadRuntimeError", 0);
loopback_reference_manager_.reset();
histogram_tester.ExpectBucketCount(
"Media.Audio.LoopbackReference.HadRuntimeError", false, 1);
}
void LoopbackReferenceManagerTest::TestStreamOpenError(
OpenOutcome loopback_open_outcome,
ReferenceOpenOutcome expected_reference_open_outcome) {
StrictMock<MockAudioInputStream> mock_input_stream;
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider =
loopback_reference_manager_->GetReferenceSignalProvider();
base::HistogramTester histogram_tester;
EXPECT_CALL(audio_manager_, GetInputStreamParameters(loopback_device_id_))
.WillOnce(Return(loopback_params_));
EXPECT_CALL(audio_manager_,
CreateAudioLog(
media::AudioLogFactory::AudioComponent::kAudioInputController,
1000000))
.WillOnce(Return(std::make_unique<NiceMock<MockAudioLog>>()));
EXPECT_CALL(audio_manager_,
MakeAudioInputStream(AudioParamsMatches(loopback_params_),
loopback_device_id_, _))
.WillOnce(Return(&mock_input_stream));
EXPECT_CALL(mock_input_stream, Open())
.WillOnce(Return(loopback_open_outcome));
EXPECT_CALL(mock_input_stream, Close());
StrictMock<MockListener> mock_listener;
ReferenceOpenOutcome outcome = reference_signal_provider->StartListening(
&mock_listener, output_device_id_);
EXPECT_EQ(outcome, expected_reference_open_outcome);
histogram_tester.ExpectUniqueSample(
"Media.Audio.LoopbackReference.OpenResult",
static_cast<int>(expected_reference_open_outcome), 1);
histogram_tester.ExpectTotalCount(
"Media.Audio.LoopbackReference.HadRuntimeError", 0);
}
TEST_F(LoopbackReferenceManagerTest, StreamOpenError) {
TestStreamOpenError(OpenOutcome::kFailed,
ReferenceOpenOutcome::STREAM_OPEN_ERROR);
}
TEST_F(LoopbackReferenceManagerTest, StreamOpenSystemPermissionsError) {
TestStreamOpenError(
OpenOutcome::kFailedSystemPermissions,
ReferenceOpenOutcome::STREAM_OPEN_SYSTEM_PERMISSIONS_ERROR);
}
TEST_F(LoopbackReferenceManagerTest, StreamOpenDeviceInUseError) {
TestStreamOpenError(OpenOutcome::kFailedInUse,
ReferenceOpenOutcome::STREAM_OPEN_DEVICE_IN_USE_ERROR);
}
TEST_F(LoopbackReferenceManagerTest, OnReferenceStreamError) {
std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(loopback_params_);
base::HistogramTester histogram_tester;
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider_1 =
loopback_reference_manager_->GetReferenceSignalProvider();
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider_2 =
loopback_reference_manager_->GetReferenceSignalProvider();
std::unique_ptr<StrictMock<MockAudioInputStream>> mock_input_stream_1 =
ExpectCreateLoopbackStream(1000000);
StrictMock<MockListener> mock_listener_1;
EXPECT_EQ(ReferenceOpenOutcome::SUCCESS,
reference_signal_provider_1->StartListening(&mock_listener_1,
output_device_id_));
CHECK(mock_input_stream_1->captured_callback_);
AudioInputCallback* audio_callback =
*(mock_input_stream_1->captured_callback_);
audio_callback->OnError();
StrictMock<MockListener> mock_listener_2;
EXPECT_EQ(ReferenceOpenOutcome::SUCCESS,
reference_signal_provider_2->StartListening(&mock_listener_2,
output_device_id_));
EXPECT_CALL(mock_listener_1, OnReferenceStreamError());
EXPECT_CALL(mock_listener_2, OnReferenceStreamError());
task_environment_.FastForwardBy(base::TimeDelta());
{
StrictMock<MockListener> temp_mock_listener;
EXPECT_EQ(ReferenceOpenOutcome::STREAM_PREVIOUS_ERROR,
reference_signal_provider_1->StartListening(&temp_mock_listener,
output_device_id_));
}
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider_3 =
loopback_reference_manager_->GetReferenceSignalProvider();
std::unique_ptr<StrictMock<MockAudioInputStream>> mock_input_stream_2 =
ExpectCreateLoopbackStream(1000001);
{
StrictMock<MockListener> temp_mock_listener;
EXPECT_EQ(ReferenceOpenOutcome::SUCCESS,
reference_signal_provider_3->StartListening(&temp_mock_listener,
output_device_id_));
reference_signal_provider_3->StopListening(&temp_mock_listener);
}
histogram_tester.ExpectBucketCount(
"Media.Audio.LoopbackReference.OpenResult",
static_cast<int>(ReferenceOpenOutcome::SUCCESS), 3);
histogram_tester.ExpectBucketCount(
"Media.Audio.LoopbackReference.OpenResult",
static_cast<int>(ReferenceOpenOutcome::STREAM_PREVIOUS_ERROR), 1);
histogram_tester.ExpectUniqueSample(
"Media.Audio.LoopbackReference.HadRuntimeError", true, 1);
}
TEST_F(LoopbackReferenceManagerTest, StopListeningAfterOnError) {
std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(loopback_params_);
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider =
loopback_reference_manager_->GetReferenceSignalProvider();
std::unique_ptr<StrictMock<MockAudioInputStream>> mock_input_stream =
ExpectCreateLoopbackStream(1000000);
StrictMock<MockListener> mock_listener;
EXPECT_EQ(ReferenceOpenOutcome::SUCCESS,
reference_signal_provider->StartListening(&mock_listener,
output_device_id_));
CHECK(mock_input_stream->captured_callback_);
AudioInputCallback* audio_callback = *(mock_input_stream->captured_callback_);
audio_callback->OnError();
reference_signal_provider->StopListening(&mock_listener);
task_environment_.FastForwardBy(base::TimeDelta());
}
class ThreadedReferenceListener : public ReferenceOutput::Listener {
public:
ThreadedReferenceListener(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> audio_thread_task_runner,
base::WaitableEvent* on_playout_data_event)
: main_task_runner_(main_task_runner),
audio_thread_task_runner_(audio_thread_task_runner),
on_playout_data_event_(on_playout_data_event) {}
~ThreadedReferenceListener() override = default;
MOCK_METHOD(void,
MockOnPlayoutData,
(const media::AudioBus&, int, base::TimeDelta),
());
MOCK_METHOD(void, MockOnReferenceStreamError, (), ());
void OnPlayoutData(const media::AudioBus& audio_bus,
int sample_rate,
base::TimeDelta audio_delay) final {
CHECK(audio_thread_task_runner_->BelongsToCurrentThread());
MockOnPlayoutData(audio_bus, sample_rate, audio_delay);
on_playout_data_event_->Signal();
}
void OnReferenceStreamError() final {
CHECK(main_task_runner_->BelongsToCurrentThread());
MockOnReferenceStreamError();
}
private:
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> audio_thread_task_runner_;
raw_ptr<base::WaitableEvent> on_playout_data_event_;
};
TEST_F(LoopbackReferenceManagerTest, DeliversAudioOnAudioThread) {
std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(loopback_params_);
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider =
loopback_reference_manager_->GetReferenceSignalProvider();
std::unique_ptr<StrictMock<MockAudioInputStream>> mock_input_stream =
ExpectCreateLoopbackStream(1000000);
base::WaitableEvent on_playout_data_event;
StrictMock<ThreadedReferenceListener> threaded_listener(
main_task_runner_, audio_thread_task_runner_, &on_playout_data_event);
reference_signal_provider->StartListening(&threaded_listener,
output_device_id_);
CHECK(mock_input_stream->captured_callback_);
AudioInputCallback* audio_callback = *(mock_input_stream->captured_callback_);
audio_bus->channel_span(0)[0] = 111;
EXPECT_CALL(
threaded_listener,
MockOnPlayoutData(FirstSampleEquals(111), loopback_params_.sample_rate(),
base::TimeDelta()));
audio_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&AudioInputCallback::OnData,
base::Unretained(audio_callback), audio_bus.get(),
base::TimeTicks::Now(), 0, media::AudioGlitchInfo()));
EXPECT_TRUE(on_playout_data_event.TimedWait(base::Seconds(1)));
reference_signal_provider->StopListening(&threaded_listener);
}
TEST_F(LoopbackReferenceManagerTest, DeliversErrorsOnMainThread) {
std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(loopback_params_);
std::unique_ptr<ReferenceSignalProvider> reference_signal_provider =
loopback_reference_manager_->GetReferenceSignalProvider();
std::unique_ptr<StrictMock<MockAudioInputStream>> mock_input_stream =
ExpectCreateLoopbackStream(1000000);
base::WaitableEvent on_playout_data_event;
StrictMock<ThreadedReferenceListener> threaded_listener(
main_task_runner_, audio_thread_task_runner_, &on_playout_data_event);
reference_signal_provider->StartListening(&threaded_listener,
output_device_id_);
CHECK(mock_input_stream->captured_callback_);
AudioInputCallback* audio_callback = *(mock_input_stream->captured_callback_);
base::WaitableEvent fired_error_event;
audio_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(
[](base::WaitableEvent* fired_error_event,
AudioInputCallback* audio_callback) {
audio_callback->OnError();
fired_error_event->Signal();
},
&fired_error_event, audio_callback));
EXPECT_TRUE(fired_error_event.TimedWait(base::Seconds(1)));
EXPECT_CALL(threaded_listener, MockOnReferenceStreamError());
task_environment_.FastForwardBy(base::TimeDelta());
}
}
}