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

Commit 47f8c730 authored by Steve Kondik's avatar Steve Kondik Committed by Steve Kondik
Browse files

audiopolicy: Defer release of output session effects

 * Some effects modules are racy and don't tolerate being destroyed
   and immediately resurrected on the same session. This is
   the common case when switching tracks, and the use of default
   output effects makes the problem even worse. Certain apps
   which handle gapless in a sloppy way are also to blame.
 * Instead of immediately nuking the entire descriptor with the
   stream, just decrease the refcount and defer it for 10 seconds.
   If it needs resurrected, the refcount will be increased and
   the delayed release command will not shoot it in the face.

Change-Id: I068dd72c4180023a74eb9ccbe8a180f6f0683dbf
parent 0479d7c7
Loading
Loading
Loading
Loading
+34 −1
Original line number Diff line number Diff line
@@ -295,16 +295,49 @@ status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t outpu
    }

    EffectVector *procDesc = mOutputSessions.valueAt(index);

    // just in case it already has a death wish
    if (procDesc->mRefCount == 0) {
        return NO_ERROR;
    }

    procDesc->mRefCount--;
    ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
          audioSession, procDesc->mRefCount);

    if (procDesc->mRefCount == 0) {
        mAudioPolicyService->releaseOutputSessionEffectsDelayed(
                output, stream, audioSession, 10000);
    }

    return status;
}

status_t AudioPolicyEffects::doReleaseOutputSessionEffects(audio_io_handle_t output,
                         audio_stream_type_t stream,
                         int audioSession)
{
    status_t status = NO_ERROR;
    (void) output; // argument not used for now

    Mutex::Autolock _l(mLock);
    ssize_t index = mOutputSessions.indexOfKey(audioSession);
    if (index < 0) {
        ALOGV("doReleaseOutputSessionEffects: no output processing was attached to this stream");
        return NO_ERROR;
    }

    EffectVector *procDesc = mOutputSessions.valueAt(index);
    ALOGV("doReleaseOutputSessionEffects(): session: %d, refCount: %d",
          audioSession, procDesc->mRefCount);

    if (procDesc->mRefCount == 0) {
        procDesc->setProcessorEnabled(false);
        procDesc->mEffects.clear();
        delete procDesc;
        mOutputSessions.removeItemsAt(index);
        mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, false);
        ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
        ALOGV("doReleaseOutputSessionEffects(): output processing released from session: %d",
              audioSession);
    }
    return status;
+6 −0
Original line number Diff line number Diff line
@@ -86,6 +86,12 @@ public:
                             audio_stream_type_t stream,
                             int audioSession);

    // For deferred release
    status_t doReleaseOutputSessionEffects(audio_io_handle_t output,
                                           audio_stream_type_t stream,
                                           int audioSession);


private:

    // class to store the description of an effects and its parameters
+39 −0
Original line number Diff line number Diff line
@@ -357,6 +357,13 @@ void AudioPolicyService::binderDied(const wp<IBinder>& who) {
            IPCThreadState::self()->getCallingPid());
}

void AudioPolicyService::releaseOutputSessionEffectsDelayed(
        audio_io_handle_t output, audio_stream_type_t stream,
        audio_unique_id_t sessionId, int delayMs)
{
    mAudioCommandThread->releaseOutputSessionEffectsCommand(output, stream, sessionId, delayMs);
}

static bool tryLock(Mutex& mutex)
{
    bool locked = false;
@@ -641,6 +648,21 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
                    svc->doOnOutputSessionEffectsUpdate(data->mStream, data->mSessionId, data->mAdded);
                    mLock.lock();
                    } break;
                case RELEASE_OUTPUT_SESSION_EFFECTS: {
                    ReleaseOutputSessionEffectsData *data =
                            (ReleaseOutputSessionEffectsData *)command->mParam.get();
                    ALOGV("AudioCommandThread() processing release output session effects %d %d %d",
                            data->mOutput, data->mStream, data->mSessionId);
                    svc = mService.promote();
                    if (svc == 0) {
                        break;
                    }
                    mLock.unlock();
                    svc->mAudioPolicyEffects->doReleaseOutputSessionEffects(
                            data->mOutput, data->mStream, data->mSessionId);
                    mLock.lock();
                    } break;


                default:
                    ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@@ -929,6 +951,23 @@ void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand(
    sendCommand(command);
}

void AudioPolicyService::AudioCommandThread::releaseOutputSessionEffectsCommand(
        audio_io_handle_t output, audio_stream_type_t stream,
        audio_unique_id_t sessionId, int delayMs)
{
    sp<AudioCommand> command = new AudioCommand();
    command->mCommand = RELEASE_OUTPUT_SESSION_EFFECTS;
    ReleaseOutputSessionEffectsData *data = new ReleaseOutputSessionEffectsData();
    data->mOutput = output;
    data->mStream = stream;
    data->mSessionId = sessionId;
    command->mParam = data;
    ALOGV("AudioCommandThread() sending release output session effects (id=%d) for stream %d",
            sessionId, stream);
    sendCommand(command, delayMs);
}


status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
    {
+17 −1
Original line number Diff line number Diff line
@@ -235,6 +235,10 @@ public:
                                              audio_unique_id_t sessionId, bool added);
            void doOnOutputSessionEffectsUpdate(audio_stream_type_t stream,
                                                audio_unique_id_t sessionId, bool added);
            void releaseOutputSessionEffectsDelayed(audio_io_handle_t output,
                                                    audio_stream_type_t stream,
                                                    audio_unique_id_t sessionId,
                                                    int delayMs);

private:
                        AudioPolicyService() ANDROID_API;
@@ -268,7 +272,8 @@ private:
            UPDATE_AUDIOPATCH_LIST,
            SET_AUDIOPORT_CONFIG,
            DYN_POLICY_MIX_STATE_UPDATE,
            EFFECT_SESSION_UPDATE
            EFFECT_SESSION_UPDATE,
            RELEASE_OUTPUT_SESSION_EFFECTS,
        };

        AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -313,6 +318,10 @@ private:
                    void        insertCommand_l(AudioCommand *command, int delayMs = 0);
                    void        effectSessionUpdateCommand(audio_stream_type_t stream,
                                                           audio_unique_id_t sessionId, bool added);
                    void        releaseOutputSessionEffectsCommand(audio_io_handle_t output,
                                                                   audio_stream_type_t stream,
                                                                   audio_unique_id_t sessionId,
                                                                   int delayMs = 0);

    private:
        class AudioCommandData;
@@ -416,6 +425,13 @@ private:
            bool mAdded;
        };

        class ReleaseOutputSessionEffectsData : public AudioCommandData {
        public:
            audio_io_handle_t mOutput;
            audio_stream_type_t mStream;
            audio_unique_id_t mSessionId;
        };

        Mutex   mLock;
        Condition mWaitWorkCV;
        Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands