Loading media/libaudioclient/aidl/android/media/ISoundDose.aidl +13 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,19 @@ interface ISoundDose { */ oneway void resetCsd(float currentCsd, in SoundDoseRecord[] records); /** * Updates the attenuation used for the MEL calculation when the volume is * not applied by the audio framework. This can be the case when for example * the absolute volume is used for a particular device. * * @param attenuationDB the attenuation as a negative value in dB that will * be applied for the internal MEL when computing CSD. * A value of 0 represents no attenuation for the MELs * @param device the audio_devices_t type for which we will apply the * attenuation */ oneway void updateAttenuation(float attenuationDB, int device); /* -------------------------- Test API methods -------------------------- /** Get the currently used RS2 value. */ float getOutputRs2(); Loading services/audioflinger/sounddose/SoundDoseManager.cpp +37 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,10 @@ sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice( if (streamProcessor != mActiveProcessors.end() && (processor = streamProcessor->second.promote())) { ALOGV("%s: found callback for stream %d", __func__, streamHandle); const auto activeTypeIt = mActiveDeviceTypes.find(deviceId); if (activeTypeIt != mActiveDeviceTypes.end()) { processor->setAttenuation(mMelAttenuationDB[activeTypeIt->second]); } processor->setDeviceId(deviceId); processor->setOutputRs2(mRs2Value); return processor; Loading @@ -71,6 +75,10 @@ sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice( ALOGV("%s: creating new callback for device %d", __func__, streamHandle); sp<audio_utils::MelProcessor> melProcessor = sp<audio_utils::MelProcessor>::make( sampleRate, channelCount, format, *this, deviceId, mRs2Value); const auto activeTypeIt = mActiveDeviceTypes.find(deviceId); if (activeTypeIt != mActiveDeviceTypes.end()) { melProcessor->setAttenuation(mMelAttenuationDB[activeTypeIt->second]); } mActiveProcessors[streamHandle] = melProcessor; return melProcessor; } Loading Loading @@ -174,6 +182,7 @@ void SoundDoseManager::mapAddressToDeviceId(const AudioDeviceTypeAddr& adt, std::lock_guard _l(mLock); ALOGI("%s: map address: %s to device id: %d", __func__, adt.toString().c_str(), deviceId); mActiveDevices[adt] = deviceId; mActiveDeviceTypes[deviceId] = adt.mType; } void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) { Loading @@ -187,6 +196,7 @@ void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) { } ++activeDevice; } mActiveDeviceTypes.erase(deviceId); } ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning( Loading Loading @@ -272,6 +282,15 @@ binder::Status SoundDoseManager::SoundDose::resetCsd( return binder::Status::ok(); } binder::Status SoundDoseManager::SoundDose::updateAttenuation(float attenuationDB, int device) { ALOGV("%s", __func__); auto soundDoseManager = mSoundDoseManager.promote(); if (soundDoseManager != nullptr) { soundDoseManager->updateAttenuation(attenuationDB, static_cast<audio_devices_t>(device)); } return binder::Status::ok(); } binder::Status SoundDoseManager::SoundDose::getOutputRs2(float* value) { ALOGV("%s", __func__); auto soundDoseManager = mSoundDoseManager.promote(); Loading Loading @@ -310,6 +329,24 @@ binder::Status SoundDoseManager::SoundDose::forceComputeCsdOnAllDevices( return binder::Status::ok(); } void SoundDoseManager::updateAttenuation(float attenuationDB, audio_devices_t deviceType) { std::lock_guard _l(mLock); ALOGV("%s: updating MEL processor attenuation for device %d to %f", __func__, deviceType, attenuationDB); mMelAttenuationDB[deviceType] = attenuationDB; for (const auto& mp : mActiveProcessors) { auto melProcessor = mp.second.promote(); if (melProcessor != nullptr) { auto deviceId = melProcessor->getDeviceId(); if (mActiveDeviceTypes[deviceId] == deviceType) { ALOGV("%s: updating MEL processor attenuation for deviceId %d to %f", __func__, deviceId, attenuationDB); melProcessor->setAttenuation(attenuationDB); } } } } void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) { // invalidate any HAL sound dose interface used setHalSoundDoseInterface(nullptr); Loading services/audioflinger/sounddose/SoundDoseManager.h +10 −7 Original line number Diff line number Diff line Loading @@ -95,9 +95,8 @@ public: audio_port_handle_t getIdForAudioDevice( const aidl::android::media::audio::common::AudioDevice& audioDevice) const; /** Caches mapping between address and device port id. */ void mapAddressToDeviceId(const AudioDeviceTypeAddr& adt, const audio_port_handle_t deviceId); /** Caches mapping between address, device port id and device type. */ void mapAddressToDeviceId(const AudioDeviceTypeAddr& adt, const audio_port_handle_t deviceId); /** Clear all map entries with passed audio_port_handle_t. */ void clearMapDeviceIdEntries(audio_port_handle_t deviceId); Loading Loading @@ -133,10 +132,11 @@ private: binder::Status setOutputRs2(float value) override; binder::Status resetCsd(float currentCsd, const std::vector<media::SoundDoseRecord>& records) override; binder::Status getOutputRs2(float* value); binder::Status getCsd(float* value); binder::Status forceUseFrameworkMel(bool useFrameworkMel); binder::Status forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices); binder::Status updateAttenuation(float attenuationDB, int device) override; binder::Status getOutputRs2(float* value) override; binder::Status getCsd(float* value) override; binder::Status forceUseFrameworkMel(bool useFrameworkMel) override; binder::Status forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices) override; wp<SoundDoseManager> mSoundDoseManager; const sp<media::ISoundDoseCallback> mSoundDoseCallback; Loading @@ -163,6 +163,7 @@ private: sp<media::ISoundDoseCallback> getSoundDoseCallback() const; void updateAttenuation(float attenuationDB, audio_devices_t deviceType); void setUseFrameworkMel(bool useFrameworkMel); void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices); /** Returns the HAL sound dose interface or null if internal MEL computation is used. */ Loading @@ -180,8 +181,10 @@ private: // logic for deviceId's that should not report MEL values (e.g.: do not have an active MUSIC // or GAME stream). std::map<AudioDeviceTypeAddr, audio_port_handle_t> mActiveDevices GUARDED_BY(mLock); std::unordered_map<audio_port_handle_t, audio_devices_t> mActiveDeviceTypes GUARDED_BY(mLock); float mRs2Value GUARDED_BY(mLock); std::unordered_map<audio_devices_t, float> mMelAttenuationDB GUARDED_BY(mLock); sp<SoundDose> mSoundDose GUARDED_BY(mLock); Loading services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp +18 −9 Original line number Diff line number Diff line Loading @@ -17,11 +17,16 @@ // #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 <SoundDoseManager.h> #if !defined(BACKEND_NDK) #define BACKEND_NDK #endif #include <media/AidlConversionCppNdk.h> namespace android { namespace { Loading Loading @@ -199,26 +204,30 @@ TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument) TEST_F(SoundDoseManagerTest, GetIdReturnsMappedAddress) { const std::string address = "testAddress"; const audio_port_handle_t deviceId = 2; const AudioDeviceTypeAddr adt{audio_devices_t{0}, address}; AudioDevice audioDevice; audioDevice.address.set<AudioDeviceAddress::id>(address); 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)); EXPECT_EQ(deviceId, mSoundDoseManager->getIdForAudioDevice(audioDevice.value())); } TEST_F(SoundDoseManagerTest, GetAfterClearIdReturnsNone) { const std::string address = "testAddress"; const AudioDeviceTypeAddr adt {audio_devices_t{0}, address}; const audio_devices_t deviceType = AUDIO_DEVICE_OUT_WIRED_HEADSET; const AudioDeviceTypeAddr adt{deviceType, address}; const audio_port_handle_t deviceId = 2; AudioDevice audioDevice; audioDevice.address.set<AudioDeviceAddress::id>(address); 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)); EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice.value())); } TEST_F(SoundDoseManagerTest, GetUnmappedIdReturnsHandleNone) { Loading Loading
media/libaudioclient/aidl/android/media/ISoundDose.aidl +13 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,19 @@ interface ISoundDose { */ oneway void resetCsd(float currentCsd, in SoundDoseRecord[] records); /** * Updates the attenuation used for the MEL calculation when the volume is * not applied by the audio framework. This can be the case when for example * the absolute volume is used for a particular device. * * @param attenuationDB the attenuation as a negative value in dB that will * be applied for the internal MEL when computing CSD. * A value of 0 represents no attenuation for the MELs * @param device the audio_devices_t type for which we will apply the * attenuation */ oneway void updateAttenuation(float attenuationDB, int device); /* -------------------------- Test API methods -------------------------- /** Get the currently used RS2 value. */ float getOutputRs2(); Loading
services/audioflinger/sounddose/SoundDoseManager.cpp +37 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,10 @@ sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice( if (streamProcessor != mActiveProcessors.end() && (processor = streamProcessor->second.promote())) { ALOGV("%s: found callback for stream %d", __func__, streamHandle); const auto activeTypeIt = mActiveDeviceTypes.find(deviceId); if (activeTypeIt != mActiveDeviceTypes.end()) { processor->setAttenuation(mMelAttenuationDB[activeTypeIt->second]); } processor->setDeviceId(deviceId); processor->setOutputRs2(mRs2Value); return processor; Loading @@ -71,6 +75,10 @@ sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice( ALOGV("%s: creating new callback for device %d", __func__, streamHandle); sp<audio_utils::MelProcessor> melProcessor = sp<audio_utils::MelProcessor>::make( sampleRate, channelCount, format, *this, deviceId, mRs2Value); const auto activeTypeIt = mActiveDeviceTypes.find(deviceId); if (activeTypeIt != mActiveDeviceTypes.end()) { melProcessor->setAttenuation(mMelAttenuationDB[activeTypeIt->second]); } mActiveProcessors[streamHandle] = melProcessor; return melProcessor; } Loading Loading @@ -174,6 +182,7 @@ void SoundDoseManager::mapAddressToDeviceId(const AudioDeviceTypeAddr& adt, std::lock_guard _l(mLock); ALOGI("%s: map address: %s to device id: %d", __func__, adt.toString().c_str(), deviceId); mActiveDevices[adt] = deviceId; mActiveDeviceTypes[deviceId] = adt.mType; } void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) { Loading @@ -187,6 +196,7 @@ void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) { } ++activeDevice; } mActiveDeviceTypes.erase(deviceId); } ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning( Loading Loading @@ -272,6 +282,15 @@ binder::Status SoundDoseManager::SoundDose::resetCsd( return binder::Status::ok(); } binder::Status SoundDoseManager::SoundDose::updateAttenuation(float attenuationDB, int device) { ALOGV("%s", __func__); auto soundDoseManager = mSoundDoseManager.promote(); if (soundDoseManager != nullptr) { soundDoseManager->updateAttenuation(attenuationDB, static_cast<audio_devices_t>(device)); } return binder::Status::ok(); } binder::Status SoundDoseManager::SoundDose::getOutputRs2(float* value) { ALOGV("%s", __func__); auto soundDoseManager = mSoundDoseManager.promote(); Loading Loading @@ -310,6 +329,24 @@ binder::Status SoundDoseManager::SoundDose::forceComputeCsdOnAllDevices( return binder::Status::ok(); } void SoundDoseManager::updateAttenuation(float attenuationDB, audio_devices_t deviceType) { std::lock_guard _l(mLock); ALOGV("%s: updating MEL processor attenuation for device %d to %f", __func__, deviceType, attenuationDB); mMelAttenuationDB[deviceType] = attenuationDB; for (const auto& mp : mActiveProcessors) { auto melProcessor = mp.second.promote(); if (melProcessor != nullptr) { auto deviceId = melProcessor->getDeviceId(); if (mActiveDeviceTypes[deviceId] == deviceType) { ALOGV("%s: updating MEL processor attenuation for deviceId %d to %f", __func__, deviceId, attenuationDB); melProcessor->setAttenuation(attenuationDB); } } } } void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) { // invalidate any HAL sound dose interface used setHalSoundDoseInterface(nullptr); Loading
services/audioflinger/sounddose/SoundDoseManager.h +10 −7 Original line number Diff line number Diff line Loading @@ -95,9 +95,8 @@ public: audio_port_handle_t getIdForAudioDevice( const aidl::android::media::audio::common::AudioDevice& audioDevice) const; /** Caches mapping between address and device port id. */ void mapAddressToDeviceId(const AudioDeviceTypeAddr& adt, const audio_port_handle_t deviceId); /** Caches mapping between address, device port id and device type. */ void mapAddressToDeviceId(const AudioDeviceTypeAddr& adt, const audio_port_handle_t deviceId); /** Clear all map entries with passed audio_port_handle_t. */ void clearMapDeviceIdEntries(audio_port_handle_t deviceId); Loading Loading @@ -133,10 +132,11 @@ private: binder::Status setOutputRs2(float value) override; binder::Status resetCsd(float currentCsd, const std::vector<media::SoundDoseRecord>& records) override; binder::Status getOutputRs2(float* value); binder::Status getCsd(float* value); binder::Status forceUseFrameworkMel(bool useFrameworkMel); binder::Status forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices); binder::Status updateAttenuation(float attenuationDB, int device) override; binder::Status getOutputRs2(float* value) override; binder::Status getCsd(float* value) override; binder::Status forceUseFrameworkMel(bool useFrameworkMel) override; binder::Status forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices) override; wp<SoundDoseManager> mSoundDoseManager; const sp<media::ISoundDoseCallback> mSoundDoseCallback; Loading @@ -163,6 +163,7 @@ private: sp<media::ISoundDoseCallback> getSoundDoseCallback() const; void updateAttenuation(float attenuationDB, audio_devices_t deviceType); void setUseFrameworkMel(bool useFrameworkMel); void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices); /** Returns the HAL sound dose interface or null if internal MEL computation is used. */ Loading @@ -180,8 +181,10 @@ private: // logic for deviceId's that should not report MEL values (e.g.: do not have an active MUSIC // or GAME stream). std::map<AudioDeviceTypeAddr, audio_port_handle_t> mActiveDevices GUARDED_BY(mLock); std::unordered_map<audio_port_handle_t, audio_devices_t> mActiveDeviceTypes GUARDED_BY(mLock); float mRs2Value GUARDED_BY(mLock); std::unordered_map<audio_devices_t, float> mMelAttenuationDB GUARDED_BY(mLock); sp<SoundDose> mSoundDose GUARDED_BY(mLock); Loading
services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp +18 −9 Original line number Diff line number Diff line Loading @@ -17,11 +17,16 @@ // #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 <SoundDoseManager.h> #if !defined(BACKEND_NDK) #define BACKEND_NDK #endif #include <media/AidlConversionCppNdk.h> namespace android { namespace { Loading Loading @@ -199,26 +204,30 @@ TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument) TEST_F(SoundDoseManagerTest, GetIdReturnsMappedAddress) { const std::string address = "testAddress"; const audio_port_handle_t deviceId = 2; const AudioDeviceTypeAddr adt{audio_devices_t{0}, address}; AudioDevice audioDevice; audioDevice.address.set<AudioDeviceAddress::id>(address); 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)); EXPECT_EQ(deviceId, mSoundDoseManager->getIdForAudioDevice(audioDevice.value())); } TEST_F(SoundDoseManagerTest, GetAfterClearIdReturnsNone) { const std::string address = "testAddress"; const AudioDeviceTypeAddr adt {audio_devices_t{0}, address}; const audio_devices_t deviceType = AUDIO_DEVICE_OUT_WIRED_HEADSET; const AudioDeviceTypeAddr adt{deviceType, address}; const audio_port_handle_t deviceId = 2; AudioDevice audioDevice; audioDevice.address.set<AudioDeviceAddress::id>(address); 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)); EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice.value())); } TEST_F(SoundDoseManagerTest, GetUnmappedIdReturnsHandleNone) { Loading