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

Commit 599e1491 authored by Eric Laurent's avatar Eric Laurent Committed by android-build-merger
Browse files

Merge "refactor mutexes for audio effects in audio flinger and audio policy" into qt-dev

am: aceea8bd

Change-Id: I51038a1d201f63d3518b33f10dc7b0d3adb1ff34
parents f03c527d aceea8bd
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1067,6 +1067,13 @@ status_t AudioSystem::setEffectEnabled(int id, bool enabled)
    return aps->setEffectEnabled(id, enabled);
}

status_t AudioSystem::moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return PERMISSION_DENIED;
    return aps->moveEffectsToIo(ids, io);
}

status_t AudioSystem::isStreamActive(audio_stream_type_t stream, bool* state, uint32_t inPastMs)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+43 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ enum {
    LIST_AUDIO_VOLUME_GROUPS,
    GET_VOLUME_GROUP_FOR_ATTRIBUTES,
    SET_ALLOWED_CAPTURE_POLICY,
    MOVE_EFFECTS_TO_IO,
};

#define MAX_ITEMS_PER_LIST 1024
@@ -550,6 +551,22 @@ public:
        return static_cast <status_t> (reply.readInt32());
    }

    status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) override
    {
        Parcel data, reply;
        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
        data.writeInt32(ids.size());
        for (auto id : ids) {
            data.writeInt32(id);
        }
        data.writeInt32(io);
        status_t status = remote()->transact(MOVE_EFFECTS_TO_IO, data, &reply);
        if (status != NO_ERROR) {
            return status;
        }
        return static_cast <status_t> (reply.readInt32());
    }

    virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
    {
        Parcel data, reply;
@@ -1284,6 +1301,7 @@ status_t BnAudioPolicyService::onTransact(
        case GET_OUTPUT_FOR_ATTR:
        case ACQUIRE_SOUNDTRIGGER_SESSION:
        case RELEASE_SOUNDTRIGGER_SESSION:
        case MOVE_EFFECTS_TO_IO:
            ALOGW("%s: transaction %d received from PID %d",
                  __func__, code, IPCThreadState::self()->getCallingPid());
            // return status only for non void methods
@@ -1700,6 +1718,31 @@ status_t BnAudioPolicyService::onTransact(
            return NO_ERROR;
        } break;

        case MOVE_EFFECTS_TO_IO: {
            CHECK_INTERFACE(IAudioPolicyService, data, reply);
            std::vector<int> ids;
            int32_t size;
            status_t status = data.readInt32(&size);
            if (status != NO_ERROR) {
                return status;
            }
            if (size > MAX_ITEMS_PER_LIST) {
                return BAD_VALUE;
            }
            for (int32_t i = 0; i < size; i++) {
                int id;
                status =  data.readInt32(&id);
                if (status != NO_ERROR) {
                    return status;
                }
                ids.push_back(id);
            }

            audio_io_handle_t io = data.readInt32();
            reply->writeInt32(static_cast <int32_t>(moveEffectsToIo(ids, io)));
            return NO_ERROR;
        } break;

        case IS_STREAM_ACTIVE: {
            CHECK_INTERFACE(IAudioPolicyService, data, reply);
            audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();
+1 −0
Original line number Diff line number Diff line
@@ -286,6 +286,7 @@ public:
                                    int id);
    static status_t unregisterEffect(int id);
    static status_t setEffectEnabled(int id, bool enabled);
    static status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io);

    // clear stream to output mapping cache (gStreamOutputMap)
    // and output configuration cache (gOutputs)
+1 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ public:
                                    int id) = 0;
    virtual status_t unregisterEffect(int id) = 0;
    virtual status_t setEffectEnabled(int id, bool enabled) = 0;
    virtual status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) = 0;
    virtual bool     isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const = 0;
    virtual bool     isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0)
                             const = 0;
+149 −71
Original line number Diff line number Diff line
@@ -687,6 +687,10 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
    bool updatePid = (input.clientInfo.clientPid == -1);
    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
    uid_t clientUid = input.clientInfo.clientUid;
    audio_io_handle_t effectThreadId = AUDIO_IO_HANDLE_NONE;
    std::vector<int> effectIds;


    if (!isAudioServerOrMediaServerUid(callingUid)) {
        ALOGW_IF(clientUid != callingUid,
                "%s uid %d tried to pass itself off as %d",
@@ -851,7 +855,10 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
            // no risk of deadlock because AudioFlinger::mLock is held
            Mutex::Autolock _dl(thread->mLock);
            Mutex::Autolock _sl(effectThread->mLock);
            moveEffectChain_l(sessionId, effectThread, thread, true);
            if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
                effectThreadId = thread->id();
                effectIds = thread->getEffectIds_l(sessionId);
            }
        }

        // Look for sync events awaiting for a session to be used.
@@ -885,6 +892,12 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
        goto Exit;
    }

    // effectThreadId is not NONE if an effect chain corresponding to the track session
    // was found on another thread and must be moved on this thread
    if (effectThreadId != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::moveEffectsToIo(effectIds, effectThreadId);
    }

    // return handle to client
    trackHandle = new TrackHandle(track);

@@ -1225,7 +1238,8 @@ status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
    if (output == AUDIO_IO_HANDLE_NONE) {
        return BAD_VALUE;
    }
    ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to change AUDIO_STREAM_PATCH volume");
    ALOG_ASSERT(stream != AUDIO_STREAM_PATCH || value == 1.0,
        "attempt to change AUDIO_STREAM_PATCH volume");

    AutoMutex lock(mLock);
    VolumeInterface *volumeInterface = getVolumeInterface_l(output);
@@ -1629,6 +1643,8 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
}

void AudioFlinger::removeNotificationClient(pid_t pid)
{
    std::vector< sp<AudioFlinger::EffectModule> > removedEffects;
    {
        Mutex::Autolock _l(mLock);
        {
@@ -1653,7 +1669,11 @@ void AudioFlinger::removeNotificationClient(pid_t pid)
            }
        }
        if (removed) {
        purgeStaleEffects_l();
            removedEffects = purgeStaleEffects_l();
        }
    }
    for (auto& effect : removedEffects) {
        effect->updatePolicyState();
    }
}

@@ -2425,7 +2445,7 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
                    Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
                    for (size_t i = 0; i < effectChains.size(); i ++) {
                        moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
                                dstThread, true);
                                dstThread);
                    }
                }
            }
@@ -2791,6 +2811,8 @@ void AudioFlinger::acquireAudioSessionId(audio_session_t audioSession, pid_t pid
}

void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
{
    std::vector< sp<EffectModule> > removedEffects;
    {
        Mutex::Autolock _l(mLock);
        pid_t caller = IPCThreadState::self()->getCallingPid();
@@ -2808,9 +2830,10 @@ void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid
                if (ref->mCnt == 0) {
                    mAudioSessionRefs.removeAt(i);
                    delete ref;
                purgeStaleEffects_l();
                    std::vector< sp<EffectModule> > effects = purgeStaleEffects_l();
                    removedEffects.insert(removedEffects.end(), effects.begin(), effects.end());
                }
            return;
                goto Exit;
            }
        }
        // If the caller is audioserver it is likely that the session being released was acquired
@@ -2819,6 +2842,12 @@ void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid
                 "session id %d not found for pid %d", audioSession, caller);
    }

Exit:
    for (auto& effect : removedEffects) {
        effect->updatePolicyState();
    }
}

bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession)
{
    size_t num = mAudioSessionRefs.size();
@@ -2831,11 +2860,12 @@ bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession)
    return false;
}

void AudioFlinger::purgeStaleEffects_l() {
std::vector<sp<AudioFlinger::EffectModule>> AudioFlinger::purgeStaleEffects_l() {

    ALOGV("purging stale effects");

    Vector< sp<EffectChain> > chains;
    std::vector< sp<EffectModule> > removedEffects;

    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
        sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
@@ -2847,6 +2877,7 @@ void AudioFlinger::purgeStaleEffects_l() {
            }
        }
    }

    for (size_t i = 0; i < mRecordThreads.size(); i++) {
        sp<RecordThread> t = mRecordThreads.valueAt(i);
        Mutex::Autolock _l(t->mLock);
@@ -2856,6 +2887,15 @@ void AudioFlinger::purgeStaleEffects_l() {
        }
    }

    for (size_t i = 0; i < mMmapThreads.size(); i++) {
        sp<MmapThread> t = mMmapThreads.valueAt(i);
        Mutex::Autolock _l(t->mLock);
        for (size_t j = 0; j < t->mEffectChains.size(); j++) {
            sp<EffectChain> ec = t->mEffectChains[j];
            chains.push(ec);
        }
    }

    for (size_t i = 0; i < chains.size(); i++) {
        sp<EffectChain> ec = chains[i];
        int sessionid = ec->sessionId();
@@ -2884,11 +2924,11 @@ void AudioFlinger::purgeStaleEffects_l() {
                if (effect->purgeHandles()) {
                    t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
                }
                AudioSystem::unregisterEffect(effect->id());
                removedEffects.push_back(effect);
            }
        }
    }
    return;
    return removedEffects;
}

// dumpToThreadLog_l() must be called with AudioFlinger::mLock held
@@ -3380,8 +3420,16 @@ sp<IEffect> AudioFlinger::createEffect(
        }
    }

    if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
        // handle must be cleared outside lock.
    if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
        // Check CPU and memory usage
        sp<EffectModule> effect = handle->effect().promote();
        if (effect != nullptr) {
            status_t rStatus = effect->updatePolicyState();
            if (rStatus != NO_ERROR) {
                lStatus = rStatus;
            }
        }
    } else {
        handle.clear();
    }

@@ -3413,14 +3461,13 @@ status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t

    Mutex::Autolock _dl(dstThread->mLock);
    Mutex::Autolock _sl(srcThread->mLock);
    return moveEffectChain_l(sessionId, srcThread, dstThread, false);
    return moveEffectChain_l(sessionId, srcThread, dstThread);
}

// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
                                   AudioFlinger::PlaybackThread *srcThread,
                                   AudioFlinger::PlaybackThread *dstThread,
                                   bool reRegister)
                                   AudioFlinger::PlaybackThread *dstThread)
{
    ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
            sessionId, srcThread, dstThread);
@@ -3476,33 +3523,64 @@ status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
            }
            strategy = dstChain->strategy();
        }
        if (reRegister) {
            AudioSystem::unregisterEffect(effect->id());
            AudioSystem::registerEffect(&effect->desc(),
                                        dstThread->id(),
                                        strategy,
                                        sessionId,
                                        effect->id());
            AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
        }
        effect = chain->getEffectFromId_l(0);
    }

    if (status != NO_ERROR) {
        for (size_t i = 0; i < removed.size(); i++) {
            srcThread->addEffect_l(removed[i]);
            if (dstChain != 0 && reRegister) {
                AudioSystem::unregisterEffect(removed[i]->id());
                AudioSystem::registerEffect(&removed[i]->desc(),
                                            srcThread->id(),
                                            strategy,
                                            sessionId,
                                            removed[i]->id());
                AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
        }
    }

    return status;
}

status_t AudioFlinger::moveAuxEffectToIo(int EffectId,
                                         const sp<PlaybackThread>& dstThread,
                                         sp<PlaybackThread> *srcThread)
{
    status_t status = NO_ERROR;
    Mutex::Autolock _l(mLock);
    sp<PlaybackThread> thread = getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);

    if (EffectId != 0 && thread != 0 && dstThread != thread.get()) {
        Mutex::Autolock _dl(dstThread->mLock);
        Mutex::Autolock _sl(thread->mLock);
        sp<EffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
        sp<EffectChain> dstChain;
        if (srcChain == 0) {
            return INVALID_OPERATION;
        }

        sp<EffectModule> effect = srcChain->getEffectFromId_l(EffectId);
        if (effect == 0) {
            return INVALID_OPERATION;
        }
        thread->removeEffect_l(effect);
        status = dstThread->addEffect_l(effect);
        if (status != NO_ERROR) {
            thread->addEffect_l(effect);
            status = INVALID_OPERATION;
            goto Exit;
        }

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

Exit:
        // removeEffect_l() has stopped the effect if it was active so it must be restarted
        if (effect->state() == EffectModule::ACTIVE ||
            effect->state() == EffectModule::STOPPING) {
            effect->start();
        }
    }

    if (status == NO_ERROR && srcThread != nullptr) {
        *srcThread = thread;
    }
    return status;
}

Loading