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

Commit 99fbd7c2 authored by Shunkai Yao's avatar Shunkai Yao Committed by Android (Google) Code Review
Browse files

Merge changes from topic "24d1_effect_chain_improvement" into 24D1-dev

* changes:
  Put orphan effect chain back if orphan effect creation failed
  Return non-zero channel mask for orphan effects
  AudioEffect: prevent adding effect for unknown session on first io
  AudioFlinger: Keep track of music effect thread when primary output is unavailable
parents f605b052 0bc34d4d
Loading
Loading
Loading
Loading
+192 −27
Original line number Diff line number Diff line
@@ -1079,6 +1079,7 @@ status_t AudioFlinger::createTrack(const media::CreateTrackRequest& _input,
        client = registerPid(clientPid);

        IAfPlaybackThread* effectThread = nullptr;
        sp<IAfEffectChain> effectChain = nullptr;
        // check if an effect chain with the same session ID is present on another
        // output thread and move it here.
        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -1091,6 +1092,10 @@ status_t AudioFlinger::createTrack(const media::CreateTrackRequest& _input,
                }
            }
        }
        // Check if an orphan effect chain exists for this session
        if (effectThread == nullptr) {
            effectChain = getOrphanEffectChain_l(sessionId);
        }
        ALOGV("createTrack() sessionId: %d", sessionId);

        output.sampleRate = input.config.sample_rate;
@@ -1135,6 +1140,13 @@ status_t AudioFlinger::createTrack(const media::CreateTrackRequest& _input,
                    effectIds = thread->getEffectIds_l(sessionId);
                }
            }
            if (effectChain != nullptr) {
                if (moveEffectChain_ll(sessionId, nullptr, thread, effectChain.get())
                        == NO_ERROR) {
                    effectThreadId = thread->id();
                    effectIds = thread->getEffectIds_l(sessionId);
                }
            }
        }

        // Look for sync events awaiting for a session to be used.
@@ -3059,6 +3071,25 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)


            mPlaybackThreads.removeItem(output);
            // Save AUDIO_SESSION_OUTPUT_MIX effect to orphan chains
            // Output Mix Effect session is used to manage Music Effect by AudioPolicy Manager.
            // It exists across all playback threads.
            if (playbackThread->type() == IAfThreadBase::MIXER
                    || playbackThread->type() == IAfThreadBase::OFFLOAD
                    || playbackThread->type() == IAfThreadBase::SPATIALIZER) {
                sp<IAfEffectChain> mixChain;
                {
                    audio_utils::scoped_lock sl(playbackThread->mutex());
                    mixChain = playbackThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
                    if (mixChain != nullptr) {
                        ALOGW("%s() output %d moving mix session to orphans", __func__, output);
                        playbackThread->removeEffectChain_l(mixChain);
                    }
                }
                if (mixChain != nullptr) {
                    putOrphanEffectChain_l(mixChain);
                }
            }
            // save all effects to the default thread
            if (mPlaybackThreads.size()) {
                IAfPlaybackThread* const dstThread =
@@ -4203,7 +4234,9 @@ status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request,
            // before creating the AudioEffect or the io handle must be specified.
            //
            // Detect if the effect is created after an AudioRecord is destroyed.
            if (getOrphanEffectChain_l(sessionId).get() != nullptr) {
            if (sessionId != AUDIO_SESSION_OUTPUT_MIX
                  && ((descOut.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)
                  && getOrphanEffectChain_l(sessionId).get() != nullptr) {
                ALOGE("%s: effect %s with no specified io handle is denied because the AudioRecord"
                      " for session %d no longer exists",
                      __func__, descOut.name, sessionId);
@@ -4214,11 +4247,27 @@ status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request,
            // Legacy handling of creating an effect on an expired or made-up
            // session id.  We think that it is a Playback effect.
            //
            // If no output thread contains the requested session ID, default to
            // first output. The effect chain will be moved to the correct output
            // thread when a track with the same session ID is created
            if (io == AUDIO_IO_HANDLE_NONE && mPlaybackThreads.size() > 0) {
                io = mPlaybackThreads.keyAt(0);
            // If no output thread contains the requested session ID, park the effect to
            // the orphan chains. The effect chain will be moved to the correct output
            // thread when a track with the same session ID is created.
            if (io == AUDIO_IO_HANDLE_NONE) {
                if (probe) {
                    // In probe mode, as no compatible thread found, exit with error.
                    lStatus = BAD_VALUE;
                    goto Exit;
                }
                ALOGV("%s() got io %d for effect %s", __func__, io, descOut.name);
                sp<Client> client = registerPid(currentPid);
                bool pinned = !audio_is_global_session(sessionId) && isSessionAcquired_l(sessionId);
                handle = createOrphanEffect_l(client, effectClient, priority, sessionId,
                                              &descOut, &enabledOut, &lStatus, pinned,
                                              request.notifyFramesProcessed);
                if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
                    // remove local strong reference to Client with clientMutex() held
                    audio_utils::lock_guard _cl(clientMutex());
                    client.clear();
                }
                goto Register;
            }
            ALOGV("createEffect() got io %d for effect %s", io, descOut.name);
        } else if (checkPlaybackThread_l(io) != nullptr
@@ -4259,7 +4308,8 @@ status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request,
                    goto Exit;
                }
            }
        } else {
        }
        if (thread->type() == IAfThreadBase::RECORD || sessionId == AUDIO_SESSION_OUTPUT_MIX) {
            // Check if one effect chain was awaiting for an effect to be created on this
            // session and used it instead of creating a new one.
            sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
@@ -4335,6 +4385,85 @@ Exit:
    return lStatus;
}

sp<IAfEffectHandle> AudioFlinger::createOrphanEffect_l(
        const sp<Client>& client,
        const sp<IEffectClient>& effectClient,
        int32_t priority,
        audio_session_t sessionId,
        effect_descriptor_t *desc,
        int *enabled,
        status_t *status,
        bool pinned,
        bool notifyFramesProcessed)
{
    ALOGV("%s effectClient %p, priority %d, sessionId %d, factory %p",
          __func__, effectClient.get(), priority, sessionId, mEffectsFactoryHal.get());

    // Check if an orphan effect chain exists for this session or create new chain for this session
    sp<IAfEffectModule> effect;
    sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
    bool chainCreated = false;
    if (chain == nullptr) {
        chain = IAfEffectChain::create(/* ThreadBase= */ nullptr, sessionId, this);
        chainCreated = true;
    } else {
        effect = chain->getEffectFromDesc(desc);
    }
    bool effectCreated = false;
    if (effect == nullptr) {
        audio_unique_id_t effectId = nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
        // create a new effect module if none present in the chain
        status_t llStatus =
                chain->createEffect(effect, desc, effectId, sessionId, pinned);
        if (llStatus != NO_ERROR) {
            *status = llStatus;
            // if the effect chain was not created here, put it back
            if (!chainCreated) {
                putOrphanEffectChain_l(chain);
            }
            return nullptr;
        }
        effect->setMode(getMode());

        if (effect->isHapticGenerator()) {
            // TODO(b/184194057): Use the vibrator information from the vibrator that will be used
            // for the HapticGenerator.
            const std::optional<media::AudioVibratorInfo> defaultVibratorInfo =
                    std::move(getDefaultVibratorInfo_l());
            if (defaultVibratorInfo) {
                // Only set the vibrator info when it is a valid one.
                audio_utils::lock_guard _cl(chain->mutex());
                effect->setVibratorInfo_l(*defaultVibratorInfo);
            }
        }
        effectCreated = true;
    }
    // create effect handle and connect it to effect module
    sp<IAfEffectHandle> handle =
            IAfEffectHandle::create(effect, client, effectClient, priority, notifyFramesProcessed);
    status_t lStatus = handle->initCheck();
    if (lStatus == OK) {
        lStatus = effect->addHandle(handle.get());
    }
    // in case of lStatus error, EffectHandle will still return and caller should do the clear
    if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
        if (effectCreated) {
            chain->removeEffect(effect);
        }
        // if the effect chain was not created here, put it back
        if (!chainCreated) {
            putOrphanEffectChain_l(chain);
        }
    } else {
        if (enabled != NULL) {
            *enabled = (int)effect->isEnabled();
        }
        putOrphanEffectChain_l(chain);
    }
    *status = lStatus;
    return handle;
}

status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcIo,
        audio_io_handle_t dstIo)
NO_THREAD_SAFETY_ANALYSIS
@@ -4363,17 +4492,39 @@ NO_THREAD_SAFETY_ANALYSIS
        }
        return ret;
    }
    IAfPlaybackThread* const srcThread = checkPlaybackThread_l(srcIo);
    if (srcThread == nullptr) {
        ALOGW("%s() bad srcIo %d", __func__, srcIo);
        return BAD_VALUE;
    }
    IAfPlaybackThread* const dstThread = checkPlaybackThread_l(dstIo);

    IAfPlaybackThread* dstThread = checkPlaybackThread_l(dstIo);
    if (dstThread == nullptr) {
        ALOGW("%s() bad dstIo %d", __func__, dstIo);
        return BAD_VALUE;
    }

    IAfPlaybackThread* srcThread = checkPlaybackThread_l(srcIo);
    sp<IAfEffectChain> orphanChain = getOrphanEffectChain_l(sessionId);
    if (srcThread == nullptr && orphanChain == nullptr && sessionId == AUDIO_SESSION_OUTPUT_MIX) {
        ALOGW("%s() AUDIO_SESSION_OUTPUT_MIX not found in orphans, checking other mix", __func__);
        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
            const sp<IAfPlaybackThread> pt = mPlaybackThreads.valueAt(i);
            const uint32_t sessionType = pt->hasAudioSession(AUDIO_SESSION_OUTPUT_MIX);
            if ((pt->type() == IAfThreadBase::MIXER || pt->type() == IAfThreadBase::OFFLOAD) &&
                    ((sessionType & IAfThreadBase::EFFECT_SESSION) != 0)) {
                srcThread = pt.get();
                ALOGW("%s() found srcOutput %d hosting AUDIO_SESSION_OUTPUT_MIX", __func__,
                      pt->id());
                break;
            }
        }
    }
    if (srcThread == nullptr && orphanChain == nullptr) {
        ALOGW("moveEffects() bad srcIo %d", srcIo);
        return BAD_VALUE;
    }
    // dstThread pointer validity has already been checked
    if (orphanChain != nullptr) {
        audio_utils::scoped_lock _ll(dstThread->mutex());
        return moveEffectChain_ll(sessionId, nullptr, dstThread, orphanChain.get());
    }
    // srcThread pointer validity has already been checked
    audio_utils::scoped_lock _ll(dstThread->mutex(), srcThread->mutex());
    return moveEffectChain_ll(sessionId, srcThread, dstThread);
}
@@ -4399,12 +4550,17 @@ void AudioFlinger::setEffectSuspended(int effectId,
// 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)
        IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread,
        IAfEffectChain* srcChain)
{
    ALOGV("%s: session %d from thread %p to thread %p",
            __func__, sessionId, srcThread, dstThread);
    ALOGV("%s: session %d from thread %p to thread %p %s",
            __func__, sessionId, srcThread, dstThread,
            (srcChain != nullptr ? "from specific chain" : ""));
    ALOG_ASSERT((srcThread != nullptr) != (srcChain != nullptr),
                "no source provided for source chain");

    sp<IAfEffectChain> chain = srcThread->getEffectChain_l(sessionId);
    sp<IAfEffectChain> chain =
          srcChain != nullptr ? srcChain : srcThread->getEffectChain_l(sessionId);
    if (chain == 0) {
        ALOGW("%s: effect chain for session %d not on source thread %p",
                __func__, sessionId, srcThread);
@@ -4424,8 +4580,9 @@ status_t AudioFlinger::moveEffectChain_ll(audio_session_t sessionId,
    // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
    // removed.
    // TODO(b/216875016): consider holding the effect chain locks for the duration of the move.
    if (srcThread != nullptr) {
        srcThread->removeEffectChain_l(chain);

    }
    // transfer all effects one by one so that new effect chain is created on new thread with
    // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
    sp<IAfEffectChain> dstChain;
@@ -4435,7 +4592,11 @@ status_t AudioFlinger::moveEffectChain_ll(audio_session_t sessionId,
    // process effects one by one.
    for (sp<IAfEffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
            effect = chain->getEffectFromId_l(0)) {
        if (srcThread != nullptr) {
            srcThread->removeEffect_l(effect);
        } else {
            chain->removeEffect(effect);
        }
        removed.add(effect);
        status = dstThread->addEffect_ll(effect);
        if (status != NO_ERROR) {
@@ -4463,7 +4624,7 @@ status_t AudioFlinger::moveEffectChain_ll(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_ll(effect) == NO_ERROR) {
            if (srcThread != nullptr && srcThread->addEffect_ll(effect) == NO_ERROR) {
                ++restored;
                if (dstChain == nullptr) {
                    dstChain = effect->getCallback()->chain().promote();
@@ -4494,15 +4655,19 @@ status_t AudioFlinger::moveEffectChain_ll(audio_session_t sessionId,
        if (errorString.empty()) {
            errorString = StringPrintf("%s: failed status %d", __func__, status);
        }
        ALOGW("%s: %s unsuccessful move of session %d from srcThread %p to dstThread %p "
        ALOGW("%s: %s unsuccessful move of session %d from %s %p to dstThread %p "
                "(%zu effects removed from srcThread, %zu effects restored to srcThread, "
                "%zu effects started)",
                __func__, errorString.c_str(), sessionId, srcThread, dstThread,
                __func__, errorString.c_str(), sessionId,
                (srcThread != nullptr ? "srcThread" : "srcChain"),
                (srcThread != nullptr ? (void*) srcThread : (void*) srcChain), dstThread,
                removed.size(), restored, started);
    } else {
        ALOGD("%s: successful move of session %d from srcThread %p to dstThread %p "
        ALOGD("%s: successful move of session %d from %s %p to dstThread %p "
                "(%zu effects moved, %zu effects started)",
                __func__, sessionId, srcThread, dstThread, removed.size(), started);
                __func__, sessionId, (srcThread != nullptr ? "srcThread" : "srcChain"),
                (srcThread != nullptr ? (void*) srcThread : (void*) srcChain), dstThread,
                removed.size(), started);
    }
    return status;
}
@@ -4673,7 +4838,7 @@ bool AudioFlinger::updateOrphanEffectChains_l(const sp<IAfEffectModule>& effect)
    ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
    if (index >= 0) {
        sp<IAfEffectChain> chain = mOrphanEffectChains.valueAt(index);
        if (chain->removeEffect_l(effect, true) == 0) {
        if (chain->removeEffect(effect, true) == 0) {
            ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
            mOrphanEffectChains.removeItemsAt(index);
        }
+12 −1
Original line number Diff line number Diff line
@@ -373,7 +373,8 @@ private:
            EXCLUDES_AudioFlinger_Mutex;

    status_t moveEffectChain_ll(audio_session_t sessionId,
            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final
            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread,
            IAfEffectChain* srcChain = nullptr) final
            REQUIRES(mutex(), audio_utils::ThreadBase_Mutex);

    // This is a helper that is called during incoming binder calls.
@@ -702,6 +703,16 @@ private:

    sp<Client> registerPid(pid_t pid) EXCLUDES_AudioFlinger_ClientMutex; // always returns non-0

    sp<IAfEffectHandle> createOrphanEffect_l(const sp<Client>& client,
                                          const sp<media::IEffectClient>& effectClient,
                                          int32_t priority,
                                          audio_session_t sessionId,
                                          effect_descriptor_t *desc,
                                          int *enabled,
                                          status_t *status /*non-NULL*/,
                                          bool pinned,
                                          bool notifyFramesProcessed) REQUIRES(mutex());

    // for use from destructor
    status_t closeOutput_nonvirtual(audio_io_handle_t output) EXCLUDES_AudioFlinger_Mutex;
    status_t closeInput_nonvirtual(audio_io_handle_t input) EXCLUDES_AudioFlinger_Mutex;
+60 −39

File changed.

Preview size limit exceeded, changes collapsed.

+56 −37
Original line number Diff line number Diff line
@@ -234,9 +234,9 @@ public:
    bool isSpatializer() const final;

    status_t setHapticScale_l(int id, os::HapticScale hapticScale) final
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectBase_Mutex;
            REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex;
    status_t setVibratorInfo_l(const media::AudioVibratorInfo& vibratorInfo) final
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectBase_Mutex;
            REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex;
    status_t sendMetadata_ll(const std::vector<playback_track_metadata_v7_t>& metadata) final
            REQUIRES(audio_utils::ThreadBase_Mutex,
                     audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex;
@@ -412,7 +412,9 @@ private:
// it also provide it's own input buffer used by the track as accumulation buffer.
class EffectChain : public IAfEffectChain {
public:
    EffectChain(const sp<IAfThreadBase>& thread, audio_session_t sessionId);
    EffectChain(const sp<IAfThreadBase>& thread,
                audio_session_t sessionId,
                const sp<IAfThreadCallback>& afThreadCallback);

    void process_l() final REQUIRES(audio_utils::EffectChain_Mutex);

@@ -420,25 +422,25 @@ public:
        return mMutex;
    }

    status_t createEffect_l(sp<IAfEffectModule>& effect, effect_descriptor_t* desc, int id,
    status_t createEffect(sp<IAfEffectModule>& effect, effect_descriptor_t* desc, int id,
                            audio_session_t sessionId, bool pinned) final
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
            EXCLUDES_EffectChain_Mutex;
    status_t addEffect(const sp<IAfEffectModule>& handle) final
            EXCLUDES_EffectChain_Mutex;
    status_t addEffect_l(const sp<IAfEffectModule>& handle) final
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
    status_t addEffect_ll(const sp<IAfEffectModule>& handle) final
            REQUIRES(audio_utils::ThreadBase_Mutex, audio_utils::EffectChain_Mutex);
    size_t removeEffect_l(const sp<IAfEffectModule>& handle, bool release = false) final
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
            REQUIRES(audio_utils::EffectChain_Mutex);
    size_t removeEffect(const sp<IAfEffectModule>& handle, bool release = false) final
            EXCLUDES_EffectChain_Mutex;

    audio_session_t sessionId() const final { return mSessionId; }
    void setSessionId(audio_session_t sessionId) final { mSessionId = sessionId; }

    sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t* descriptor) const final
            REQUIRES(audio_utils::ThreadBase_Mutex);
    sp<IAfEffectModule> getEffectFromDesc(effect_descriptor_t* descriptor) const final
            EXCLUDES_EffectChain_Mutex;
    sp<IAfEffectModule> getEffectFromId_l(int id) const final
            REQUIRES(audio_utils::ThreadBase_Mutex);
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
    sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t* type) const final
            REQUIRES(audio_utils::ThreadBase_Mutex);
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
    std::vector<int> getEffectIds_l() const final REQUIRES(audio_utils::ThreadBase_Mutex);
    // FIXME use float to improve the dynamic range

@@ -446,11 +448,13 @@ public:
                   bool force = false) final EXCLUDES_EffectChain_Mutex;
    void resetVolume_l() final REQUIRES(audio_utils::EffectChain_Mutex);
    void setDevices_l(const AudioDeviceTypeAddrVector& devices) final
            REQUIRES(audio_utils::ThreadBase_Mutex);
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
    void setInputDevice_l(const AudioDeviceTypeAddr& device) final
            REQUIRES(audio_utils::ThreadBase_Mutex);
    void setMode_l(audio_mode_t mode) final REQUIRES(audio_utils::ThreadBase_Mutex);
    void setAudioSource_l(audio_source_t source) final REQUIRES(audio_utils::ThreadBase_Mutex);
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
    void setMode_l(audio_mode_t mode) final
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
    void setAudioSource_l(audio_source_t source) final
            REQUIRES(audio_utils::ThreadBase_Mutex)  EXCLUDES_EffectChain_Mutex;

    void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final {
        mInBuffer = buffer;
@@ -517,8 +521,11 @@ public:
    bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;

    // Requires either IAfThreadBase::mutex() or EffectChain::mutex() held
    bool containsHapticGeneratingEffect_l() final;
    bool containsHapticGeneratingEffect() final
            EXCLUDES_EffectChain_Mutex;

    bool containsHapticGeneratingEffect_l() final
            REQUIRES(audio_utils::EffectChain_Mutex);

    void setHapticScale_l(int id, os::HapticScale hapticScale) final
            REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
@@ -527,15 +534,19 @@ public:

    wp<IAfThreadBase> thread() const final { return mEffectCallback->thread(); }

    bool isFirstEffect(int id) const final {
    bool isFirstEffect_l(int id) const final REQUIRES(audio_utils::EffectChain_Mutex) {
        return !mEffects.isEmpty() && id == mEffects[0]->id();
    }

    void dump(int fd, const Vector<String16>& args) const final;

    size_t numberOfEffects() const final { return mEffects.size(); }
    size_t numberOfEffects() const final {
      audio_utils::lock_guard _l(mutex());
      return mEffects.size();
    }

    sp<IAfEffectModule> getEffectModule(size_t index) const final {
        audio_utils::lock_guard _l(mutex());
        return mEffects[index];
    }

@@ -560,11 +571,13 @@ public:
        // Note: ctors taking a weak pointer to their owner must not promote it
        // during construction (but may keep a reference for later promotion).
        EffectCallback(const wp<EffectChain>& owner,
                const sp<IAfThreadBase>& thread)  // we take a sp<> but store a wp<>.
                const sp<IAfThreadBase>& thread,
                const sp<IAfThreadCallback>& afThreadCallback)  // we take a sp<> but store a wp<>.
            : mChain(owner)
            , mThread(thread) {
            , mThread(thread), mAfThreadCallback(afThreadCallback) {
            if (thread != nullptr) {
                mThreadType = thread->type();
            mAfThreadCallback = thread->afThreadCallback();
            }
        }

        status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -606,6 +619,9 @@ public:
        wp<IAfEffectChain> chain() const final { return mChain; }

        bool isAudioPolicyReady() const final {
            if (mAfThreadCallback == nullptr) {
                return false;
            }
            return mAfThreadCallback->isAudioPolicyReady();
        }

@@ -613,15 +629,19 @@ public:

        void setThread(const sp<IAfThreadBase>& thread) {
            mThread = thread;
            if (thread != nullptr) {
                mThreadType = thread->type();
                mAfThreadCallback = thread->afThreadCallback();
            }

        }
        bool hasThreadAttached() const {
            return thread().promote() != nullptr;
        }
    private:
        const wp<IAfEffectChain> mChain;
        mediautils::atomic_wp<IAfThreadBase> mThread;
        sp<IAfThreadCallback> mAfThreadCallback;
        IAfThreadBase::type_t mThreadType;
        IAfThreadBase::type_t mThreadType = IAfThreadBase::MIXER;
    };

    DISALLOW_COPY_AND_ASSIGN(EffectChain);
@@ -637,8 +657,8 @@ public:

    // get a list of effect modules to suspend when an effect of the type
    // passed is enabled.
    void getSuspendEligibleEffects_l(Vector<sp<IAfEffectModule>>& effects)
            REQUIRES(audio_utils::ThreadBase_Mutex);
    void getSuspendEligibleEffects(Vector<sp<IAfEffectModule>>& effects)
            EXCLUDES_EffectChain_Mutex;

    // get an effect module if it is currently enable
    sp<IAfEffectModule> getEffectIfEnabled_l(const effect_uuid_t* type)
@@ -646,8 +666,7 @@ public:
    // true if the effect whose descriptor is passed can be suspended
    // OEMs can modify the rules implemented in this method to exclude specific effect
    // types or implementations from the suspend/restore mechanism.
    bool isEffectEligibleForSuspend_l(const effect_descriptor_t& desc)
            REQUIRES(audio_utils::ThreadBase_Mutex);
    bool isEffectEligibleForSuspend(const effect_descriptor_t& desc);

    static bool isEffectEligibleForBtNrecSuspend_l(const effect_uuid_t* type)
            REQUIRES(audio_utils::ThreadBase_Mutex);
@@ -660,15 +679,15 @@ public:
    void setVolumeForOutput_l(uint32_t left, uint32_t right)
            REQUIRES(audio_utils::EffectChain_Mutex);

    ssize_t getInsertIndex_ll(const effect_descriptor_t& desc)
            REQUIRES(audio_utils::ThreadBase_Mutex, audio_utils::EffectChain_Mutex);
    ssize_t getInsertIndex_l(const effect_descriptor_t& desc)
            REQUIRES(audio_utils::EffectChain_Mutex);

    std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const
            REQUIRES(audio_utils::EffectChain_Mutex);

    // mutex protecting effect list
    mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kEffectChain_Mutex};
             Vector<sp<IAfEffectModule>> mEffects; // list of effect modules
             Vector<sp<IAfEffectModule>> mEffects  GUARDED_BY(mutex()); // list of effect modules
             audio_session_t mSessionId; // audio session ID
             sp<EffectBufferHalInterface> mInBuffer;  // chain input buffer
             sp<EffectBufferHalInterface> mOutBuffer; // chain output buffer
+24 −18

File changed.

Preview size limit exceeded, changes collapsed.

Loading