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

Commit 993c09b2 authored by Eric Laurent's avatar Eric Laurent Committed by android-build-merger
Browse files

DO NOT MERGE - improve audio effect framwework thread safety

am: b378b73d

Change-Id: Ie7431955f75364bb7e450594387be41f669a98f0
parents 49209a36 b378b73d
Loading
Loading
Loading
Loading
+18 −5
Original line number Original line Diff line number Diff line
@@ -2396,6 +2396,18 @@ void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid
    ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller);
    ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller);
}
}


bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession)
{
    size_t num = mAudioSessionRefs.size();
    for (size_t i = 0; i < num; i++) {
        AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
        if (ref->mSessionid == audioSession) {
            return true;
        }
    }
    return false;
}

void AudioFlinger::purgeStaleEffects_l() {
void AudioFlinger::purgeStaleEffects_l() {


    ALOGV("purging stale effects");
    ALOGV("purging stale effects");
@@ -2789,8 +2801,9 @@ sp<IEffect> AudioFlinger::createEffect(
        sp<Client> client = registerPid(pid);
        sp<Client> client = registerPid(pid);


        // create effect on selected output thread
        // create effect on selected output thread
        bool pinned = (sessionId > AUDIO_SESSION_OUTPUT_MIX) && isSessionAcquired_l(sessionId);
        handle = thread->createEffect_l(client, effectClient, priority, sessionId,
        handle = thread->createEffect_l(client, effectClient, priority, sessionId,
                &desc, enabled, &lStatus);
                &desc, enabled, &lStatus, pinned);
        if (handle != 0 && id != NULL) {
        if (handle != 0 && id != NULL) {
            *id = handle->id();
            *id = handle->id();
        }
        }
@@ -2987,7 +3000,7 @@ bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule>
    ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
    ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
    if (index >= 0) {
    if (index >= 0) {
        sp<EffectChain> chain = mOrphanEffectChains.valueAt(index);
        sp<EffectChain> chain = mOrphanEffectChains.valueAt(index);
        if (chain->removeEffect_l(effect) == 0) {
        if (chain->removeEffect_l(effect, true) == 0) {
            ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
            ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
            mOrphanEffectChains.removeItemsAt(index);
            mOrphanEffectChains.removeItemsAt(index);
        }
        }
+1 −0
Original line number Original line Diff line number Diff line
@@ -585,6 +585,7 @@ private:
                void        removeNotificationClient(pid_t pid);
                void        removeNotificationClient(pid_t pid);
                bool isNonOffloadableGlobalEffectEnabled_l();
                bool isNonOffloadableGlobalEffectEnabled_l();
                void onNonOffloadableGlobalEffectEnable();
                void onNonOffloadableGlobalEffectEnable();
                bool isSessionAcquired_l(audio_session_t audioSession);


                // Store an effect chain to mOrphanEffectChains keyed vector.
                // Store an effect chain to mOrphanEffectChains keyed vector.
                // Called when a thread exits and effects are still attached to it.
                // Called when a thread exits and effects are still attached to it.
+140 −87
Original line number Original line Diff line number Diff line
@@ -59,8 +59,9 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
                                        const wp<AudioFlinger::EffectChain>& chain,
                                        const wp<AudioFlinger::EffectChain>& chain,
                                        effect_descriptor_t *desc,
                                        effect_descriptor_t *desc,
                                        int id,
                                        int id,
                                        audio_session_t sessionId)
                                        audio_session_t sessionId,
    : mPinned(sessionId > AUDIO_SESSION_OUTPUT_MIX),
                                        bool pinned)
    : mPinned(pinned),
      mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
      mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
      mDescriptor(*desc),
      mDescriptor(*desc),
      // mConfig is set by configure() and not used before then
      // mConfig is set by configure() and not used before then
@@ -71,7 +72,7 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
      mSuspended(false),
      mSuspended(false),
      mAudioFlinger(thread->mAudioFlinger)
      mAudioFlinger(thread->mAudioFlinger)
{
{
    ALOGV("Constructor %p", this);
    ALOGV("Constructor %p pinned %d", this, pinned);
    int lStatus;
    int lStatus;


    // create effect engine from effect factory
    // create effect engine from effect factory
@@ -86,6 +87,8 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
        goto Error;
        goto Error;
    }
    }


    setOffloaded(thread->type() == ThreadBase::OFFLOAD, thread->id());

    ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
    ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
    return;
    return;
Error:
Error:
@@ -98,9 +101,8 @@ AudioFlinger::EffectModule::~EffectModule()
{
{
    ALOGV("Destructor %p", this);
    ALOGV("Destructor %p", this);
    if (mEffectInterface != NULL) {
    if (mEffectInterface != NULL) {
        remove_effect_from_hal_l();
        ALOGW("EffectModule %p destructor called with unreleased interface", this);
        // release effect engine
        release_l();
        EffectRelease(mEffectInterface);
    }
    }
}
}


@@ -115,7 +117,7 @@ status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle)
    size_t i;
    size_t i;
    for (i = 0; i < size; i++) {
    for (i = 0; i < size; i++) {
        EffectHandle *h = mHandles[i];
        EffectHandle *h = mHandles[i];
        if (h == NULL || h->destroyed_l()) {
        if (h == NULL || h->disconnected()) {
            continue;
            continue;
        }
        }
        // first non destroyed handle is considered in control
        // first non destroyed handle is considered in control
@@ -143,9 +145,14 @@ status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle)
    return status;
    return status;
}
}


size_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle)
ssize_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle)
{
{
    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);
    return removeHandle_l(handle);
}

ssize_t AudioFlinger::EffectModule::removeHandle_l(EffectHandle *handle)
{
    size_t size = mHandles.size();
    size_t size = mHandles.size();
    size_t i;
    size_t i;
    for (i = 0; i < size; i++) {
    for (i = 0; i < size; i++) {
@@ -154,9 +161,10 @@ size_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle)
        }
        }
    }
    }
    if (i == size) {
    if (i == size) {
        return size;
        ALOGW("%s %p handle not found %p", __FUNCTION__, this, handle);
        return BAD_VALUE;
    }
    }
    ALOGV("removeHandle() %p removed handle %p in position %zu", this, handle, i);
    ALOGV("removeHandle_l() %p removed handle %p in position %zu", this, handle, i);


    mHandles.removeAt(i);
    mHandles.removeAt(i);
    // if removed from first place, move effect control from this handle to next in line
    // if removed from first place, move effect control from this handle to next in line
@@ -183,7 +191,7 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l()
    // the first valid handle in the list has control over the module
    // the first valid handle in the list has control over the module
    for (size_t i = 0; i < mHandles.size(); i++) {
    for (size_t i = 0; i < mHandles.size(); i++) {
        EffectHandle *h = mHandles[i];
        EffectHandle *h = mHandles[i];
        if (h != NULL && !h->destroyed_l()) {
        if (h != NULL && !h->disconnected()) {
            return h;
            return h;
        }
        }
    }
    }
@@ -191,29 +199,22 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l()
    return NULL;
    return NULL;
}
}


size_t AudioFlinger::EffectModule::disconnect(EffectHandle *handle, bool unpinIfLast)
// unsafe method called when the effect parent thread has been destroyed
ssize_t AudioFlinger::EffectModule::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
{
{
    ALOGV("disconnect() %p handle %p", this, handle);
    ALOGV("disconnect() %p handle %p", this, handle);
    // keep a strong reference on this EffectModule to avoid calling the
    Mutex::Autolock _l(mLock);
    // destructor before we exit
    ssize_t numHandles = removeHandle_l(handle);
    sp<EffectModule> keep(this);
    if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
    {
        AudioSystem::unregisterEffect(mId);
        if (removeHandle(handle) == 0) {
            if (!isPinned() || unpinIfLast) {
                sp<ThreadBase> thread = mThread.promote();
                if (thread != 0) {
                    Mutex::Autolock _l(thread->mLock);
                    thread->removeEffect_l(this);
                }
        sp<AudioFlinger> af = mAudioFlinger.promote();
        sp<AudioFlinger> af = mAudioFlinger.promote();
        if (af != 0) {
        if (af != 0) {
            mLock.unlock();
            af->updateOrphanEffectChains(this);
            af->updateOrphanEffectChains(this);
                }
            mLock.lock();
                AudioSystem::unregisterEffect(mId);
            }
        }
        }
    }
    }
    return mHandles.size();
    return numHandles;
}
}


bool AudioFlinger::EffectModule::updateState() {
bool AudioFlinger::EffectModule::updateState() {
@@ -557,6 +558,17 @@ status_t AudioFlinger::EffectModule::stop_l()
    return status;
    return status;
}
}


// must be called with EffectChain::mLock held
void AudioFlinger::EffectModule::release_l()
{
    if (mEffectInterface != NULL) {
        remove_effect_from_hal_l();
        // release effect engine
        EffectRelease(mEffectInterface);
        mEffectInterface = NULL;
    }
}

status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
{
{
    if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
    if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
@@ -649,7 +661,7 @@ status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
        uint32_t size = (replySize == NULL) ? 0 : *replySize;
        uint32_t size = (replySize == NULL) ? 0 : *replySize;
        for (size_t i = 1; i < mHandles.size(); i++) {
        for (size_t i = 1; i < mHandles.size(); i++) {
            EffectHandle *h = mHandles[i];
            EffectHandle *h = mHandles[i];
            if (h != NULL && !h->destroyed_l()) {
            if (h != NULL && !h->disconnected()) {
                h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
                h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
            }
            }
        }
        }
@@ -702,7 +714,7 @@ status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled)
        }
        }
        for (size_t i = 1; i < mHandles.size(); i++) {
        for (size_t i = 1; i < mHandles.size(); i++) {
            EffectHandle *h = mHandles[i];
            EffectHandle *h = mHandles[i];
            if (h != NULL && !h->destroyed_l()) {
            if (h != NULL && !h->disconnected()) {
                h->setEnabled(enabled);
                h->setEnabled(enabled);
            }
            }
        }
        }
@@ -866,8 +878,7 @@ bool AudioFlinger::EffectModule::purgeHandles()
    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);
    for (size_t i = 0; i < mHandles.size(); i++) {
    for (size_t i = 0; i < mHandles.size(); i++) {
        EffectHandle *handle = mHandles[i];
        EffectHandle *handle = mHandles[i];
        if (handle != NULL && !handle->destroyed_l()) {
        if (handle != NULL && !handle->disconnected()) {
            handle->effect().clear();
            if (handle->hasControl()) {
            if (handle->hasControl()) {
                enabled = handle->enabled();
                enabled = handle->enabled();
            }
            }
@@ -1094,7 +1105,7 @@ void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args __unu
    result.append("\t\t\t  Pid Priority Ctrl Locked client server\n");
    result.append("\t\t\t  Pid Priority Ctrl Locked client server\n");
    for (size_t i = 0; i < mHandles.size(); ++i) {
    for (size_t i = 0; i < mHandles.size(); ++i) {
        EffectHandle *handle = mHandles[i];
        EffectHandle *handle = mHandles[i];
        if (handle != NULL && !handle->destroyed_l()) {
        if (handle != NULL && !handle->disconnected()) {
            handle->dumpToBuffer(buffer, SIZE);
            handle->dumpToBuffer(buffer, SIZE);
            result.append(buffer);
            result.append(buffer);
        }
        }
@@ -1120,7 +1131,7 @@ AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
                                        int32_t priority)
                                        int32_t priority)
    : BnEffect(),
    : BnEffect(),
    mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
    mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
    mPriority(priority), mHasControl(false), mEnabled(false), mDestroyed(false)
    mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false)
{
{
    ALOGV("constructor %p", this);
    ALOGV("constructor %p", this);


@@ -1143,14 +1154,6 @@ AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
AudioFlinger::EffectHandle::~EffectHandle()
AudioFlinger::EffectHandle::~EffectHandle()
{
{
    ALOGV("Destructor %p", this);
    ALOGV("Destructor %p", this);

    if (mEffect == 0) {
        mDestroyed = true;
        return;
    }
    mEffect->lock();
    mDestroyed = true;
    mEffect->unlock();
    disconnect(false);
    disconnect(false);
}
}


@@ -1161,13 +1164,15 @@ status_t AudioFlinger::EffectHandle::initCheck()


status_t AudioFlinger::EffectHandle::enable()
status_t AudioFlinger::EffectHandle::enable()
{
{
    AutoMutex _l(mLock);
    ALOGV("enable %p", this);
    ALOGV("enable %p", this);
    sp<EffectModule> effect = mEffect.promote();
    if (effect == 0 || mDisconnected) {
        return DEAD_OBJECT;
    }
    if (!mHasControl) {
    if (!mHasControl) {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }
    if (mEffect == 0) {
        return DEAD_OBJECT;
    }


    if (mEnabled) {
    if (mEnabled) {
        return NO_ERROR;
        return NO_ERROR;
@@ -1175,20 +1180,20 @@ status_t AudioFlinger::EffectHandle::enable()


    mEnabled = true;
    mEnabled = true;


    sp<ThreadBase> thread = mEffect->thread().promote();
    sp<ThreadBase> thread = effect->thread().promote();
    if (thread != 0) {
    if (thread != 0) {
        thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
        thread->checkSuspendOnEffectEnabled(effect, true, effect->sessionId());
    }
    }


    // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
    // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
    if (mEffect->suspended()) {
    if (effect->suspended()) {
        return NO_ERROR;
        return NO_ERROR;
    }
    }


    status_t status = mEffect->setEnabled(true);
    status_t status = effect->setEnabled(true);
    if (status != NO_ERROR) {
    if (status != NO_ERROR) {
        if (thread != 0) {
        if (thread != 0) {
            thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
            thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
        }
        }
        mEnabled = false;
        mEnabled = false;
    } else {
    } else {
@@ -1198,12 +1203,12 @@ status_t AudioFlinger::EffectHandle::enable()
                Mutex::Autolock _l(t->mLock);
                Mutex::Autolock _l(t->mLock);
                t->broadcast_l();
                t->broadcast_l();
            }
            }
            if (!mEffect->isOffloadable()) {
            if (!effect->isOffloadable()) {
                if (thread->type() == ThreadBase::OFFLOAD) {
                if (thread->type() == ThreadBase::OFFLOAD) {
                    PlaybackThread *t = (PlaybackThread *)thread.get();
                    PlaybackThread *t = (PlaybackThread *)thread.get();
                    t->invalidateTracks(AUDIO_STREAM_MUSIC);
                    t->invalidateTracks(AUDIO_STREAM_MUSIC);
                }
                }
                if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
                if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
                    thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable();
                    thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable();
                }
                }
            }
            }
@@ -1215,27 +1220,29 @@ status_t AudioFlinger::EffectHandle::enable()
status_t AudioFlinger::EffectHandle::disable()
status_t AudioFlinger::EffectHandle::disable()
{
{
    ALOGV("disable %p", this);
    ALOGV("disable %p", this);
    AutoMutex _l(mLock);
    sp<EffectModule> effect = mEffect.promote();
    if (effect == 0 || mDisconnected) {
        return DEAD_OBJECT;
    }
    if (!mHasControl) {
    if (!mHasControl) {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }
    if (mEffect == 0) {
        return DEAD_OBJECT;
    }


    if (!mEnabled) {
    if (!mEnabled) {
        return NO_ERROR;
        return NO_ERROR;
    }
    }
    mEnabled = false;
    mEnabled = false;


    if (mEffect->suspended()) {
    if (effect->suspended()) {
        return NO_ERROR;
        return NO_ERROR;
    }
    }


    status_t status = mEffect->setEnabled(false);
    status_t status = effect->setEnabled(false);


    sp<ThreadBase> thread = mEffect->thread().promote();
    sp<ThreadBase> thread = effect->thread().promote();
    if (thread != 0) {
    if (thread != 0) {
        thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
        thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
        if (thread->type() == ThreadBase::OFFLOAD) {
        if (thread->type() == ThreadBase::OFFLOAD) {
            PlaybackThread *t = (PlaybackThread *)thread.get();
            PlaybackThread *t = (PlaybackThread *)thread.get();
            Mutex::Autolock _l(t->mLock);
            Mutex::Autolock _l(t->mLock);
@@ -1248,25 +1255,39 @@ status_t AudioFlinger::EffectHandle::disable()


void AudioFlinger::EffectHandle::disconnect()
void AudioFlinger::EffectHandle::disconnect()
{
{
    ALOGV("%s %p", __FUNCTION__, this);
    disconnect(true);
    disconnect(true);
}
}


void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
{
{
    ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
    AutoMutex _l(mLock);
    if (mEffect == 0) {
    ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
    if (mDisconnected) {
        if (unpinIfLast) {
            android_errorWriteLog(0x534e4554, "32707507");
        }
        return;
        return;
    }
    }
    // restore suspended effects if the disconnected handle was enabled and the last one.
    mDisconnected = true;
    if ((mEffect->disconnect(this, unpinIfLast) == 0) && mEnabled) {
    sp<ThreadBase> thread;
        sp<ThreadBase> thread = mEffect->thread().promote();
    {
        sp<EffectModule> effect = mEffect.promote();
        if (effect != 0) {
            thread = effect->thread().promote();
        }
    }
    if (thread != 0) {
    if (thread != 0) {
            thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
        thread->disconnectEffectHandle(this, unpinIfLast);
    } else {
        ALOGW("%s Effect handle %p disconnected after thread destruction", __FUNCTION__, this);
        // try to cleanup as much as we can
        sp<EffectModule> effect = mEffect.promote();
        if (effect != 0) {
            effect->disconnectHandle(this, unpinIfLast);
        }
        }
    }
    }


    // release sp on module => module destructor can be called now
    mEffect.clear();
    if (mClient != 0) {
    if (mClient != 0) {
        if (mCblk != NULL) {
        if (mCblk != NULL) {
            // unlike ~TrackBase(), mCblk is never a local new, so don't delete
            // unlike ~TrackBase(), mCblk is never a local new, so don't delete
@@ -1286,15 +1307,17 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
                                             void *pReplyData)
                                             void *pReplyData)
{
{
    ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
    ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
            cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
            cmdCode, mHasControl, mEffect.unsafe_get());


    AutoMutex _l(mLock);
    sp<EffectModule> effect = mEffect.promote();
    if (effect == 0 || mDisconnected) {
        return DEAD_OBJECT;
    }
    // only get parameter command is permitted for applications not controlling the effect
    // only get parameter command is permitted for applications not controlling the effect
    if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
    if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }
    if (mEffect == 0) {
        return DEAD_OBJECT;
    }
    if (mClient == 0) {
    if (mClient == 0) {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }
@@ -1339,7 +1362,7 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,


            int reply = 0;
            int reply = 0;
            uint32_t rsize = sizeof(reply);
            uint32_t rsize = sizeof(reply);
            status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
            status_t ret = effect->command(EFFECT_CMD_SET_PARAM,
                                            size,
                                            size,
                                            param,
                                            param,
                                            &rsize,
                                            &rsize,
@@ -1376,7 +1399,7 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
        return disable();
        return disable();
    }
    }


    return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
    return effect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
}
}


void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
@@ -1458,7 +1481,6 @@ AudioFlinger::EffectChain::~EffectChain()
    if (mOwnInBuffer) {
    if (mOwnInBuffer) {
        delete mInBuffer;
        delete mInBuffer;
    }
    }

}
}


// getEffectFromDesc_l() must be called with ThreadBase::mLock held
// getEffectFromDesc_l() must be called with ThreadBase::mLock held
@@ -1574,13 +1596,38 @@ void AudioFlinger::EffectChain::process_l()
    }
    }
}
}


// addEffect_l() must be called with PlaybackThread::mLock held
// createEffect_l() must be called with ThreadBase::mLock held
status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect,
                                                   ThreadBase *thread,
                                                   effect_descriptor_t *desc,
                                                   int id,
                                                   audio_session_t sessionId,
                                                   bool pinned)
{
    Mutex::Autolock _l(mLock);
    effect = new EffectModule(thread, this, desc, id, sessionId, pinned);
    status_t lStatus = effect->status();
    if (lStatus == NO_ERROR) {
        lStatus = addEffect_ll(effect);
    }
    if (lStatus != NO_ERROR) {
        effect.clear();
    }
    return lStatus;
}

// addEffect_l() must be called with ThreadBase::mLock held
status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
{
    Mutex::Autolock _l(mLock);
    return addEffect_ll(effect);
}
// addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held
status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
{
{
    effect_descriptor_t desc = effect->desc();
    effect_descriptor_t desc = effect->desc();
    uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
    uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;


    Mutex::Autolock _l(mLock);
    effect->setChain(this);
    effect->setChain(this);
    sp<ThreadBase> thread = mThread.promote();
    sp<ThreadBase> thread = mThread.promote();
    if (thread == 0) {
    if (thread == 0) {
@@ -1690,8 +1737,9 @@ status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
    return NO_ERROR;
    return NO_ERROR;
}
}


// removeEffect_l() must be called with PlaybackThread::mLock held
// removeEffect_l() must be called with ThreadBase::mLock held
size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect,
                                                 bool release)
{
{
    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);
    size_t size = mEffects.size();
    size_t size = mEffects.size();
@@ -1706,6 +1754,10 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
                    mEffects[i]->state() == EffectModule::STOPPING) {
                    mEffects[i]->state() == EffectModule::STOPPING) {
                mEffects[i]->stop();
                mEffects[i]->stop();
            }
            }
            if (release) {
                mEffects[i]->release_l();
            }

            if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
            if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
                delete[] effect->inBuffer();
                delete[] effect->inBuffer();
            } else {
            } else {
@@ -1717,6 +1769,7 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
            mEffects.removeAt(i);
            mEffects.removeAt(i);
            ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %zu", effect.get(),
            ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %zu", effect.get(),
                    this, i);
                    this, i);

            break;
            break;
        }
        }
    }
    }
@@ -1724,7 +1777,7 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
    return mEffects.size();
    return mEffects.size();
}
}


// setDevice_l() must be called with PlaybackThread::mLock held
// setDevice_l() must be called with ThreadBase::mLock held
void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device)
void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device)
{
{
    size_t size = mEffects.size();
    size_t size = mEffects.size();
@@ -1733,7 +1786,7 @@ void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device)
    }
    }
}
}


// setMode_l() must be called with PlaybackThread::mLock held
// setMode_l() must be called with ThreadBase::mLock held
void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
{
{
    size_t size = mEffects.size();
    size_t size = mEffects.size();
@@ -1742,7 +1795,7 @@ void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
    }
    }
}
}


// setAudioSource_l() must be called with PlaybackThread::mLock held
// setAudioSource_l() must be called with ThreadBase::mLock held
void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
{
{
    size_t size = mEffects.size();
    size_t size = mEffects.size();
@@ -1751,7 +1804,7 @@ void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
    }
    }
}
}


// setVolume_l() must be called with PlaybackThread::mLock or EffectChain::mLock held
// setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
{
{
    uint32_t newLeft = *left;
    uint32_t newLeft = *left;
@@ -1812,7 +1865,7 @@ bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, boo
    return hasControl;
    return hasControl;
}
}


// resetVolume_l() must be called with PlaybackThread::mLock or EffectChain::mLock held
// resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
void AudioFlinger::EffectChain::resetVolume_l()
void AudioFlinger::EffectChain::resetVolume_l()
{
{
    if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
    if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
@@ -1913,7 +1966,7 @@ void AudioFlinger::EffectChain::setEffectSuspended_l(
                    effect->setSuspended(false);
                    effect->setSuspended(false);
                    effect->lock();
                    effect->lock();
                    EffectHandle *handle = effect->controlHandle_l();
                    EffectHandle *handle = effect->controlHandle_l();
                    if (handle != NULL && !handle->destroyed_l()) {
                    if (handle != NULL && !handle->disconnected()) {
                        effect->setEnabled_l(handle->enabled());
                        effect->setEnabled_l(handle->enabled());
                    }
                    }
                    effect->unlock();
                    effect->unlock();
+26 −11
Original line number Original line Diff line number Diff line
@@ -45,7 +45,8 @@ public:
                    const wp<AudioFlinger::EffectChain>& chain,
                    const wp<AudioFlinger::EffectChain>& chain,
                    effect_descriptor_t *desc,
                    effect_descriptor_t *desc,
                    int id,
                    int id,
                    audio_session_t sessionId);
                    audio_session_t sessionId,
                    bool pinned);
    virtual ~EffectModule();
    virtual ~EffectModule();


    enum effect_state {
    enum effect_state {
@@ -93,8 +94,9 @@ public:
    const wp<ThreadBase>& thread() { return mThread; }
    const wp<ThreadBase>& thread() { return mThread; }


    status_t addHandle(EffectHandle *handle);
    status_t addHandle(EffectHandle *handle);
    size_t disconnect(EffectHandle *handle, bool unpinIfLast);
    ssize_t  disconnectHandle(EffectHandle *handle, bool unpinIfLast);
    size_t removeHandle(EffectHandle *handle);
    ssize_t removeHandle(EffectHandle *handle);
    ssize_t removeHandle_l(EffectHandle *handle);


    const effect_descriptor_t& desc() const { return mDescriptor; }
    const effect_descriptor_t& desc() const { return mDescriptor; }
    wp<EffectChain>&     chain() { return mChain; }
    wp<EffectChain>&     chain() { return mChain; }
@@ -124,6 +126,7 @@ public:
    status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
    status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
    bool             isOffloaded() const;
    bool             isOffloaded() const;
    void             addEffectToHal_l();
    void             addEffectToHal_l();
    void             release_l();


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


@@ -208,12 +211,17 @@ public:
    bool enabled() const { return mEnabled; }
    bool enabled() const { return mEnabled; }


    // Getters
    // Getters
    int id() const { return mEffect->id(); }
    wp<EffectModule> effect() const { return mEffect; }
    int id() const {
        sp<EffectModule> effect = mEffect.promote();
        if (effect == 0) {
            return 0;
        }
        return effect->id();
    }
    int priority() const { return mPriority; }
    int priority() const { return mPriority; }
    bool hasControl() const { return mHasControl; }
    bool hasControl() const { return mHasControl; }
    sp<EffectModule> effect() const { return mEffect; }
    bool disconnected() const { return mDisconnected; }
    // destroyed_l() must be called with the associated EffectModule mLock held
    bool destroyed_l() const { return mDestroyed; }


    void dumpToBuffer(char* buffer, size_t size);
    void dumpToBuffer(char* buffer, size_t size);


@@ -222,7 +230,8 @@ protected:
    EffectHandle(const EffectHandle&);
    EffectHandle(const EffectHandle&);
    EffectHandle& operator =(const EffectHandle&);
    EffectHandle& operator =(const EffectHandle&);


    sp<EffectModule> mEffect;           // pointer to controlled EffectModule
    Mutex mLock;                        // protects IEffect method calls
    wp<EffectModule> mEffect;           // pointer to controlled EffectModule
    sp<IEffectClient> mEffectClient;    // callback interface for client notifications
    sp<IEffectClient> mEffectClient;    // callback interface for client notifications
    /*const*/ sp<Client> mClient;       // client for shared memory allocation, see disconnect()
    /*const*/ sp<Client> mClient;       // client for shared memory allocation, see disconnect()
    sp<IMemory>         mCblkMemory;    // shared memory for control block
    sp<IMemory>         mCblkMemory;    // shared memory for control block
@@ -233,8 +242,7 @@ protected:
    bool mHasControl;                   // true if this handle is controlling the effect
    bool mHasControl;                   // true if this handle is controlling the effect
    bool mEnabled;                      // cached enable state: needed when the effect is
    bool mEnabled;                      // cached enable state: needed when the effect is
                                        // restored after being suspended
                                        // restored after being suspended
    bool mDestroyed;                    // Set to true by destructor. Access with EffectModule
    bool mDisconnected;                 // Set to true by disconnect()
                                        // mLock held
};
};


// the EffectChain class represents a group of effects associated to one audio session.
// the EffectChain class represents a group of effects associated to one audio session.
@@ -269,8 +277,15 @@ public:
        mLock.unlock();
        mLock.unlock();
    }
    }


    status_t createEffect_l(sp<EffectModule>& effect,
                            ThreadBase *thread,
                            effect_descriptor_t *desc,
                            int id,
                            audio_session_t sessionId,
                            bool pinned);
    status_t addEffect_l(const sp<EffectModule>& handle);
    status_t addEffect_l(const sp<EffectModule>& handle);
    size_t removeEffect_l(const sp<EffectModule>& handle);
    status_t addEffect_ll(const sp<EffectModule>& handle);
    size_t removeEffect_l(const sp<EffectModule>& handle, bool release = false);


    audio_session_t sessionId() const { return mSessionId; }
    audio_session_t sessionId() const { return mSessionId; }
    void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; }
    void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; }
+33 −12

File changed.

Preview size limit exceeded, changes collapsed.

Loading