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

Commit 3094d955 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

Fix deadlock in AudioService

Locks related to audio focus and remote control should always be
 taken in the following order:
 1/ audio focus lock
 2/ remote control stack
 3/ current remote control client generation

Change-Id: If8be11bfef92849957e692b2bd52adbd67a2ef0b
parent 4b6df6a3
Loading
Loading
Loading
Loading
+41 −39
Original line number Diff line number Diff line
@@ -3072,7 +3072,7 @@ public class AudioService extends IAudioService.Stub {
    /**
     * Update the remote control displays with the new "focused" client generation
     */
    private void setNewRcClientOnDisplays_syncRcStack(int newClientGeneration,
    private void setNewRcClientOnDisplays_syncAfRcsCurrc(int newClientGeneration,
            ComponentName newClientEventReceiver, boolean clearing) {
        // NOTE: Only one IRemoteControlDisplay supported in this implementation
        if (mRcDisplay != null) {
@@ -3091,7 +3091,7 @@ public class AudioService extends IAudioService.Stub {
    /**
     * Update the remote control clients with the new "focused" client generation
     */
    private void setNewRcClientGenerationOnClients_syncRcStack(int newClientGeneration) {
    private void setNewRcClientGenerationOnClients_syncAfRcsCurrc(int newClientGeneration) {
        Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
        while(stackIterator.hasNext()) {
            RemoteControlStackEntry se = stackIterator.next();
@@ -3115,15 +3115,13 @@ public class AudioService extends IAudioService.Stub {
     * @param clearing true if the new client generation value maps to a remote control update
     *    where the display should be cleared.
     */
    private void setNewRcClient(int newClientGeneration, ComponentName newClientEventReceiver,
            boolean clearing) {
        synchronized(mRCStack) {
    private void setNewRcClient_syncAfRcsCurrc(int newClientGeneration,
            ComponentName newClientEventReceiver, boolean clearing) {
        // send the new valid client generation ID to all displays
            setNewRcClientOnDisplays_syncRcStack(newClientGeneration, newClientEventReceiver,
        setNewRcClientOnDisplays_syncAfRcsCurrc(newClientGeneration, newClientEventReceiver,
                clearing);
        // send the new valid client generation ID to all clients
            setNewRcClientGenerationOnClients_syncRcStack(newClientGeneration);
        }
        setNewRcClientGenerationOnClients_syncAfRcsCurrc(newClientGeneration);
    }

    /**
@@ -3133,11 +3131,13 @@ public class AudioService extends IAudioService.Stub {
        // TODO remove log before release
        Log.i(TAG, "Clear remote control display");

        synchronized(mRCStack) {
            synchronized(mCurrentRcLock) {
                mCurrentRcClientGen++;

                // synchronously update the displays and clients with the new client generation
            setNewRcClient(mCurrentRcClientGen, null /*event receiver*/, true /*clearing*/);
                setNewRcClient_syncAfRcsCurrc(mCurrentRcClientGen,
                        null /*event receiver*/, true /*clearing*/);
            }
        }
    }

@@ -3145,15 +3145,16 @@ public class AudioService extends IAudioService.Stub {
     * Called when processing MSG_RCDISPLAY_UPDATE event
     */
    private void onRcDisplayUpdate(RemoteControlStackEntry rcse, int flags /* USED ?*/) {
        synchronized(mRCStack) {
            synchronized(mCurrentRcLock) {
                if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(rcse.mRcClient))) {
                    // TODO remove log before release
                    Log.i(TAG, "Display/update remote control ");

                    mCurrentRcClientGen++;

                // synchronously update the displays and clients with the new client generation
                setNewRcClient(mCurrentRcClientGen,
                    // synchronously update the displays and clients with
                    //      the new client generation
                    setNewRcClient_syncAfRcsCurrc(mCurrentRcClientGen,
                            rcse.mReceiverComponent /*event receiver*/,
                            false /*clearing*/);

@@ -3172,6 +3173,7 @@ public class AudioService extends IAudioService.Stub {
                }
            }
        }
    }


    /**