blob: cc490ce65c455e834c185ceb9755859eff3c3303 [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 "src/media/audio/audio_core/usage_gain_reporter_impl.h"
#include <lib/fidl/cpp/binding.h>
#include <gtest/gtest.h>
#include "src/media/audio/audio_core/testing/threading_model_fixture.h"
#include "src/media/audio/lib/logging/logging.h"
namespace media::audio {
namespace {
const std::string DEVICE_ID_STRING = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
const audio_stream_unique_id_t DEVICE_ID_AUDIO_STREAM =
AudioDevice::UniqueIdFromString(DEVICE_ID_STRING).take_value();
const std::string BLUETOOTH_DEVICE_ID_STRING = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
const audio_stream_unique_id_t BLUETOOTH_DEVICE_ID_AUDIO_STREAM =
AudioDevice::UniqueIdFromString(BLUETOOTH_DEVICE_ID_STRING).take_value();
class FakeGainListener : public fuchsia::media::UsageGainListener {
public:
fidl::InterfaceHandle<fuchsia::media::UsageGainListener> NewBinding() {
return binding_.NewBinding();
}
void CloseBinding() { binding_.Close(0); }
bool muted() const { return last_muted_; }
float gain_dbfs() const { return last_gain_dbfs_; }
size_t call_count() const { return call_count_; }
private:
// |fuchsia::media::UsageGainListener|
void OnGainMuteChanged(bool muted, float gain_dbfs, OnGainMuteChangedCallback callback) final {
last_muted_ = muted;
last_gain_dbfs_ = gain_dbfs;
call_count_++;
}
fidl::Binding<fuchsia::media::UsageGainListener> binding_{this};
bool last_muted_ = false;
float last_gain_dbfs_ = 0.0;
size_t call_count_ = 0;
};
class TestDeviceRegistry : public DeviceRegistry {
public:
void AddDeviceInfo(fuchsia::media::AudioDeviceInfo device_info) {
device_info_.push_back(device_info);
}
// |DeviceRegistry|
void AddDevice(const std::shared_ptr<AudioDevice>& device) final {}
void ActivateDevice(const std::shared_ptr<AudioDevice>& device) final {}
void RemoveDevice(const std::shared_ptr<AudioDevice>& device) final {}
void OnPlugStateChanged(const std::shared_ptr<AudioDevice>& device, bool plugged,
zx::time plug_time) final {}
std::vector<fuchsia::media::AudioDeviceInfo> GetDeviceInfos() final { return device_info_; }
private:
std::vector<fuchsia::media::AudioDeviceInfo> device_info_;
};
} // namespace
class UsageGainReporterTest : public gtest::TestLoopFixture {
protected:
UsageGainReporterTest()
: process_config_(
ProcessConfigBuilder()
.SetDefaultVolumeCurve(VolumeCurve::DefaultForMinGain(-60.0))
.AddDeviceProfile({std::vector<audio_stream_unique_id_t>{DEVICE_ID_AUDIO_STREAM},
DeviceConfig::OutputDeviceProfile(
/* eligible_for_loopback=*/true, /*supported_usages=*/{})})
.AddDeviceProfile(
{std::vector<audio_stream_unique_id_t>{BLUETOOTH_DEVICE_ID_AUDIO_STREAM},
DeviceConfig::OutputDeviceProfile(
/* eligible_for_loopback=*/true,
/*supported_usages=*/{}, VolumeCurve::DefaultForMinGain(-60.0),
/* independent_volume_control=*/true, PipelineConfig::Default(),
/*driver_gain_db=*/0.0)})
.Build()),
usage_(fuchsia::media::Usage::WithRenderUsage(fuchsia::media::AudioRenderUsage::MEDIA)) {}
std::unique_ptr<FakeGainListener> Listen(std::string device_id) {
const auto handle = ProcessConfig::set_instance(process_config_);
auto device_registry = std::make_unique<TestDeviceRegistry>();
device_registry->AddDeviceInfo({.unique_id = device_id});
stream_volume_manager_ = std::make_unique<StreamVolumeManager>(dispatcher());
under_test_ = std::make_unique<UsageGainReporterImpl>(
*device_registry.get(), *stream_volume_manager_.get(), process_config_);
auto fake_gain_listener = std::make_unique<FakeGainListener>();
under_test_->RegisterListener(device_id, fidl::Clone(usage_), fake_gain_listener->NewBinding());
return fake_gain_listener;
}
size_t NumListeners() { return under_test_->listeners_.size(); }
std::unique_ptr<StreamVolumeManager> stream_volume_manager_;
std::unique_ptr<UsageGainReporterImpl> under_test_;
ProcessConfig process_config_;
const fuchsia::media::Usage usage_;
};
TEST_F(UsageGainReporterTest, UpdatesSingleListenerUsageGain) {
auto fake_listener = Listen(DEVICE_ID_STRING);
const float expected_gain_dbfs = -10.0;
stream_volume_manager_->SetUsageGain(fidl::Clone(usage_), expected_gain_dbfs);
RunLoopUntilIdle();
EXPECT_FLOAT_EQ(fake_listener->gain_dbfs(), expected_gain_dbfs);
EXPECT_EQ(fake_listener->call_count(), 2u);
}
TEST_F(UsageGainReporterTest, UpdatesSingleListenerUsageGainAdjustment) {
auto fake_listener = Listen(DEVICE_ID_STRING);
const float expected_gain_dbfs = -10.0;
stream_volume_manager_->SetUsageGainAdjustment(fidl::Clone(usage_), expected_gain_dbfs);
RunLoopUntilIdle();
EXPECT_FLOAT_EQ(fake_listener->gain_dbfs(), expected_gain_dbfs);
EXPECT_EQ(fake_listener->call_count(), 2u);
}
TEST_F(UsageGainReporterTest, UpdatesSingleListenerUsageGainCombination) {
auto fake_listener = Listen(DEVICE_ID_STRING);
const float expected_gain_dbfs = -10.0;
stream_volume_manager_->SetUsageGain(fidl::Clone(usage_), expected_gain_dbfs);
stream_volume_manager_->SetUsageGainAdjustment(fidl::Clone(usage_), expected_gain_dbfs);
RunLoopUntilIdle();
EXPECT_FLOAT_EQ(fake_listener->gain_dbfs(), (2 * expected_gain_dbfs));
EXPECT_EQ(fake_listener->call_count(), 3u);
}
TEST_F(UsageGainReporterTest, NoUpdateIndependentVolumeControlSingleListener) {
auto fake_listener = Listen(BLUETOOTH_DEVICE_ID_STRING);
const float attempted_gain_dbfs = -10.0;
stream_volume_manager_->SetUsageGain(fidl::Clone(usage_), attempted_gain_dbfs);
RunLoopUntilIdle();
EXPECT_FLOAT_EQ(fake_listener->gain_dbfs(), 0.0f);
EXPECT_EQ(fake_listener->call_count(), 0u);
}
TEST_F(UsageGainReporterTest, HandlesClosedChannel) {
auto fake_listener = Listen(DEVICE_ID_STRING);
RunLoopUntilIdle();
EXPECT_EQ(fake_listener->call_count(), 1u);
EXPECT_EQ(NumListeners(), 1ul);
fake_listener->CloseBinding();
RunLoopUntilIdle();
EXPECT_EQ(NumListeners(), 0ul);
// Destruct.
fake_listener = nullptr;
// Verify we removed the listener from StreamVolumeManager.
// If we did not, this will crash.
stream_volume_manager_->SetUsageGain(
fuchsia::media::Usage::WithRenderUsage(fuchsia::media::AudioRenderUsage::MEDIA), 0.42);
}
} // namespace media::audio