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

Commit 1b928680 authored by Eric Laurent's avatar Eric Laurent
Browse files

audioflinger: fix pre processing transfer between record threads.

Fix two problems remaining with pre processing effects transfer from
one record thread to the next in case of tear down due to device connection:
1 - the enabled state of the effects was not communicated to the new HAL
input stream.
2 - the effects saved in orphan chains list were not transfered to the
new thread when a AudioRecord was created.

Bug: 17757378.
Change-Id: I0923c98470db3b51154dc89846157780a4c21e86
parent d8b03abf
Loading
Loading
Loading
Loading
+43 −5
Original line number Diff line number Diff line
@@ -1436,6 +1436,16 @@ sp<IAudioRecord> AudioFlinger::openRecord(
                                                  IPCThreadState::self()->getCallingUid(),
                                                  flags, tid, &lStatus);
        LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));

        if (lStatus == NO_ERROR) {
            // Check if one effect chain was awaiting for an AudioRecord to be created on this
            // session and move it to this thread.
            sp<EffectChain> chain = getOrphanEffectChain_l((audio_session_t)lSessionId);
            if (chain != 0) {
                Mutex::Autolock _l(thread->mLock);
                thread->addEffectChain_l(chain);
            }
        }
    }

    if (lStatus != NO_ERROR) {
@@ -2034,14 +2044,41 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input)
        }

        ALOGV("closeInput() %d", input);
        {

        // If we still have effect chains, it means that a client still holds a handle
            // on at least one effect. We must keep the chain alive in case a new record
            // thread is opened for a new capture on the same session
        // on at least one effect. We must either move the chain to an existing thread with the
        // same session ID or put it aside in case a new record thread is opened for a
        // new capture on the same session
        sp<EffectChain> chain;
        {
            Mutex::Autolock _sl(thread->mLock);
            Vector< sp<EffectChain> > effectChains = thread->getEffectChains_l();
            for (size_t i = 0; i < effectChains.size(); i++) {
                putOrphanEffectChain_l(effectChains[i]);
            // Note: maximum one chain per record thread
            if (effectChains.size() != 0) {
                chain = effectChains[0];
            }
        }
        if (chain != 0) {
            // first check if a record thread is already opened with a client on the same session.
            // This should only happen in case of overlap between one thread tear down and the
            // creation of its replacement
            size_t i;
            for (i = 0; i < mRecordThreads.size(); i++) {
                sp<RecordThread> t = mRecordThreads.valueAt(i);
                if (t == thread) {
                    continue;
                }
                if (t->hasAudioSession(chain->sessionId()) != 0) {
                    Mutex::Autolock _l(t->mLock);
                    ALOGV("closeInput() found thread %d for effect session %d",
                          t->id(), chain->sessionId());
                    t->addEffectChain_l(chain);
                    break;
                }
            }
            // put the chain aside if we could not find a record thread with the same session id.
            if (i == mRecordThreads.size()) {
                putOrphanEffectChain_l(chain);
            }
        }
        audioConfigChanged(AudioSystem::INPUT_CLOSED, input, NULL);
@@ -2478,6 +2515,7 @@ sp<IEffect> AudioFlinger::createEffect(
            // session and used it instead of creating a new one.
            sp<EffectChain> chain = getOrphanEffectChain_l((audio_session_t)sessionId);
            if (chain != 0) {
                Mutex::Autolock _l(thread->mLock);
                thread->addEffectChain_l(chain);
            }
        }
+26 −10
Original line number Diff line number Diff line
@@ -440,6 +440,20 @@ status_t AudioFlinger::EffectModule::init()
    return status;
}

void AudioFlinger::EffectModule::addEffectToHal_l()
{
    if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
         (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
        sp<ThreadBase> thread = mThread.promote();
        if (thread != 0) {
            audio_stream_t *stream = thread->stream();
            if (stream != NULL) {
                stream->add_audio_effect(stream, mEffectInterface);
            }
        }
    }
}

status_t AudioFlinger::EffectModule::start()
{
    Mutex::Autolock _l(mLock);
@@ -466,16 +480,7 @@ status_t AudioFlinger::EffectModule::start_l()
        status = cmdStatus;
    }
    if (status == 0) {
        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
             (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
            sp<ThreadBase> thread = mThread.promote();
            if (thread != 0) {
                audio_stream_t *stream = thread->stream();
                if (stream != NULL) {
                    stream->add_audio_effect(stream, mEffectInterface);
                }
            }
        }
        addEffectToHal_l();
        sp<EffectChain> chain = mChain.promote();
        if (chain != 0) {
            chain->forceVolume();
@@ -1696,6 +1701,17 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
    return hasControl;
}

void AudioFlinger::EffectChain::syncHalEffectsState()
{
    Mutex::Autolock _l(mLock);
    for (size_t i = 0; i < mEffects.size(); i++) {
        if (mEffects[i]->state() == EffectModule::ACTIVE ||
                mEffects[i]->state() == EffectModule::STOPPING) {
            mEffects[i]->addEffectToHal_l();
        }
    }
}

void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
{
    const size_t SIZE = 256;
+3 −0
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ public:
                        { return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; }
    status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
    bool             isOffloaded() const;
    void             addEffectToHal_l();

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

@@ -325,6 +326,8 @@ public:
    // we are the only observers.
    bool isVolumeForced() { return (android_atomic_acquire_cas(true, false, &mForceVolume) == 0); }

    void syncHalEffectsState();

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

protected:
+4 −0
Original line number Diff line number Diff line
@@ -6192,6 +6192,10 @@ status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& cha

    checkSuspendOnAddEffectChain_l(chain);

    // make sure enabled pre processing effects state is communicated to the HAL as we
    // just moved them to a new input stream.
    chain->syncHalEffectsState();

    mEffectChains.add(chain);

    return NO_ERROR;