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

Commit f09e93f5 authored by Vlad Popa's avatar Vlad Popa
Browse files

CSD: notify when RS2 momentary exposure is reached

RS2 is defined in IEC 62368-1 3rd edition as 100dBA. Added however the
possibility to further restrict this value as part of the momentary
exposure API.

Test: UT and manual tests
Bug: 256616352
Change-Id: I004a620e5e7915824d390f7ddc41c16f9675d45a
parent 2900c0a6
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -65,9 +65,12 @@ void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
            std::lock_guard _lAf(mAudioFlinger.mLock);
            auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
            if (thread != nullptr) {
                thread->startMelComputation(mSoundDoseManager.getOrCreateCallbackForDevice(
                thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice(
                    deviceId,
                    newPatch.streamHandle));
                    newPatch.streamHandle,
                    thread->mSampleRate,
                    thread->mChannelCount,
                    thread->mFormat));
            }
        }
    }
@@ -97,11 +100,11 @@ void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle)

    // 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();
    }
    mSoundDoseManager.removeStreamCallback(melPatch.streamHandle);
}

std::string AudioFlinger::MelReporter::dump() {
+5 −8
Original line number Diff line number Diff line
@@ -3405,14 +3405,11 @@ ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
    return bytesWritten;
}

void AudioFlinger::PlaybackThread::startMelComputation(const sp<
        audio_utils::MelProcessor::MelCallback>& callback)
void AudioFlinger::PlaybackThread::startMelComputation(
        const sp<audio_utils::MelProcessor>& processor)
{
    ALOGV("%s: creating new mel processor for thread %d", __func__, id());
    mMelProcessor = sp<audio_utils::MelProcessor>::make(mSampleRate,
                                                        mChannelCount,
                                                        mFormat,
                                                        callback);
    ALOGV("%s: starting mel processor for thread %d", __func__, id());
    mMelProcessor = processor;
}

void AudioFlinger::PlaybackThread::stopMelComputation() {
+1 −2
Original line number Diff line number Diff line
@@ -1091,8 +1091,7 @@ public:
                    return INVALID_OPERATION;
                }

                void startMelComputation(const sp
                             <audio_utils::MelProcessor::MelCallback>& callback);
                void startMelComputation(const sp<audio_utils::MelProcessor>& processor);
                void stopMelComputation();

protected:
+0 −2
Original line number Diff line number Diff line
@@ -10,9 +10,7 @@ package {
cc_library {
    name: "libsounddose",

    product_available: true,
    double_loadable: true,
    host_supported: true,

    srcs: [
        "SoundDoseManager.cpp",
+61 −24
Original line number Diff line number Diff line
@@ -40,58 +40,95 @@ int64_t getMonotonicSecond() {

}  // namespace

sp<audio_utils::MelProcessor::MelCallback> SoundDoseManager::getOrCreateCallbackForDevice(
sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
        audio_port_handle_t deviceId,
        audio_io_handle_t streamHandle)
        audio_io_handle_t streamHandle,
        uint32_t sampleRate,
        size_t channelCount,
        audio_format_t format)
{
    std::lock_guard _l(mLock);

    auto streamHandleCallback = mActiveCallbacks.find(streamHandle);
    if (streamHandleCallback != mActiveCallbacks.end()) {
    auto streamProcessor = mActiveProcessors.find(streamHandle);
    sp<audio_utils::MelProcessor> processor;
    if (streamProcessor != mActiveProcessors.end()
            && (processor = streamProcessor->second.promote())) {
        ALOGV("%s: found callback for stream %d", __func__, streamHandle);
        auto callback = streamHandleCallback->second;
        callback->mDeviceHandle = deviceId;
        return callback;
        processor->setDeviceId(deviceId);
        return processor;
    } else {
        ALOGV("%s: creating new callback for device %d", __func__, streamHandle);
        sp<Callback> melCallback = sp<Callback>::make(*this, deviceId);
        mActiveCallbacks[streamHandle] = melCallback;
        return melCallback;
        sp<audio_utils::MelProcessor> melProcessor =
            sp<audio_utils::MelProcessor>::make(sampleRate,
                                                channelCount,
                                                format,
                                                *this,
                                                deviceId,
                                                mRs2Value);
        mActiveProcessors[streamHandle] = melProcessor;
        return melProcessor;
    }
}

void SoundDoseManager::removeStreamCallback(audio_io_handle_t streamHandle)

void SoundDoseManager::setOutputRs2(float rs2Value)
{
    std::unordered_map<audio_io_handle_t, sp<Callback>>::iterator callbackToRemove;
    ALOGV("%s", __func__);
    std::lock_guard _l(mLock);

    for (auto& streamProcessor : mActiveProcessors) {
        sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
        if (processor != nullptr) {
            status_t result = processor->setOutputRs2(rs2Value);
            if (result != NO_ERROR) {
                ALOGW("%s: could not set RS2 value %f for stream %d",
                      __func__,
                      rs2Value,
                      streamProcessor.first);
            }
        }
    }
}

void SoundDoseManager::removeStreamProcessor(audio_io_handle_t streamHandle)
{
    std::lock_guard _l(mLock);
    callbackToRemove = mActiveCallbacks.find(streamHandle);
    if (callbackToRemove != mActiveCallbacks.end()) {
        mActiveCallbacks.erase(callbackToRemove);
    auto callbackToRemove = mActiveProcessors.find(streamHandle);
    if(callbackToRemove != mActiveProcessors.end()) {
        mActiveProcessors.erase(callbackToRemove);
    }
}

void SoundDoseManager::Callback::onNewMelValues(const std::vector<float>& mels,
void SoundDoseManager::onNewMelValues(const std::vector<float>& mels,
                                      size_t offset,
                                                size_t length) const
                                      size_t length,
                                      audio_port_handle_t deviceId) const
{
    ALOGV("%s", __func__);
    std::lock_guard _l(mSoundDoseManager.mLock);
    std::lock_guard _l(mLock);

    int64_t timestampSec = getMonotonicSecond();

    // only for internal callbacks
    mSoundDoseManager.mMelAggregator.aggregateAndAddNewMelRecord(
        audio_utils::MelRecord(mDeviceHandle, std::vector<float>(
    mMelAggregator->aggregateAndAddNewMelRecord(
        audio_utils::MelRecord(deviceId, std::vector<float>(
                                   mels.begin() + offset,
                                   mels.begin() + offset + length),
                               timestampSec - length));
}

void SoundDoseManager::onMomentaryExposure(float currentMel,
                                           audio_port_handle_t deviceId) const {
    ALOGV("%s: Momentary exposure for device %d triggered: %f MEL",
          __func__,
          deviceId,
          currentMel);
}

std::string SoundDoseManager::dump() const
{
    std::string output;
    mMelAggregator.foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
    mMelAggregator->foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
        base::StringAppendF(&output,
                            "CSD %f with average MEL %f in interval [%" PRId64 ", %" PRId64 "]",
                            csdRecord.value,
@@ -102,7 +139,7 @@ std::string SoundDoseManager::dump() const
    });

    base::StringAppendF(&output, "\nCached Mel Records:\n");
    mMelAggregator.foreachCachedMel([&output](const audio_utils::MelRecord& melRecord) {
    mMelAggregator->foreachCachedMel([&output](const audio_utils::MelRecord& melRecord) {
        base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
        base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);

@@ -116,7 +153,7 @@ std::string SoundDoseManager::dump() const
}

size_t SoundDoseManager::getCachedMelRecordsSize() const {
    return mMelAggregator.getCachedMelRecordsSize();
    return mMelAggregator->getCachedMelRecordsSize();
}

}  // namespace android
Loading