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

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

Fix 5623252 unlink to death of audio focus client early

When removing an entry in the audio focus stack, don't wait for
 this object's finalizer to unlink to the death of the associated
 client, and unlink right away.
The FocusStackEntry.unlinkToDeath() method is made safe to call
 by catching the exception it can throw inside its body.

Change-Id: Id347a933d72dcb41531adff2854fb00277032cc9
parent 34a62348
Loading
Loading
Loading
Loading
+18 −14
Original line number Diff line number Diff line
@@ -2693,23 +2693,23 @@ public class AudioService extends IAudioService.Stub {
            mCallingUid = uid;
        }

        private void unlinkToDeath() {
        public void unlinkToDeath() {
            try {
                if (mSourceRef != null && mHandler != null) {
                    mSourceRef.unlinkToDeath(mHandler, 0);
                    mHandler = null;
                }
            } catch (java.util.NoSuchElementException e) {
                Log.e(TAG, "Encountered " + e + " in FocusStackEntry.unlinkToDeath()");
            }
        }

        @Override
        protected void finalize() throws Throwable {
            try {
                unlinkToDeath();
            } catch (java.util.NoSuchElementException e) {
                Log.w(TAG, e + " thrown by unlinkToDeath() during finalize, ignoring");
            } finally {
            unlinkToDeath(); // unlink exception handled inside method
            super.finalize();
        }
    }
    }

    private Stack<FocusStackEntry> mFocusStack = new Stack<FocusStackEntry>();

@@ -2739,11 +2739,12 @@ public class AudioService extends IAudioService.Stub {
     *   focus, notify the next item in the stack it gained focus.
     */
    private void removeFocusStackEntry(String clientToRemove, boolean signal) {
        // is the current top of the focus stack abandoning focus? (because of death or request)
        // is the current top of the focus stack abandoning focus? (because of request, not death)
        if (!mFocusStack.empty() && mFocusStack.peek().mClientId.equals(clientToRemove))
        {
            //Log.i(TAG, "   removeFocusStackEntry() removing top of stack");
            mFocusStack.pop();
            FocusStackEntry fse = mFocusStack.pop();
            fse.unlinkToDeath();
            if (signal) {
                // notify the new top of the stack it gained focus
                notifyTopOfAudioFocusStack();
@@ -2762,6 +2763,7 @@ public class AudioService extends IAudioService.Stub {
                    Log.i(TAG, " AudioFocus  abandonAudioFocus(): removing entry for "
                            + fse.mClientId);
                    stackIterator.remove();
                    fse.unlinkToDeath();
                }
            }
        }
@@ -2770,7 +2772,7 @@ public class AudioService extends IAudioService.Stub {
    /**
     * Helper function:
     * Called synchronized on mAudioFocusLock
     * Remove focus listeners from the focus stack for a particular client.
     * Remove focus listeners from the focus stack for a particular client when it has died.
     */
    private void removeFocusStackEntryForClient(IBinder cb) {
        // is the owner of the audio focus part of the client to remove?
@@ -2783,6 +2785,7 @@ public class AudioService extends IAudioService.Stub {
                Log.i(TAG, " AudioFocus  abandonAudioFocus(): removing entry for "
                        + fse.mClientId);
                stackIterator.remove();
                // the client just died, no need to unlink to its death
            }
        }
        if (isTopOfStackForClientToRemove) {
@@ -2874,7 +2877,8 @@ public class AudioService extends IAudioService.Stub {
                }
                // the reason for the audio focus request has changed: remove the current top of
                // stack and respond as if we had a new focus owner
                mFocusStack.pop();
                FocusStackEntry fse = mFocusStack.pop();
                fse.unlinkToDeath();
            }

            // notify current top of stack it is losing focus