/* * 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 #include #include #include #include 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&), (override)); }; class SoundDoseManagerTest : public ::testing::Test { protected: void SetUp() override { mSoundDoseManager = sp::make(); mHalSoundDose = ndk::SharedRefBase::make(); ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound) .WillByDefault([] (float rs2) { EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2); return ndk::ScopedAStatus::ok(); }); } sp mSoundDoseManager; std::shared_ptr mHalSoundDose; }; TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) { sp processor1 = mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1, /*streamHandle=*/1, /*sampleRate*/44100, /*channelCount*/2, /*format*/AUDIO_FORMAT_PCM_FLOAT); sp 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 processor1 = mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1, /*streamHandle=*/1, /*sampleRate*/44100, /*channelCount*/2, /*format*/AUDIO_FORMAT_PCM_FLOAT); mSoundDoseManager->removeStreamProcessor(1); sp 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::vectormels{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& 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& callback) { EXPECT_NE(nullptr, callback); return ndk::ScopedAStatus::ok(); }); EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose)); } TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) { std::shared_ptr halCallback; EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound).Times(1); EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback) .Times(1) .WillOnce([&] (const std::shared_ptr& callback) { halCallback = callback; return ndk::ScopedAStatus::ok(); }); EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose)); EXPECT_NE(nullptr, halCallback); AudioDevice audioDevice = {}; audioDevice.address.set("test"); auto status = halCallback->onMomentaryExposureWarning( /*in_currentDbA=*/101.f, audioDevice); EXPECT_FALSE(status.isOk()); } TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalAfterInternalSelectedReturnsException) { std::shared_ptr halCallback; EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound).Times(1); EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback) .Times(1) .WillOnce([&] (const std::shared_ptr& 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("test"); auto status = halCallback->onMomentaryExposureWarning( /*in_currentDbA=*/101.f, audioDevice); EXPECT_FALSE(status.isOk()); } TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument) { std::shared_ptr halCallback; EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound).Times(1); EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback) .Times(1) .WillOnce([&] (const std::shared_ptr& callback) { halCallback = callback; return ndk::ScopedAStatus::ok(); }); EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose)); EXPECT_NE(nullptr, halCallback); AudioDevice audioDevice = {}; audioDevice.address.set("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(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