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

Commit aceea8bd authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

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

parents 06001610 6c79632b
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