blob: b92aa59a218bab3ce217eee888958d2d0da17743 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fuchsia/media/audio/cpp/fidl.h>
#include <fuchsia/media/cpp/fidl.h>
#include <cmath>
#include <memory>
#include "src/media/audio/lib/test/constants.h"
#include "src/media/audio/lib/test/hermetic_audio_test.h"
#include "src/media/audio/lib/test/test_fixture.h"
namespace media::audio::test {
namespace {
class FakeGainListener : public fuchsia::media::UsageGainListener {
public:
explicit FakeGainListener(TestFixture* fixture) : binding_(this) {
fixture->AddErrorHandler(binding_, "FakeGainListener");
}
fidl::InterfaceHandle<fuchsia::media::UsageGainListener> NewBinding() {
return binding_.NewBinding();
}
using Handler = std::function<void(bool muted, float gain_db)>;
void SetNextHandler(Handler h) { next_handler_ = h; }
private:
// |fuchsia::media::UsageGainListener|
void OnGainMuteChanged(bool muted, float gain_db, OnGainMuteChangedCallback callback) final {
if (next_handler_) {
next_handler_(muted, gain_db);
next_handler_ = nullptr;
}
callback();
}
fidl::Binding<fuchsia::media::UsageGainListener> binding_;
Handler next_handler_;
};
} // namespace
class UsageGainReporterTest : public HermeticAudioTest {
public:
void SetUp() {
HermeticAudioTest::SetUp();
// We need to create an output device to listen on.
// The specific choice of format doesn't matter here, any format will do.
constexpr auto kSampleFormat = fuchsia::media::AudioSampleFormat::SIGNED_16;
constexpr auto kSampleRate = 48000;
auto format = Format::Create<kSampleFormat>(2, kSampleRate).value();
CreateOutput(device_id_array_, format, kSampleRate /* 1s buffer */);
}
struct Controller {
Controller(TestFixture* fixture) : fake_listener(fixture) {}
fuchsia::media::audio::VolumeControlPtr volume_control;
fuchsia::media::UsageGainReporterPtr gain_reporter;
FakeGainListener fake_listener;
};
std::unique_ptr<Controller> CreateController(fuchsia::media::AudioRenderUsage u) {
fuchsia::media::Usage usage = fuchsia::media::Usage::WithRenderUsage(std::move(u));
auto c = std::make_unique<Controller>(this);
audio_core_->BindUsageVolumeControl(fidl::Clone(usage), c->volume_control.NewRequest());
AddErrorHandler(c->volume_control, "VolumeControl");
environment()->ConnectToService(c->gain_reporter.NewRequest());
AddErrorHandler(c->gain_reporter, "GainReporter");
c->gain_reporter->RegisterListener(device_id_string_, fidl::Clone(usage),
c->fake_listener.NewBinding());
return c;
}
// The device ID is arbitrary.
const std::string device_id_string_ = "ff000000000000000000000000000000";
const audio_stream_unique_id_t device_id_array_ = {{
0xff,
0x00,
}};
};
TEST_F(UsageGainReporterTest, SetVolumeAndMute) {
auto c = CreateController(fuchsia::media::AudioRenderUsage::MEDIA);
// The initial callback happens immediately.
c->fake_listener.SetNextHandler(AddCallback("OnGainMuteChanged InitialCall"));
ExpectCallback();
bool last_muted;
float last_gain_db;
auto set_callback = [this, &c, &last_muted, &last_gain_db](std::string stage) {
last_muted = true;
last_gain_db = kTooHighGainDb;
c->fake_listener.SetNextHandler(
AddCallback("OnGainMuteChanged after " + stage,
[&last_muted, &last_gain_db](bool muted, float gain_db) {
last_muted = muted;
last_gain_db = gain_db;
}));
};
set_callback("SetVolume(0)");
c->volume_control->SetVolume(0);
ExpectCallback();
EXPECT_FALSE(last_muted);
EXPECT_FLOAT_EQ(last_gain_db, fuchsia::media::audio::MUTED_GAIN_DB);
set_callback("SetVolume(1)");
c->volume_control->SetVolume(1);
ExpectCallback();
EXPECT_FALSE(last_muted);
EXPECT_FLOAT_EQ(last_gain_db, 0);
// TODO(54949): SetMute(true) events are broken
#if 0
set_callback("SetMute(true)");
c->volume_control->SetMute(true);
ExpectCallback();
EXPECT_TRUE(last_muted);
EXPECT_FLOAT_EQ(last_gain_db, fuchsia::media::audio::MUTED_GAIN_DB);
// Unmute should restore the volume.
set_callback("SetMute(false)");
c->volume_control->SetMute(false);
ExpectCallback();
EXPECT_FALSE(last_muted);
EXPECT_FLOAT_EQ(last_gain_db, 0);
#endif
}
TEST_F(UsageGainReporterTest, RoutedCorrectly) {
auto c1 = CreateController(fuchsia::media::AudioRenderUsage::MEDIA);
auto c2 = CreateController(fuchsia::media::AudioRenderUsage::BACKGROUND);
// The initial callbacks happen immediately.
c1->fake_listener.SetNextHandler(AddCallback("OnGainMuteChanged1 InitialCall"));
c2->fake_listener.SetNextHandler(AddCallback("OnGainMuteChanged2 InitialCall"));
ExpectCallback();
// Routing to c1.
c1->fake_listener.SetNextHandler(AddCallback("OnGainMuteChanged1 RouteTo1"));
c2->fake_listener.SetNextHandler(AddUnexpectedCallback("OnGainMuteChanged2 RouteTo1"));
c1->volume_control->SetVolume(0);
ExpectCallback();
// Routing to c2.
c1->fake_listener.SetNextHandler(AddUnexpectedCallback("OnGainMuteChanged1 RouteTo2"));
c2->fake_listener.SetNextHandler(AddCallback("OnGainMuteChanged2 RouteTo2"));
c2->volume_control->SetVolume(0);
ExpectCallback();
}
} // namespace media::audio::test