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

Commit f79092de authored by Andy Hung's avatar Andy Hung
Browse files

Add AudioFlinger to Thread thread safety annotations

Test: atest AudioTrackTest AudioRecordTest
Test: atest AAudioTests AudioTrackOffloadTest
Test: atest AudioPlaybackCaptureTest
Test: Camera YouTube
Bug: 275748373
Merged-In: I9b4573be8f5f6546d6979f69a9ad8d19e5d95bc6
Change-Id: I9b4573be8f5f6546d6979f69a9ad8d19e5d95bc6
parent 17068ab1
Loading
Loading
Loading
Loading
+19 −17
Original line number Diff line number Diff line
@@ -1102,8 +1102,9 @@ status_t AudioFlinger::createTrack(const media::CreateTrackRequest& _input,
            // move effect chain to this output thread if an effect on same session was waiting
            // for a track to be created
            if (effectThread != nullptr) {
                audio_utils::lock_guard _sl(effectThread->mutex());
                if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
                // No thread safety analysis: double lock on a thread capability.
                audio_utils::lock_guard_no_thread_safety_analysis _sl(effectThread->mutex());
                if (moveEffectChain_ll(sessionId, effectThread, thread) == NO_ERROR) {
                    effectThreadId = thread->id();
                    effectIds = thread->getEffectIds_l(sessionId);
                }
@@ -3034,7 +3035,7 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
                    audio_utils::scoped_lock sl(dstThread->mutex(), playbackThread->mutex());
                    Vector<sp<IAfEffectChain>> effectChains = playbackThread->getEffectChains_l();
                    for (size_t i = 0; i < effectChains.size(); i ++) {
                        moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
                        moveEffectChain_ll(effectChains[i]->sessionId(), playbackThread.get(),
                                dstThread);
                    }
                }
@@ -4298,7 +4299,7 @@ status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t
    }

    audio_utils::scoped_lock _ll(dstThread->mutex(), srcThread->mutex());
    return moveEffectChain_l(sessionId, srcThread, dstThread);
    return moveEffectChain_ll(sessionId, srcThread, dstThread);
}


@@ -4318,25 +4319,26 @@ void AudioFlinger::setEffectSuspended(int effectId,
}


// moveEffectChain_l must be called with both srcThread and dstThread mutex()s held
status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
// moveEffectChain_ll must be called with the AudioFlinger::mutex()
// and both srcThread and dstThread mutex()s held
status_t AudioFlinger::moveEffectChain_ll(audio_session_t sessionId,
        IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
{
    ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
            sessionId, srcThread, dstThread);
    ALOGV("%s: session %d from thread %p to thread %p",
            __func__, sessionId, srcThread, dstThread);

    sp<IAfEffectChain> chain = srcThread->getEffectChain_l(sessionId);
    if (chain == 0) {
        ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
                sessionId, srcThread);
        ALOGW("%s: effect chain for session %d not on source thread %p",
                __func__, sessionId, srcThread);
        return INVALID_OPERATION;
    }

    // Check whether the destination thread and all effects in the chain are compatible
    if (!chain->isCompatibleWithThread_l(dstThread)) {
        ALOGW("moveEffectChain_l() effect chain failed because"
        ALOGW("%s: effect chain failed because"
                " destination thread %p is not compatible with effects in the chain",
                dstThread);
                __func__, dstThread);
        return INVALID_OPERATION;
    }

@@ -4358,7 +4360,7 @@ status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
            effect = chain->getEffectFromId_l(0)) {
        srcThread->removeEffect_l(effect);
        removed.add(effect);
        status = dstThread->addEffect_l(effect);
        status = dstThread->addEffect_ll(effect);
        if (status != NO_ERROR) {
            errorString = StringPrintf(
                    "cannot add effect %p to destination thread", effect.get());
@@ -4384,7 +4386,7 @@ status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
        for (const auto& effect : removed) {
            dstThread->removeEffect_l(effect); // Note: Depending on error location, the last
                                               // effect may not have been placed on dstThread.
            if (srcThread->addEffect_l(effect) == NO_ERROR) {
            if (srcThread->addEffect_ll(effect) == NO_ERROR) {
                ++restored;
                if (dstChain == nullptr) {
                    dstChain = effect->getCallback()->chain().promote();
@@ -4449,16 +4451,16 @@ status_t AudioFlinger::moveAuxEffectToIo(int EffectId,
            return INVALID_OPERATION;
        }
        thread->removeEffect_l(effect);
        status = dstThread->addEffect_l(effect);
        status = dstThread->addEffect_ll(effect);
        if (status != NO_ERROR) {
            thread->addEffect_l(effect);
            thread->addEffect_ll(effect);
            status = INVALID_OPERATION;
            goto Exit;
        }

        dstChain = effect->getCallback()->chain().promote();
        if (dstChain == 0) {
            thread->addEffect_l(effect);
            thread->addEffect_ll(effect);
            status = INVALID_OPERATION;
        }

+3 −2
Original line number Diff line number Diff line
@@ -367,8 +367,9 @@ private:
    bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect) final
            EXCLUDES_AudioFlinger_Mutex;

    status_t moveEffectChain_l(audio_session_t sessionId,
            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final REQUIRES(mutex());
    status_t moveEffectChain_ll(audio_session_t sessionId,
            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final
            REQUIRES(mutex(), audio_utils::ThreadBase_Mutex);

    // This is a helper that is called during incoming binder calls.
    // Requests media.log to start merging log buffers
+4 −1
Original line number Diff line number Diff line
@@ -3338,7 +3338,10 @@ status_t DeviceEffectProxy::onCreatePatch(
}

status_t DeviceEffectProxy::checkPort(const IAfPatchPanel::Patch& patch,
        const struct audio_port_config *port, sp<IAfEffectHandle> *handle) {
        const struct audio_port_config *port, sp<IAfEffectHandle> *handle)
NO_THREAD_SAFETY_ANALYSIS
// calling function 'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
{

    ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
            __func__, port->type, port->ext.device.type,
+41 −22
Original line number Diff line number Diff line
@@ -67,44 +67,56 @@ struct stream_type_t {
// and hence may be used by the Effect / Track framework.
class IAfThreadCallback : public virtual RefBase {
public:
    virtual audio_utils::mutex& mutex() const = 0;
    virtual bool isNonOffloadableGlobalEffectEnabled_l() const = 0;  // Tracks
    virtual audio_utils::mutex& mutex() const
            RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
    virtual bool isNonOffloadableGlobalEffectEnabled_l() const
            REQUIRES(mutex()) = 0;  // Tracks
    virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
    virtual bool btNrecIsOff() const = 0;
    virtual float masterVolume_l() const = 0;
    virtual bool masterMute_l() const = 0;
    virtual float getMasterBalance_l() const = 0;
    virtual bool streamMute_l(audio_stream_type_t stream) const = 0;
    virtual float masterVolume_l() const
            REQUIRES(mutex()) = 0;
    virtual bool masterMute_l() const
            REQUIRES(mutex()) = 0;
    virtual float getMasterBalance_l() const
            REQUIRES(mutex()) = 0;
    virtual bool streamMute_l(audio_stream_type_t stream) const
            REQUIRES(mutex()) = 0;
    virtual audio_mode_t getMode() const = 0;
    virtual bool isLowRamDevice() const = 0;
    virtual bool isAudioPolicyReady() const = 0;  // Effects
    virtual uint32_t getScreenState() const = 0;
    virtual std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const = 0;
    virtual std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const
            REQUIRES(mutex()) = 0;
    virtual const sp<IAfPatchPanel>& getPatchPanel() const = 0;
    virtual const sp<MelReporter>& getMelReporter() const = 0;
    virtual const sp<EffectsFactoryHalInterface>& getEffectsFactoryHal() const = 0;
    virtual sp<IAudioManager> getOrCreateAudioManager() = 0;  // Tracks

    virtual bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect) = 0;
    virtual status_t moveEffectChain_l(audio_session_t sessionId,
            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) = 0;
    virtual bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect)
            EXCLUDES_AudioFlinger_Mutex = 0;
    virtual status_t moveEffectChain_ll(audio_session_t sessionId,
            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
            REQUIRES(mutex(), audio_utils::ThreadBase_Mutex) = 0;

    virtual void requestLogMerge() = 0;
    virtual sp<NBLog::Writer> newWriter_l(size_t size, const char *name) = 0;
    virtual sp<NBLog::Writer> newWriter_l(size_t size, const char *name)
            REQUIRES(mutex()) = 0;
    virtual void unregisterWriter(const sp<NBLog::Writer>& writer) = 0;

    virtual sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
            audio_session_t triggerSession,
            audio_session_t listenerSession,
            const audioflinger::SyncEventCallback& callBack,
            const wp<IAfTrackBase>& cookie) = 0;
            const wp<IAfTrackBase>& cookie)
            EXCLUDES_AudioFlinger_Mutex = 0;

    virtual void ioConfigChanged(audio_io_config_event_t event,
            const sp<AudioIoDescriptor>& ioDesc,
            pid_t pid = 0) = 0;
    virtual void onNonOffloadableGlobalEffectEnable() = 0;
            pid_t pid = 0) EXCLUDES_AudioFlinger_ClientMutex = 0;
    virtual void onNonOffloadableGlobalEffectEnable() EXCLUDES_AudioFlinger_Mutex = 0;
    virtual void onSupportedLatencyModesChanged(
            audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) = 0;
            audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes)
            EXCLUDES_AudioFlinger_ClientMutex = 0;
};

class IAfThreadBase : public virtual RefBase {
@@ -213,7 +225,8 @@ public:
            status_t* status /*non-NULL*/,
            bool pinned,
            bool probe,
            bool notifyFramesProcessed) = 0;
            bool notifyFramesProcessed)
            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;

    // return values for hasAudioSession (bit field)
    enum effect_state {
@@ -255,7 +268,8 @@ public:
    // add and effect module. Also creates the effect chain is none exists for
    // the effects audio session. Only called in a context of moving an effect
    // from one thread to another
    virtual status_t addEffect_l(const sp<IAfEffectModule>& effect) = 0;
    virtual status_t addEffect_ll(const sp<IAfEffectModule>& effect)
            REQUIRES(audio_utils::AudioFlinger_Mutex, mutex()) = 0;
    // remove and effect module. Also removes the effect chain is this was the last
    // effect
    virtual void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) = 0;
@@ -310,7 +324,8 @@ public:
    // deliver stats to mediametrics.
    virtual void sendStatistics(bool force) = 0;

    virtual audio_utils::mutex& mutex() const = 0;
    virtual audio_utils::mutex& mutex() const
            RETURN_CAPABILITY(audio_utils::ThreadBase_Mutex) = 0;

    virtual void onEffectEnable(const sp<IAfEffectModule>& effect) = 0;
    virtual void onEffectDisable() = 0;
@@ -321,8 +336,10 @@ public:
    virtual void invalidateTracksForAudioSession(audio_session_t sessionId) const = 0;

    virtual bool isStreamInitialized() const = 0;
    virtual void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) = 0;
    virtual void stopMelComputation_l() = 0;
    virtual void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor)
            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
    virtual void stopMelComputation_l()
            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;

    virtual product_strategy_t getStrategyForStream(audio_stream_type_t stream) const = 0;

@@ -398,7 +415,8 @@ public:
            audio_port_handle_t portId,
            const sp<media::IAudioTrackCallback>& callback,
            bool isSpatialized,
            bool isBitPerfect) = 0;
            bool isBitPerfect)
            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;

    virtual status_t addTrack_l(const sp<IAfTrack>& track) = 0;
    virtual bool destroyTrack_l(const sp<IAfTrack>& track) = 0;
@@ -502,7 +520,8 @@ public:
            pid_t tid,
            status_t* status /*non-NULL*/,
            audio_port_handle_t portId,
            int32_t maxSharedAudioHistoryMs) = 0;
            int32_t maxSharedAudioHistoryMs)
            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
    virtual void destroyTrack_l(const sp<IAfRecordTrack>& track) = 0;
    virtual void removeTrack_l(const sp<IAfRecordTrack>& track) = 0;

+119 −114
Original line number Diff line number Diff line
@@ -1794,9 +1794,9 @@ std::vector<int> ThreadBase::getEffectIds_l(audio_session_t sessionId) const
    return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
}

// PlaybackThread::addEffect_l() must be called with AudioFlinger::mutex() and
// PlaybackThread::mutex() held
status_t ThreadBase::addEffect_l(const sp<IAfEffectModule>& effect)
// PlaybackThread::addEffect_ll() must be called with AudioFlinger::mutex() and
// ThreadBase::mutex() held
status_t ThreadBase::addEffect_ll(const sp<IAfEffectModule>& effect)
{
    // check for existing effect chain with the requested audio session
    audio_session_t sessionId = effect->sessionId();
@@ -1804,22 +1804,22 @@ status_t ThreadBase::addEffect_l(const sp<IAfEffectModule>& effect)
    bool chainCreated = false;

    ALOGD_IF((mType == OFFLOAD) && !effect->isOffloadable(),
             "addEffect_l() on offloaded thread %p: effect %s does not support offload flags %#x",
                    this, effect->desc().name, effect->desc().flags);
             "%s: on offloaded thread %p: effect %s does not support offload flags %#x",
             __func__, this, effect->desc().name, effect->desc().flags);

    if (chain == 0) {
        // create a new chain for this session
        ALOGV("addEffect_l() new effect chain for session %d", sessionId);
        ALOGV("%s: new effect chain for session %d", __func__, sessionId);
        chain = IAfEffectChain::create(this, sessionId);
        addEffectChain_l(chain);
        chain->setStrategy(getStrategyForSession_l(sessionId));
        chainCreated = true;
    }
    ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
    ALOGV("%s: %p chain %p effect %p", __func__, this, chain.get(), effect.get());

    if (chain->getEffectFromId_l(effect->id()) != 0) {
        ALOGW("addEffect_l() %p effect %s already present in chain %p",
                this, effect->desc().name, chain.get());
        ALOGW("%s: %p effect %s already present in chain %p",
                __func__, this, effect->desc().name, chain.get());
        return BAD_VALUE;
    }

@@ -3122,6 +3122,8 @@ void PlaybackThread::resetDraining(uint32_t sequence)
}

void PlaybackThread::readOutputParameters_l()
NO_THREAD_SAFETY_ANALYSIS
// 'moveEffectChain_ll' requires holding mutex 'AudioFlinger_Mutex' exclusively
{
    // unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
    const audio_config_base_t audioConfig = mOutput->getAudioProperties();
@@ -3289,10 +3291,11 @@ void PlaybackThread::readOutputParameters_l()
    // Note that mutex() is not held when readOutputParameters_l() is called from the constructor
    // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
    // matter.
    // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
    // create a copy of mEffectChains as calling moveEffectChain_ll()
    // can reorder some effect chains
    Vector<sp<IAfEffectChain>> effectChains = mEffectChains;
    for (size_t i = 0; i < effectChains.size(); i ++) {
        mAfThreadCallback->moveEffectChain_l(effectChains[i]->sessionId(),
        mAfThreadCallback->moveEffectChain_ll(effectChains[i]->sessionId(),
            this/* srcThread */, this/* dstThread */);
    }

@@ -7838,6 +7841,8 @@ status_t SpatializerThread::setRequestedLatencyMode(audio_latency_mode_t mode) {
}

void SpatializerThread::checkOutputStageEffects()
NO_THREAD_SAFETY_ANALYSIS
//  'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
{
    bool hasVirtualizer = false;
    bool hasDownMixer = false;
Loading