blob: 9fab77d56740448f58a38edee19a0a67b7da1501 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// #define LOG_NDEBUG 0
#define LOG_TAG "SoundDoseManager_tests"
#include <SoundDoseManager.h>
#include <aidl/android/hardware/audio/core/sounddose/BnSoundDose.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <media/AidlConversionCppNdk.h>
namespace android {
namespace {
using aidl::android::hardware::audio::core::sounddose::BnSoundDose;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
class HalSoundDoseMock : public BnSoundDose {
public:
MOCK_METHOD(ndk::ScopedAStatus, getOutputRs2UpperBound, (float*), (override));
MOCK_METHOD(ndk::ScopedAStatus, setOutputRs2UpperBound, (float), (override));
MOCK_METHOD(ndk::ScopedAStatus, registerSoundDoseCallback,
(const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>&), (override));
};
class SoundDoseManagerTest : public ::testing::Test {
protected:
void SetUp() override {
mSoundDoseManager = sp<SoundDoseManager>::make();
mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound)
.WillByDefault([] (float rs2) {
EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
return ndk::ScopedAStatus::ok();
});
}
sp<SoundDoseManager> mSoundDoseManager;
std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
};
TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) {
sp<audio_utils::MelProcessor> processor1 =
mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT);
sp<audio_utils::MelProcessor> processor2 =
mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT);
EXPECT_EQ(processor1, processor2);
}
TEST_F(SoundDoseManagerTest, RemoveExistingStream) {
sp<audio_utils::MelProcessor> processor1 =
mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT);
mSoundDoseManager->removeStreamProcessor(1);
sp<audio_utils::MelProcessor> processor2 =
mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT);
EXPECT_NE(processor1, processor2);
}
TEST_F(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
std::vector<float>mels{1, 1};
mSoundDoseManager->onNewMelValues(mels, 0, mels.size(), /*deviceId=*/1);
EXPECT_EQ(mSoundDoseManager->getCachedMelRecordsSize(), size_t{1});
}
TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) {
EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
}
TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
.Times(1)
.WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
EXPECT_NE(nullptr, callback);
return ndk::ScopedAStatus::ok();
});
EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT));
}
TEST_F(SoundDoseManagerTest, SetHalSoundDoseRegistersHalCallbacks) {
EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
.Times(1)
.WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
EXPECT_NE(nullptr, callback);
return ndk::ScopedAStatus::ok();
});
EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
}
TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) {
std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
.Times(1)
.WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
halCallback = callback;
return ndk::ScopedAStatus::ok();
});
EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
AudioDevice audioDevice = {};
audioDevice.address.set<AudioDeviceAddress::id>("test");
auto status = halCallback->onMomentaryExposureWarning(
/*in_currentDbA=*/101.f, audioDevice);
EXPECT_FALSE(status.isOk());
}
TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalAfterInternalSelectedReturnsException) {
std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
.Times(1)
.WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
halCallback = callback;
return ndk::ScopedAStatus::ok();
});
EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
AudioDevice audioDevice = {};
audioDevice.address.set<AudioDeviceAddress::id>("test");
auto status = halCallback->onMomentaryExposureWarning(
/*in_currentDbA=*/101.f, audioDevice);
EXPECT_FALSE(status.isOk());
}
TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument) {
std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
.Times(1)
.WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
halCallback = callback;
return ndk::ScopedAStatus::ok();
});
EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
AudioDevice audioDevice = {};
audioDevice.address.set<AudioDeviceAddress::id>("test");
auto status = halCallback->onNewMelValues(/*in_melRecord=*/{}, audioDevice);
EXPECT_FALSE(status.isOk());
}
TEST_F(SoundDoseManagerTest, GetIdReturnsMappedAddress) {
const std::string address = "testAddress";
const audio_port_handle_t deviceId = 2;
const audio_devices_t deviceType = AUDIO_DEVICE_OUT_WIRED_HEADSET;
const AudioDeviceTypeAddr adt{deviceType, address};
auto audioDevice = aidl::android::legacy2aidl_audio_device_AudioDevice(
deviceType, address.c_str());
ASSERT_TRUE(audioDevice.ok());
mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
EXPECT_EQ(deviceId, mSoundDoseManager->getIdForAudioDevice(audioDevice.value()));
}
TEST_F(SoundDoseManagerTest, GetAfterClearIdReturnsNone) {
const std::string address = "testAddress";
const audio_devices_t deviceType = AUDIO_DEVICE_OUT_WIRED_HEADSET;
const AudioDeviceTypeAddr adt{deviceType, address};
const audio_port_handle_t deviceId = 2;
auto audioDevice = aidl::android::legacy2aidl_audio_device_AudioDevice(
deviceType, address.c_str());
ASSERT_TRUE(audioDevice.ok());
mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice.value()));
}
TEST_F(SoundDoseManagerTest, GetUnmappedIdReturnsHandleNone) {
const std::string address = "testAddress";
AudioDevice audioDevice;
audioDevice.address.set<AudioDeviceAddress::id>(address);
EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice));
}
TEST_F(SoundDoseManagerTest, GetDefaultForceComputeCsdOnAllDevices) {
EXPECT_FALSE(mSoundDoseManager->forceComputeCsdOnAllDevices());
}
TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) {
// TODO: for now dogfooding with internal MEL. Revert to false when using the HAL MELs
EXPECT_TRUE(mSoundDoseManager->forceUseFrameworkMel());
}
} // namespace
} // namespace android