Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76779c8b authored by Vlad Popa's avatar Vlad Popa Committed by Android (Google) Code Review
Browse files

Merge "CSD: add logic for using HAL sound dose values"

parents aa988bf8 1d5f0d5c
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ cc_library_shared {

    defaults: [
        "latest_android_media_audio_common_types_cpp_shared",
        "latest_android_hardware_audio_sounddose_ndk_shared",
    ],

    srcs: [
@@ -76,6 +77,7 @@ cc_library_shared {
        "libutils",
        "liblog",
        "libbinder",
        "libbinder_ndk",
        "libaudioclient",
        "libaudiomanager",
        "libmedialogservice",
@@ -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: [
+3 −0
Original line number Diff line number Diff line
@@ -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();
+1 −0
Original line number Diff line number Diff line
@@ -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>
+118 −20
Original line number Diff line number Diff line
@@ -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;
    }

@@ -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__);
@@ -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;
}

+33 −7
Original line number Diff line number Diff line
@@ -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);

@@ -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};
@@ -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