blob: b3f98a4e55b2922abc3589f63857cfeb226c5313 [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/shared/usage_gain_reporter_impl.h"
#include <lib/fidl/cpp/binding.h>
#include <lib/syslog/cpp/macros.h>
#include <gtest/gtest.h>
#include "src/lib/testing/loop_fixture/test_loop_fixture.h"
#include "src/media/audio/audio_core/shared/device_id.h"
namespace media::audio {
namespace {
const std::string DEVICE_ID_STRING = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
const audio_stream_unique_id_t DEVICE_ID_AUDIO_STREAM =
DeviceUniqueIdFromString(DEVICE_ID_STRING).take_value();
const std::string BLUETOOTH_DEVICE_ID_STRING = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
const audio_stream_unique_id_t BLUETOOTH_DEVICE_ID_AUDIO_STREAM =
DeviceUniqueIdFromString(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 TestDeviceLister : public DeviceLister {
public:
void AddDeviceInfo(fuchsia::media::AudioDeviceInfo device_info) {
device_info_.push_back(device_info);
}
// |DeviceLister|
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, /*software_gain_db=*/0.0)})
.Build()),
usage_(fuchsia::media::Usage::WithRenderUsage(fuchsia::media::AudioRenderUsage::MEDIA)) {}
std::unique_ptr<FakeGainListener> Listen(std::string device_id) {
auto device_lister = std::make_unique<TestDeviceLister>();
device_lister->AddDeviceInfo({.unique_id = device_id});
stream_volume_manager_ = std::make_unique<StreamVolumeManager>(dispatcher());
under_test_ = std::make_unique<UsageGainReporterImpl>(
*device_lister.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.42f);
}
} // namespace media::audio