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

Commit 32187259 authored by Ajender Reddy's avatar Ajender Reddy
Browse files

libaudiohal@aidl: serialize IStream[Common|Out|In]

Serialize the calls to IStream[Common|Out|In], such that HAL
implementation avoids any race condition.

Test: m

BUG: 384443124

Change-Id: Ibfa4a3109eea78a45ddacc1970cd1d559074e342
parent 31d9a1ab
Loading
Loading
Loading
Loading
+49 −26
Original line number Diff line number Diff line
@@ -49,6 +49,12 @@ using ::aidl::android::hardware::audio::core::StreamDescriptor;
using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
using ::aidl::android::media::audio::IHalAdapterVendorExtension;

#define SERIALIZE_CALL(mtx, exp)   \
    [&]() -> decltype(exp) {       \
        std::lock_guard lock(mtx); \
        return exp;                \
    }()

namespace android {

using HalCommand = StreamDescriptor::Command;
@@ -129,7 +135,7 @@ StreamHalAidl::StreamHalAidl(std::string_view className, bool isInput, const aud
StreamHalAidl::~StreamHalAidl() {
    AUGMENT_LOG(D);
    if (mStream != nullptr) {
        ndk::ScopedAStatus status = mStream->close();
        ndk::ScopedAStatus status = SERIALIZE_CALL(mCallLock, mStream->close());
        AUGMENT_LOG_IF(E, !status.isOk(), "status %s", status.getDescription().c_str());
    }
}
@@ -166,9 +172,9 @@ status_t StreamHalAidl::setParameters(const String8& kvPairs) {
    AUGMENT_LOG(D, "parameters: %s", parameters.toString().c_str());

    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
                    parameters, String8(AudioParameter::keyStreamHwAvSync),
            [&](int hwAvSyncId) {
                return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId));
            parameters, String8(AudioParameter::keyStreamHwAvSync), [&](int hwAvSyncId) {
                return statusTFromBinderStatus(
                        SERIALIZE_CALL(mCallLock, mStream->updateHwAvSyncId(hwAvSyncId)));
            }));
    return parseAndSetVendorParameters(mVendorExt, mStream, parameters);
}
@@ -205,7 +211,8 @@ status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect) {
        return BAD_VALUE;
    }
    auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
    return statusTFromBinderStatus(mStream->addEffect(aidlEffect->getIEffect()));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->addEffect(aidlEffect->getIEffect())));
}

status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect) {
@@ -216,7 +223,8 @@ status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect) {
        return BAD_VALUE;
    }
    auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
    return statusTFromBinderStatus(mStream->removeEffect(aidlEffect->getIEffect()));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->removeEffect(aidlEffect->getIEffect())));
}

status_t StreamHalAidl::standby() {
@@ -275,6 +283,7 @@ status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
    if (!mStream) return NO_INIT;
    Vector<String16> newArgs = args;
    newArgs.push(String16(kDumpFromAudioServerArgument));
    // Do not serialize the dump call with mCallLock
    status_t status = mStream->dump(fd, Args(newArgs).args(), newArgs.size());
    mStreamPowerLog.dump(fd);
    return status;
@@ -553,7 +562,7 @@ status_t StreamHalAidl::exit() {
    AUGMENT_LOG(D);
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    return statusTFromBinderStatus(mStream->prepareToClose());
    return statusTFromBinderStatus(SERIALIZE_CALL(mCallLock, mStream->prepareToClose()));
}

void StreamHalAidl::onAsyncTransferReady() {
@@ -806,13 +815,14 @@ status_t StreamOutHalAidl::setVolume(float left, float right) {
            volumes[i] = (left + right) / 2;
        }
    }
    return statusTFromBinderStatus(mStream->setHwVolume(volumes));
    return statusTFromBinderStatus(SERIALIZE_CALL(mCallLock, mStream->setHwVolume(volumes)));
}

status_t StreamOutHalAidl::selectPresentation(int presentationId, int programId) {
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    return statusTFromBinderStatus(mStream->selectPresentation(presentationId, programId));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->selectPresentation(presentationId, programId)));
}

status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
@@ -931,7 +941,8 @@ status_t StreamOutHalAidl::updateSourceMetadata(
    if (!mStream) return NO_INIT;
    ::aidl::android::hardware::audio::common::SourceMetadata aidlMetadata =
              VALUE_OR_RETURN_STATUS(legacy2aidl_SourceMetadata(sourceMetadata));
    return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->updateMetadata(aidlMetadata)));
}

status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
@@ -941,7 +952,8 @@ status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
        return BAD_VALUE;
    }
    ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getDualMonoMode(&aidlMode)));
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->getDualMonoMode(&aidlMode))));
    *mode = VALUE_OR_RETURN_STATUS(
            ::aidl::android::aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(aidlMode));
    return OK;
@@ -952,7 +964,8 @@ status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
    if (!mStream) return NO_INIT;
    ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
    return statusTFromBinderStatus(mStream->setDualMonoMode(aidlMode));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->setDualMonoMode(aidlMode)));
}

status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB) {
@@ -961,13 +974,15 @@ status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB) {
    if (leveldB == nullptr) {
        return BAD_VALUE;
    }
    return statusTFromBinderStatus(mStream->getAudioDescriptionMixLevel(leveldB));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->getAudioDescriptionMixLevel(leveldB)));
}

status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB) {
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    return statusTFromBinderStatus(mStream->setAudioDescriptionMixLevel(leveldB));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->setAudioDescriptionMixLevel(leveldB)));
}

status_t StreamOutHalAidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
@@ -977,7 +992,8 @@ status_t StreamOutHalAidl::getPlaybackRateParameters(audio_playback_rate_t* play
        return BAD_VALUE;
    }
    ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getPlaybackRateParameters(&aidlRate)));
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->getPlaybackRateParameters(&aidlRate))));
    *playbackRate = VALUE_OR_RETURN_STATUS(
            ::aidl::android::aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(aidlRate));
    return OK;
@@ -988,7 +1004,8 @@ status_t StreamOutHalAidl::setPlaybackRateParameters(const audio_playback_rate_t
    if (!mStream) return NO_INIT;
    ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(playbackRate));
    return statusTFromBinderStatus(mStream->setPlaybackRateParameters(aidlRate));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->setPlaybackRateParameters(aidlRate)));
}

status_t StreamOutHalAidl::setEventCallback(
@@ -1006,7 +1023,8 @@ status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode) {
    if (!mStream) return NO_INIT;
    ::aidl::android::media::audio::common::AudioLatencyMode aidlMode = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
    return statusTFromBinderStatus(mStream->setLatencyMode(aidlMode));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->setLatencyMode(aidlMode)));
};

status_t StreamOutHalAidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
@@ -1016,8 +1034,8 @@ status_t StreamOutHalAidl::getRecommendedLatencyModes(std::vector<audio_latency_
        return BAD_VALUE;
    }
    std::vector<::aidl::android::media::audio::common::AudioLatencyMode> aidlModes;
    RETURN_STATUS_IF_ERROR(
            statusTFromBinderStatus(mStream->getRecommendedLatencyModes(&aidlModes)));
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->getRecommendedLatencyModes(&aidlModes))));
    *modes = VALUE_OR_RETURN_STATUS(
            ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
                    aidlModes,
@@ -1113,8 +1131,9 @@ status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter &parame
    }
    if (updateMetadata) {
        AUGMENT_LOG(D, "set offload metadata %s", mOffloadMetadata.toString().c_str());
        if (status_t status = statusTFromBinderStatus(
                        mStream->updateOffloadMetadata(mOffloadMetadata)); status != OK) {
        if (status_t status = statusTFromBinderStatus(SERIALIZE_CALL(
                    mCallLock, mStream->updateOffloadMetadata(mOffloadMetadata)));
            status != OK) {
            AUGMENT_LOG(E, "updateOffloadMetadata failed %d", status);
            return status;
        }
@@ -1147,7 +1166,7 @@ status_t StreamInHalAidl::setGain(float gain) {
    if (!mStream) return NO_INIT;
    const size_t channelCount = audio_channel_count_from_in_mask(mConfig.channel_mask);
    std::vector<float> gains(channelCount != 0 ? channelCount : 1, gain);
    return statusTFromBinderStatus(mStream->setHwGain(gains));
    return statusTFromBinderStatus(SERIALIZE_CALL(mCallLock, mStream->setHwGain(gains)));
}

status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
@@ -1185,7 +1204,8 @@ status_t StreamInHalAidl::getActiveMicrophones(std::vector<media::MicrophoneInfo
    auto staticInfo = micInfoProvider->getMicrophoneInfo();
    if (!staticInfo) return INVALID_OPERATION;
    std::vector<MicrophoneDynamicInfo> dynamicInfo;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getActiveMicrophones(&dynamicInfo)));
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->getActiveMicrophones(&dynamicInfo))));
    std::vector<media::MicrophoneInfoFw> result;
    result.reserve(dynamicInfo.size());
    for (const auto& d : dynamicInfo) {
@@ -1215,7 +1235,8 @@ status_t StreamInHalAidl::updateSinkMetadata(
    if (!mStream) return NO_INIT;
    ::aidl::android::hardware::audio::common::SinkMetadata aidlMetadata =
              VALUE_OR_RETURN_STATUS(legacy2aidl_SinkMetadata(sinkMetadata));
    return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->updateMetadata(aidlMetadata)));
}

status_t StreamInHalAidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
@@ -1225,13 +1246,15 @@ status_t StreamInHalAidl::setPreferredMicrophoneDirection(audio_microphone_direc
              VALUE_OR_RETURN_STATUS(
                      ::aidl::android::legacy2aidl_audio_microphone_direction_t_MicrophoneDirection(
                              direction));
    return statusTFromBinderStatus(mStream->setMicrophoneDirection(aidlDirection));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->setMicrophoneDirection(aidlDirection)));
}

status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom) {
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    return statusTFromBinderStatus(mStream->setMicrophoneFieldDimension(zoom));
    return statusTFromBinderStatus(
            SERIALIZE_CALL(mCallLock, mStream->setMicrophoneFieldDimension(zoom)));
}

} // namespace android
+9 −0
Original line number Diff line number Diff line
@@ -306,6 +306,15 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper
    // queues as they are thread-safe, only send/receive operation must be protected.
    std::mutex mCommandReplyLock;

    /*
     * This lock is exclusively intended to serialize binder calls to remote
     * IStream[Common|Out|In] objects in Audio HAL. Thereby, preventing any race conditions in Audio
     * HAL. The only exception for above is when calling the IStream[Common|Out|In]::dump API.
     * Please note that lock doesn't prevent access to IStream[Common|Out|In] class fields. That
     * explains why there is no 'GUARDED_BY' annotations.
     */
    std::mutex mCallLock;

  private:
    static audio_config_base_t configToBase(const audio_config& config) {
        audio_config_base_t result = AUDIO_CONFIG_BASE_INITIALIZER;