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

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

Merge "CSD: add support for multiple sound dose HALs" into udc-qpr-dev

parents 1d739d3d 08c8c4b8
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -38,24 +38,21 @@ bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::strin

    ndk::SpAIBinder soundDoseBinder;
    if (device->getSoundDoseInterface(module, &soundDoseBinder) != OK) {
        ALOGW("%s: HAL cannot provide sound dose interface for module %s, use internal MEL",
        ALOGW("%s: HAL cannot provide sound dose interface for module %s",
              __func__, module.c_str());
        activateInternalSoundDoseComputation();
        return false;
    }

    if (soundDoseBinder == nullptr) {
         ALOGW("%s: HAL doesn't implement a sound dose interface for module %s, use internal MEL",
         ALOGW("%s: HAL doesn't implement a sound dose interface for module %s",
              __func__, module.c_str());
        activateInternalSoundDoseComputation();
        return false;
    }

    std::shared_ptr<ISoundDose> soundDoseInterface = ISoundDose::fromBinder(soundDoseBinder);

    if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
    if (!mSoundDoseManager->setHalSoundDoseInterface(module, soundDoseInterface)) {
        ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
        activateInternalSoundDoseComputation();
        return false;
    }

@@ -73,7 +70,8 @@ void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
        mUseHalSoundDoseInterface = false;
    }

    mSoundDoseManager->setHalSoundDoseInterface(nullptr);
    // reset the HAL interfaces and use internal MELs
    mSoundDoseManager->resetHalSoundDoseInterfaces();
}

void AudioFlinger::MelReporter::onFirstRef() {
@@ -251,6 +249,9 @@ sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
void AudioFlinger::MelReporter::stopInternalMelComputation() {
    ALOGV("%s", __func__);
    std::lock_guard _l(mLock);
    if (mUseHalSoundDoseInterface) {
        return;
    }
    mActiveMelPatches.clear();
    mUseHalSoundDoseInterface = true;
}
+50 −33
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
        size_t channelCount, audio_format_t format) {
    std::lock_guard _l(mLock);

    if (mHalSoundDose != nullptr && mEnabledCsd) {
    if (mHalSoundDose.size() > 0 && mEnabledCsd) {
        ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
        return nullptr;
    }
@@ -83,19 +83,27 @@ sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
    return melProcessor;
}

bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose) {
bool SoundDoseManager::setHalSoundDoseInterface(const std::string &module,
                                                const std::shared_ptr<ISoundDose> &halSoundDose) {
    ALOGV("%s", __func__);

    if (halSoundDose == nullptr) {
        ALOGI("%s: passed ISoundDose object is null", __func__);
        return false;
    }

    std::shared_ptr<HalSoundDoseCallback> halSoundDoseCallback;
    {
        std::lock_guard _l(mLock);

        mHalSoundDose = halSoundDose;
        if (halSoundDose == nullptr) {
            ALOGI("%s: passed ISoundDose object is null, switching to internal CSD", __func__);
        if (mHalSoundDose.find(module) != mHalSoundDose.end()) {
            ALOGW("%s: Module %s already has a sound dose HAL assigned, skipping", __func__,
                  module.c_str());
            return false;
        }
        mHalSoundDose[module] = halSoundDose;

        if (!mHalSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
        if (!halSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
            ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
                  __func__,
                  mRs2UpperBound);
@@ -119,16 +127,26 @@ bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose
    return true;
}

void SoundDoseManager::resetHalSoundDoseInterfaces() {
    ALOGV("%s", __func__);

    const std::lock_guard _l(mLock);
    mHalSoundDose.clear();
}

void SoundDoseManager::setOutputRs2UpperBound(float rs2Value) {
    ALOGV("%s", __func__);
    std::lock_guard _l(mLock);

    if (mHalSoundDose != nullptr) {
    if (mHalSoundDose.size() > 0) {
        for (auto& halSoundDose : mHalSoundDose) {
            // using the HAL sound dose interface
        if (!mHalSoundDose->setOutputRs2UpperBound(rs2Value).isOk()) {
            if (!halSoundDose.second->setOutputRs2UpperBound(rs2Value).isOk()) {
                ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
            return;
                continue;
            }
        }

        mRs2UpperBound = rs2Value;
        return;
    }
@@ -200,14 +218,16 @@ void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) {

ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
        float in_currentDbA, const AudioDevice& in_audioDevice) {
    auto soundDoseManager = mSoundDoseManager.promote();
    sp<SoundDoseManager> soundDoseManager;
    {
        const std::lock_guard _l(mCbLock);
        soundDoseManager = mSoundDoseManager.promote();
        if (soundDoseManager == nullptr) {
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }
    }

    std::shared_ptr<ISoundDose> halSoundDose;
    soundDoseManager->getHalSoundDose(&halSoundDose);
    if(halSoundDose == nullptr) {
    if (!soundDoseManager->useHalSoundDose()) {
        ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
@@ -227,14 +247,16 @@ ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWa
ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
        const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
        const AudioDevice& in_audioDevice) {
    auto soundDoseManager = mSoundDoseManager.promote();
    sp<SoundDoseManager> soundDoseManager;
    {
        const std::lock_guard _l(mCbLock);
        soundDoseManager = mSoundDoseManager.promote();
        if (soundDoseManager == nullptr) {
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }
    }

    std::shared_ptr<ISoundDose> halSoundDose;
    soundDoseManager->getHalSoundDose(&halSoundDose);
    if(halSoundDose == nullptr) {
    if (!soundDoseManager->useHalSoundDose()) {
        ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
@@ -508,7 +530,7 @@ bool SoundDoseManager::shouldComputeCsdForDeviceWithAddress(const audio_devices_

void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
    // invalidate any HAL sound dose interface used
    setHalSoundDoseInterface(nullptr);
    resetHalSoundDoseInterfaces();

    std::lock_guard _l(mLock);
    mUseFrameworkMel = useFrameworkMel;
@@ -534,17 +556,12 @@ bool SoundDoseManager::isSoundDoseHalSupported() const {
        return false;
    }

    std::shared_ptr<ISoundDose> halSoundDose;
    getHalSoundDose(&halSoundDose);
    if (mHalSoundDose == nullptr) {
        return false;
    }
    return true;
    return useHalSoundDose();
}

void SoundDoseManager::getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const {
    std::lock_guard _l(mLock);
    *halSoundDose = mHalSoundDose;
bool SoundDoseManager::useHalSoundDose() const {
    const std::lock_guard _l(mLock);
    return mHalSoundDose.size() > 0;
}

void SoundDoseManager::resetSoundDose() {
+13 −6
Original line number Diff line number Diff line
@@ -94,12 +94,15 @@ public:
    sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);

    /**
     * Sets the HAL sound dose interface to use for the MEL computation. Use nullptr
     * for using the internal MEL computation.
     * Sets the HAL sound dose interface for a specific module to use for the MEL computation.
     *
     * @return true if setting the HAL sound dose value was successful, false otherwise.
     */
    bool setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose);
    bool setHalSoundDoseInterface(const std::string &module,
                                  const std::shared_ptr<ISoundDose> &halSoundDose);

    /** Reset all the stored HAL sound dose interface. */
    void resetHalSoundDoseInterfaces();

    /** Returns the cached audio port id from the active devices. */
    audio_port_handle_t getIdForAudioDevice(
@@ -193,6 +196,7 @@ private:
                const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;

        wp<SoundDoseManager> mSoundDoseManager;
        std::mutex mCbLock;
    };

    void resetSoundDose();
@@ -206,8 +210,11 @@ private:
    void setUseFrameworkMel(bool useFrameworkMel);
    void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
    bool isSoundDoseHalSupported() const;
    /** Returns the HAL sound dose interface or null if internal MEL computation is used. */
    void getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const;
    /**
     * Returns true if there is one active HAL sound dose interface or null if internal MEL
     * computation is used.
     **/
    bool useHalSoundDose() const;

    mutable std::mutex mLock;

@@ -241,7 +248,7 @@ private:

    sp<SoundDose> mSoundDose GUARDED_BY(mLock);

    std::shared_ptr<ISoundDose> mHalSoundDose GUARDED_BY(mLock);
    std::unordered_map<std::string, std::shared_ptr<ISoundDose>> mHalSoundDose GUARDED_BY(mLock);
    std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock);

    bool mUseFrameworkMel GUARDED_BY(mLock) = false;
+25 −7
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ public:
    MOCK_METHOD(void, stopMelComputationForDeviceId, (audio_port_handle_t), (override));
};

constexpr char kPrimaryModule[] = "primary";
constexpr char kSecondaryModule[] = "secondary";

class SoundDoseManagerTest : public ::testing::Test {
protected:
@@ -52,17 +54,24 @@ protected:
        mMelReporterCallback = sp<MelReporterCallback>::make();
        mSoundDoseManager = sp<SoundDoseManager>::make(mMelReporterCallback);
        mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
        mSecondaryHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();

        ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound)
            .WillByDefault([] (float rs2) {
                EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
                return ndk::ScopedAStatus::ok();
            });
        ON_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound)
                .WillByDefault([] (float rs2) {
                    EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
                    return ndk::ScopedAStatus::ok();
                });
    }

    sp<MelReporterCallback> mMelReporterCallback;
    sp<SoundDoseManager> mSoundDoseManager;
    std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
    std::shared_ptr<HalSoundDoseMock> mSecondaryHalSoundDose;
};

TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) {
@@ -110,7 +119,7 @@ TEST_F(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
}

TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) {
    EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
    EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, nullptr));
}

TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
@@ -122,7 +131,7 @@ TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
            return ndk::ScopedAStatus::ok();
        });

    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));

    EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
            /*streamHandle=*/1,
@@ -139,8 +148,17 @@ TEST_F(SoundDoseManagerTest, SetHalSoundDoseRegistersHalCallbacks) {
            EXPECT_NE(nullptr, callback);
            return ndk::ScopedAStatus::ok();
        });
    EXPECT_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
    EXPECT_CALL(*mSecondaryHalSoundDose.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_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kSecondaryModule,
                                                            mSecondaryHalSoundDose));
}

TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) {
@@ -154,7 +172,7 @@ TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgumen
           return ndk::ScopedAStatus::ok();
       });

    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));

    EXPECT_NE(nullptr, halCallback);
    AudioDevice audioDevice = {};
@@ -175,9 +193,9 @@ TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalAfterInternalSelectedReturn
           return ndk::ScopedAStatus::ok();
       });

    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
    EXPECT_NE(nullptr, halCallback);
    EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
    mSoundDoseManager->resetHalSoundDoseInterfaces();

    AudioDevice audioDevice = {};
    audioDevice.address.set<AudioDeviceAddress::id>("test");
@@ -197,7 +215,7 @@ TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument)
           return ndk::ScopedAStatus::ok();
       });

    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));

    EXPECT_NE(nullptr, halCallback);
    AudioDevice audioDevice = {};