Loading services/audioflinger/Android.bp +3 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ cc_library_shared { defaults: [ "latest_android_media_audio_common_types_cpp_shared", "latest_android_hardware_audio_sounddose_ndk_shared", ], srcs: [ Loading Loading @@ -76,6 +77,7 @@ cc_library_shared { "libutils", "liblog", "libbinder", "libbinder_ndk", "libaudioclient", "libaudiomanager", "libmedialogservice", Loading Loading @@ -105,11 +107,11 @@ cc_library_shared { "libaudiohal_headers", "libaudioutils_headers", "libmedia_headers", "libsounddose_headers", ], export_shared_lib_headers: [ "libpermission", "android.hardware.audio.sounddose-V1-ndk", ], cflags: [ Loading services/audioflinger/AudioFlinger.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -2573,6 +2573,9 @@ audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name) ALOGE("loadHwModule() error %d loading module %s", rc, name); return AUDIO_MODULE_HANDLE_NONE; } if (!mMelReporter->activateHalSoundDoseComputation(name)) { ALOGW("loadHwModule() sound dose reporting is not available"); } mHardwareStatus = AUDIO_HW_INIT; rc = dev->initCheck(); Loading services/audioflinger/AudioFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <sys/types.h> #include <limits.h> #include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h> #include <android/media/BnAudioTrack.h> #include <android/media/IAudioFlingerClient.h> #include <android/media/IAudioTrackCallback.h> Loading services/audioflinger/MelReporter.cpp +118 −20 Original line number Diff line number Diff line Loading @@ -22,12 +22,73 @@ #include <android/media/ISoundDoseCallback.h> #include <audio_utils/power.h> #include <android/binder_manager.h> #include <utils/Log.h> using aidl::android::hardware::audio::core::ISoundDose; using aidl::android::hardware::audio::sounddose::ISoundDoseFactory; namespace android { constexpr std::string_view kSoundDoseInterfaceModule = "/default"; bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module) { if (mSoundDoseFactory == nullptr) { ALOGW("%s sound dose HAL reporting not available", __func__); activateInternalSoundDoseComputation(); return false; } std::shared_ptr<ISoundDose> soundDoseInterface; auto result = mSoundDoseFactory->getSoundDose(module, &soundDoseInterface); if (!result.isOk()) { ALOGW("%s HAL cannot provide sound dose interface for module %s", __func__, module.c_str()); activateInternalSoundDoseComputation(); return false; } if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) { ALOGW("%s cannot activate HAL MEL reporting for module %s", __func__, module.c_str()); activateInternalSoundDoseComputation(); return false; } std::lock_guard _l(mLock); mUseHalSoundDoseInterface = true; stopInternalMelComputation(); return true; } void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() { mSoundDoseManager->setHalSoundDoseInterface(nullptr); std::lock_guard _l(mLock); mUseHalSoundDoseInterface = false; for (const auto& activePatches : mActiveMelPatches) { for (const auto& deviceId : activePatches.second.deviceHandles) { startMelComputationForNewPatch(activePatches.second.streamHandle, deviceId); } } } void AudioFlinger::MelReporter::onFirstRef() { mAudioFlinger.mPatchCommandThread->addListener(this); std::string interface = std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data(); AIBinder* binder = AServiceManager_checkService(interface.c_str()); if (binder == nullptr) { ALOGW("%s service %s doesn't exist", __func__, interface.c_str()); return; } mSoundDoseFactory = ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder)); } bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) { if (mSoundDoseManager.computeCsdOnAllDevices()) { if (mSoundDoseManager->computeCsdOnAllDevices()) { return true; } Loading Loading @@ -65,24 +126,39 @@ void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle, && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) { audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id; newPatch.deviceHandles.push_back(deviceId); AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type, patch.mAudioPatch.sinks[i].ext.device.address}; mSoundDoseManager->mapAddressToDeviceId(adt, deviceId); bool useHalSoundDoseInterface; { std::lock_guard _l(mLock); useHalSoundDoseInterface = mUseHalSoundDoseInterface; } if (!useHalSoundDoseInterface) { startMelComputationForNewPatch(streamHandle, deviceId); } } } std::lock_guard _l(mLock); mActiveMelPatches[patch.mAudioPatch.id] = newPatch; } void AudioFlinger::MelReporter::startMelComputationForNewPatch( audio_io_handle_t streamHandle, audio_port_handle_t deviceId) { // Start the MEL calculation in the PlaybackThread std::lock_guard _lAf(mAudioFlinger.mLock); auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle); if (thread != nullptr) { thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice( thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice( deviceId, newPatch.streamHandle, streamHandle, thread->mSampleRate, thread->mChannelCount, thread->mFormat)); } } } std::lock_guard _l(mLock); mActiveMelPatches[patch.mAudioPatch.id] = newPatch; } void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) { ALOGV("%s", __func__); Loading @@ -103,25 +179,47 @@ void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) mActiveMelPatches.erase(patchIt); } // Stop MEL calculation for the PlaybackThread std::lock_guard _lAf(mAudioFlinger.mLock); mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle); auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle); if (thread != nullptr) { thread->stopMelComputation(); for (const auto& deviceId : melPatch.deviceHandles) { mSoundDoseManager->clearMapDeviceIdEntries(deviceId); } stopInternalMelComputationForStream(melPatch.streamHandle); } sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface( const sp<media::ISoundDoseCallback>& callback) { // no need to lock since getSoundDoseInterface is synchronized return mSoundDoseManager.getSoundDoseInterface(callback); return mSoundDoseManager->getSoundDoseInterface(callback); } void AudioFlinger::MelReporter::stopInternalMelComputation() { ALOGV("%s", __func__); std::unordered_map<audio_patch_handle_t, ActiveMelPatch> activePatchesCopy; { std::lock_guard _l(mLock); activePatchesCopy = mActiveMelPatches; mActiveMelPatches.clear(); } for (const auto& activePatch : activePatchesCopy) { stopInternalMelComputationForStream(activePatch.second.streamHandle); } } void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) { ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId); std::lock_guard _lAf(mAudioFlinger.mLock); mSoundDoseManager->removeStreamProcessor(streamId); auto thread = mAudioFlinger.checkPlaybackThread_l(streamId); if (thread != nullptr) { thread->stopMelComputation(); } } std::string AudioFlinger::MelReporter::dump() { std::lock_guard _l(mLock); std::string output("\nSound Dose:\n"); output.append(mSoundDoseManager.dump()); output.append(mSoundDoseManager->dump()); return output; } Loading services/audioflinger/MelReporter.h +33 −7 Original line number Diff line number Diff line Loading @@ -32,17 +32,34 @@ constexpr static int kMaxTimestampDeltaInSec = 120; class MelReporter : public PatchCommandThread::PatchCommandListener { public: explicit MelReporter(AudioFlinger& audioFlinger) : mAudioFlinger(audioFlinger) {} : mAudioFlinger(audioFlinger), mSoundDoseManager(sp<SoundDoseManager>::make()) {} void onFirstRef() override { mAudioFlinger.mPatchCommandThread->addListener(this); } void onFirstRef() override; /** Returns true if we should compute MEL for the given device. */ bool shouldComputeMelForDeviceType(audio_devices_t device); // For now only support internal MelReporting [[nodiscard]] bool isHalReportingEnabled() const { return false; } /** * Activates the MEL reporting from the HAL sound dose interface. If the HAL * does not support the sound dose interface for this module, the internal MEL * calculation will be use. * * For now support internal MelReporting only if the sound dose standalone HAL * is not implemented * * @return true if the MEL reporting will be done from the sound dose HAL * interface */ bool activateHalSoundDoseComputation(const std::string& module); /** * Activates the MEL reporting from internal framework values. These are used * as a fallback when there is no sound dose interface implementation from HAL. * Note: the internal CSD computation does not guarantee a certification with * IEC62368-1 3rd edition or EN50332-3 */ void activateInternalSoundDoseComputation(); sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback); Loading @@ -54,9 +71,17 @@ public: void onReleaseAudioPatch(audio_patch_handle_t handle) override; private: void stopInternalMelComputation(); void stopInternalMelComputationForStream(audio_io_handle_t streamId); void startMelComputationForNewPatch(audio_io_handle_t streamHandle, audio_port_handle_t deviceId); AudioFlinger& mAudioFlinger; // does not own the object std::shared_ptr<::aidl::android::hardware::audio::sounddose::ISoundDoseFactory> mSoundDoseFactory; SoundDoseManager mSoundDoseManager; sp<SoundDoseManager> mSoundDoseManager; struct ActiveMelPatch { audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE}; Loading @@ -70,4 +95,5 @@ private: std::mutex mLock; std::unordered_map<audio_patch_handle_t, ActiveMelPatch> mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock); bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false; }; Loading
services/audioflinger/Android.bp +3 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ cc_library_shared { defaults: [ "latest_android_media_audio_common_types_cpp_shared", "latest_android_hardware_audio_sounddose_ndk_shared", ], srcs: [ Loading Loading @@ -76,6 +77,7 @@ cc_library_shared { "libutils", "liblog", "libbinder", "libbinder_ndk", "libaudioclient", "libaudiomanager", "libmedialogservice", Loading Loading @@ -105,11 +107,11 @@ cc_library_shared { "libaudiohal_headers", "libaudioutils_headers", "libmedia_headers", "libsounddose_headers", ], export_shared_lib_headers: [ "libpermission", "android.hardware.audio.sounddose-V1-ndk", ], cflags: [ Loading
services/audioflinger/AudioFlinger.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -2573,6 +2573,9 @@ audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name) ALOGE("loadHwModule() error %d loading module %s", rc, name); return AUDIO_MODULE_HANDLE_NONE; } if (!mMelReporter->activateHalSoundDoseComputation(name)) { ALOGW("loadHwModule() sound dose reporting is not available"); } mHardwareStatus = AUDIO_HW_INIT; rc = dev->initCheck(); Loading
services/audioflinger/AudioFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <sys/types.h> #include <limits.h> #include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h> #include <android/media/BnAudioTrack.h> #include <android/media/IAudioFlingerClient.h> #include <android/media/IAudioTrackCallback.h> Loading
services/audioflinger/MelReporter.cpp +118 −20 Original line number Diff line number Diff line Loading @@ -22,12 +22,73 @@ #include <android/media/ISoundDoseCallback.h> #include <audio_utils/power.h> #include <android/binder_manager.h> #include <utils/Log.h> using aidl::android::hardware::audio::core::ISoundDose; using aidl::android::hardware::audio::sounddose::ISoundDoseFactory; namespace android { constexpr std::string_view kSoundDoseInterfaceModule = "/default"; bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module) { if (mSoundDoseFactory == nullptr) { ALOGW("%s sound dose HAL reporting not available", __func__); activateInternalSoundDoseComputation(); return false; } std::shared_ptr<ISoundDose> soundDoseInterface; auto result = mSoundDoseFactory->getSoundDose(module, &soundDoseInterface); if (!result.isOk()) { ALOGW("%s HAL cannot provide sound dose interface for module %s", __func__, module.c_str()); activateInternalSoundDoseComputation(); return false; } if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) { ALOGW("%s cannot activate HAL MEL reporting for module %s", __func__, module.c_str()); activateInternalSoundDoseComputation(); return false; } std::lock_guard _l(mLock); mUseHalSoundDoseInterface = true; stopInternalMelComputation(); return true; } void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() { mSoundDoseManager->setHalSoundDoseInterface(nullptr); std::lock_guard _l(mLock); mUseHalSoundDoseInterface = false; for (const auto& activePatches : mActiveMelPatches) { for (const auto& deviceId : activePatches.second.deviceHandles) { startMelComputationForNewPatch(activePatches.second.streamHandle, deviceId); } } } void AudioFlinger::MelReporter::onFirstRef() { mAudioFlinger.mPatchCommandThread->addListener(this); std::string interface = std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data(); AIBinder* binder = AServiceManager_checkService(interface.c_str()); if (binder == nullptr) { ALOGW("%s service %s doesn't exist", __func__, interface.c_str()); return; } mSoundDoseFactory = ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder)); } bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) { if (mSoundDoseManager.computeCsdOnAllDevices()) { if (mSoundDoseManager->computeCsdOnAllDevices()) { return true; } Loading Loading @@ -65,24 +126,39 @@ void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle, && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) { audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id; newPatch.deviceHandles.push_back(deviceId); AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type, patch.mAudioPatch.sinks[i].ext.device.address}; mSoundDoseManager->mapAddressToDeviceId(adt, deviceId); bool useHalSoundDoseInterface; { std::lock_guard _l(mLock); useHalSoundDoseInterface = mUseHalSoundDoseInterface; } if (!useHalSoundDoseInterface) { startMelComputationForNewPatch(streamHandle, deviceId); } } } std::lock_guard _l(mLock); mActiveMelPatches[patch.mAudioPatch.id] = newPatch; } void AudioFlinger::MelReporter::startMelComputationForNewPatch( audio_io_handle_t streamHandle, audio_port_handle_t deviceId) { // Start the MEL calculation in the PlaybackThread std::lock_guard _lAf(mAudioFlinger.mLock); auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle); if (thread != nullptr) { thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice( thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice( deviceId, newPatch.streamHandle, streamHandle, thread->mSampleRate, thread->mChannelCount, thread->mFormat)); } } } std::lock_guard _l(mLock); mActiveMelPatches[patch.mAudioPatch.id] = newPatch; } void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) { ALOGV("%s", __func__); Loading @@ -103,25 +179,47 @@ void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) mActiveMelPatches.erase(patchIt); } // Stop MEL calculation for the PlaybackThread std::lock_guard _lAf(mAudioFlinger.mLock); mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle); auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle); if (thread != nullptr) { thread->stopMelComputation(); for (const auto& deviceId : melPatch.deviceHandles) { mSoundDoseManager->clearMapDeviceIdEntries(deviceId); } stopInternalMelComputationForStream(melPatch.streamHandle); } sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface( const sp<media::ISoundDoseCallback>& callback) { // no need to lock since getSoundDoseInterface is synchronized return mSoundDoseManager.getSoundDoseInterface(callback); return mSoundDoseManager->getSoundDoseInterface(callback); } void AudioFlinger::MelReporter::stopInternalMelComputation() { ALOGV("%s", __func__); std::unordered_map<audio_patch_handle_t, ActiveMelPatch> activePatchesCopy; { std::lock_guard _l(mLock); activePatchesCopy = mActiveMelPatches; mActiveMelPatches.clear(); } for (const auto& activePatch : activePatchesCopy) { stopInternalMelComputationForStream(activePatch.second.streamHandle); } } void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) { ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId); std::lock_guard _lAf(mAudioFlinger.mLock); mSoundDoseManager->removeStreamProcessor(streamId); auto thread = mAudioFlinger.checkPlaybackThread_l(streamId); if (thread != nullptr) { thread->stopMelComputation(); } } std::string AudioFlinger::MelReporter::dump() { std::lock_guard _l(mLock); std::string output("\nSound Dose:\n"); output.append(mSoundDoseManager.dump()); output.append(mSoundDoseManager->dump()); return output; } Loading
services/audioflinger/MelReporter.h +33 −7 Original line number Diff line number Diff line Loading @@ -32,17 +32,34 @@ constexpr static int kMaxTimestampDeltaInSec = 120; class MelReporter : public PatchCommandThread::PatchCommandListener { public: explicit MelReporter(AudioFlinger& audioFlinger) : mAudioFlinger(audioFlinger) {} : mAudioFlinger(audioFlinger), mSoundDoseManager(sp<SoundDoseManager>::make()) {} void onFirstRef() override { mAudioFlinger.mPatchCommandThread->addListener(this); } void onFirstRef() override; /** Returns true if we should compute MEL for the given device. */ bool shouldComputeMelForDeviceType(audio_devices_t device); // For now only support internal MelReporting [[nodiscard]] bool isHalReportingEnabled() const { return false; } /** * Activates the MEL reporting from the HAL sound dose interface. If the HAL * does not support the sound dose interface for this module, the internal MEL * calculation will be use. * * For now support internal MelReporting only if the sound dose standalone HAL * is not implemented * * @return true if the MEL reporting will be done from the sound dose HAL * interface */ bool activateHalSoundDoseComputation(const std::string& module); /** * Activates the MEL reporting from internal framework values. These are used * as a fallback when there is no sound dose interface implementation from HAL. * Note: the internal CSD computation does not guarantee a certification with * IEC62368-1 3rd edition or EN50332-3 */ void activateInternalSoundDoseComputation(); sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback); Loading @@ -54,9 +71,17 @@ public: void onReleaseAudioPatch(audio_patch_handle_t handle) override; private: void stopInternalMelComputation(); void stopInternalMelComputationForStream(audio_io_handle_t streamId); void startMelComputationForNewPatch(audio_io_handle_t streamHandle, audio_port_handle_t deviceId); AudioFlinger& mAudioFlinger; // does not own the object std::shared_ptr<::aidl::android::hardware::audio::sounddose::ISoundDoseFactory> mSoundDoseFactory; SoundDoseManager mSoundDoseManager; sp<SoundDoseManager> mSoundDoseManager; struct ActiveMelPatch { audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE}; Loading @@ -70,4 +95,5 @@ private: std::mutex mLock; std::unordered_map<audio_patch_handle_t, ActiveMelPatch> mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock); bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false; };