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

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

CSD: Add default AIDL HAL implementation

This should enable the sound dose gts on cuttlefish devices. The sound
dose HAL uses the internal MelProcessor to compute the MELs which are
reported to the framework.

Test: atest GtsAudioTestCases:SoundDoseTest
Bug: 301527435
Change-Id: Ifc505a0171bc8b4d3f5cf65d950fa5c0f812087f
parent b3f44985
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -46,11 +46,20 @@ cc_library {
        "SoundDose.cpp",
    ],
    shared_libs: [
        "libaudio_aidl_conversion_common_ndk",
        "libaudioutils",
        "libbase",
        "libbinder_ndk",
        "libcutils",
        "libutils",
    ],
    cflags: [
        "-Wall",
        "-Wextra",
        "-Werror",
        "-Wthread-safety",
        "-DBACKEND_NDK",
    ],
    visibility: [
        "//hardware/interfaces/audio/aidl/sounddose/default",
    ],
@@ -111,8 +120,12 @@ cc_library {
    shared_libs: [
        "android.hardware.bluetooth.audio-V3-ndk",
        "libaudio_aidl_conversion_common_ndk",
        "libaudioutils",
        "libaudioutils_nonvndk",
        "libbluetooth_audio_session_aidl",
        "liblog",
        "libmedia_helper",
        "libmediautils_vendor",
        "libstagefright_foundation",
    ],
    export_shared_lib_headers: [
@@ -143,8 +156,10 @@ cc_binary {
    ],
    shared_libs: [
        "android.hardware.bluetooth.audio-V3-ndk",
        "libaudioutils_nonvndk",
        "libaudio_aidl_conversion_common_ndk",
        "libbluetooth_audio_session_aidl",
        "liblog",
        "libmedia_helper",
        "libstagefright_foundation",
    ],
+6 −1
Original line number Diff line number Diff line
@@ -189,6 +189,11 @@ ndk::ScopedAStatus Module::createStreamContext(
        StreamContext::DebugParameters params{mDebug.streamTransientStateDelayMs,
                                              mVendorDebug.forceTransientBurst,
                                              mVendorDebug.forceSynchronousDrain};
        std::shared_ptr<ISoundDose> soundDose;
        if (!getSoundDose(&soundDose).isOk()) {
            LOG(ERROR) << __func__ << ": could not create sound dose instance";
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }
        StreamContext temp(
                std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
                std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
@@ -196,7 +201,7 @@ ndk::ScopedAStatus Module::createStreamContext(
                portConfigIt->channelMask.value(), portConfigIt->sampleRate.value().value, flags,
                portConfigIt->ext.get<AudioPortExt::mix>().handle,
                std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
                asyncCallback, outEventCallback, params);
                asyncCallback, outEventCallback, mSoundDose.getInstance(), params);
        if (temp.isValid()) {
            *out_context = std::move(temp);
        } else {
+89 −0
Original line number Diff line number Diff line
@@ -18,7 +18,15 @@

#include "core-impl/SoundDose.h"

#include <aidl/android/hardware/audio/core/sounddose/ISoundDose.h>
#include <android-base/logging.h>
#include <media/AidlConversionCppNdk.h>
#include <utils/Timers.h>

using aidl::android::hardware::audio::core::sounddose::ISoundDose;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioFormatDescription;

namespace aidl::android::hardware::audio::core::sounddose {

@@ -28,11 +36,16 @@ ndk::ScopedAStatus SoundDose::setOutputRs2UpperBound(float in_rs2ValueDbA) {
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }

    ::android::audio_utils::lock_guard l(mMutex);
    mRs2Value = in_rs2ValueDbA;
    if (mMelProcessor != nullptr) {
        mMelProcessor->setOutputRs2UpperBound(in_rs2ValueDbA);
    }
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus SoundDose::getOutputRs2UpperBound(float* _aidl_return) {
    ::android::audio_utils::lock_guard l(mMutex);
    *_aidl_return = mRs2Value;
    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
    return ndk::ScopedAStatus::ok();
@@ -44,6 +57,8 @@ ndk::ScopedAStatus SoundDose::registerSoundDoseCallback(
        LOG(ERROR) << __func__ << ": Callback is nullptr";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }

    ::android::audio_utils::lock_guard l(mCbMutex);
    if (mCallback != nullptr) {
        LOG(ERROR) << __func__ << ": Sound dose callback was already registered";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
@@ -51,7 +66,81 @@ ndk::ScopedAStatus SoundDose::registerSoundDoseCallback(

    mCallback = in_callback;
    LOG(DEBUG) << __func__ << ": Registered sound dose callback ";

    return ndk::ScopedAStatus::ok();
}

void SoundDose::setAudioDevice(const AudioDevice& audioDevice) {
    ::android::audio_utils::lock_guard l(mCbMutex);
    mAudioDevice = audioDevice;
}

void SoundDose::startDataProcessor(uint32_t sampleRate, uint32_t channelCount,
                                   const AudioFormatDescription& aidlFormat) {
    ::android::audio_utils::lock_guard l(mMutex);
    const auto result = aidl2legacy_AudioFormatDescription_audio_format_t(aidlFormat);
    const audio_format_t format = result.value_or(AUDIO_FORMAT_INVALID);

    if (mMelProcessor == nullptr) {
        // we don't have the deviceId concept on the vendor side so just pass 0
        mMelProcessor = ::android::sp<::android::audio_utils::MelProcessor>::make(
                sampleRate, channelCount, format, mMelCallback, /*deviceId=*/0, mRs2Value);
    } else {
        mMelProcessor->updateAudioFormat(sampleRate, channelCount, format);
    }
}

void SoundDose::process(const void* buffer, size_t bytes) {
    ::android::audio_utils::lock_guard l(mMutex);
    if (mMelProcessor != nullptr) {
        mMelProcessor->process(buffer, bytes);
    }
}

void SoundDose::onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length,
                               audio_port_handle_t deviceId __attribute__((__unused__))) const {
    ::android::audio_utils::lock_guard l(mCbMutex);
    if (!mAudioDevice.has_value()) {
        LOG(WARNING) << __func__ << ": New mel values without a registered device";
        return;
    }
    if (mCallback == nullptr) {
        LOG(ERROR) << __func__ << ": New mel values without a registered callback";
        return;
    }

    ISoundDose::IHalSoundDoseCallback::MelRecord melRecord;
    melRecord.timestamp = nanoseconds_to_seconds(systemTime());
    melRecord.melValues = std::vector<float>(mels.begin() + offset, mels.begin() + offset + length);

    mCallback->onNewMelValues(melRecord, mAudioDevice.value());
}

void SoundDose::MelCallback::onNewMelValues(const std::vector<float>& mels, size_t offset,
                                            size_t length,
                                            audio_port_handle_t deviceId
                                            __attribute__((__unused__))) const {
    mSoundDose.onNewMelValues(mels, offset, length, deviceId);
}

void SoundDose::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId
                                    __attribute__((__unused__))) const {
    ::android::audio_utils::lock_guard l(mCbMutex);
    if (!mAudioDevice.has_value()) {
        LOG(WARNING) << __func__ << ": Momentary exposure without a registered device";
        return;
    }
    if (mCallback == nullptr) {
        LOG(ERROR) << __func__ << ": Momentary exposure without a registered callback";
        return;
    }

    mCallback->onMomentaryExposureWarning(currentMel, mAudioDevice.value());
}

void SoundDose::MelCallback::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId
                                                 __attribute__((__unused__))) const {
    mSoundDose.onMomentaryExposure(currentMel, deviceId);
}

}  // namespace aidl::android::hardware::audio::core::sounddose
+12 −0
Original line number Diff line number Diff line
@@ -90,6 +90,14 @@ bool StreamContext::isValid() const {
    return true;
}

void StreamContext::startStreamDataProcessor() {
    auto streamDataProcessor = mStreamDataProcessor.lock();
    if (streamDataProcessor != nullptr) {
        streamDataProcessor->startDataProcessor(mSampleRate, getChannelCount(mChannelLayout),
                                                mFormat);
    }
}

void StreamContext::reset() {
    mCommandMQ.reset();
    mReplyMQ.reset();
@@ -593,6 +601,10 @@ bool StreamOutWorkerLogic::write(size_t clientSize, StreamDescriptor::Reply* rep
                fatal = true;
                LOG(ERROR) << __func__ << ": write failed: " << status;
            }
            auto streamDataProcessor = mContext->getStreamDataProcessor().lock();
            if (streamDataProcessor != nullptr) {
                streamDataProcessor->process(mDataBuffer.get(), actualFrameCount * frameSize);
            }
        } else {
            if (mContext->getAsyncCallback() == nullptr) {
                usleep(3000);  // Simulate blocking transfer delay.
+1 −1
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ class Module : public BnModule {
    bool mMicMute = false;
    bool mMasterMute = false;
    float mMasterVolume = 1.0f;
    ChildInterface<sounddose::ISoundDose> mSoundDose;
    ChildInterface<sounddose::SoundDose> mSoundDose;
    std::optional<bool> mIsMmapSupported;

  protected:
Loading