diff options
author | Jean-Michel Trivi <jmtrivi@google.com> | 2013-01-02 10:56:35 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-01-02 10:56:35 -0800 |
commit | f2fc1cbb067eb12eccb23c5469814675539e28a6 (patch) | |
tree | a6a798a075f04386ab5c6e47f8a047cd746e666c /media | |
parent | 4c7f809dd5c934b86b0450e59941998aeb7fb96e (diff) | |
parent | bc83425c116694b60fde0d9ae6314339c7b8fe2f (diff) | |
download | frameworks_base-f2fc1cbb067eb12eccb23c5469814675539e28a6.zip frameworks_base-f2fc1cbb067eb12eccb23c5469814675539e28a6.tar.gz frameworks_base-f2fc1cbb067eb12eccb23c5469814675539e28a6.tar.bz2 |
Merge "Fix stack traversal order when removing or adding media button receiver"
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/AudioService.java | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index addb4cb..25eabee 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -4963,28 +4963,34 @@ public class AudioService extends IAudioService.Stub implements OnFinished { /** * Helper function: * Set the new remote control receiver at the top of the RC focus stack. + * Called synchronized on mAudioFocusLock, then mRCStack * precondition: mediaIntent != null, target != null */ - private void pushMediaButtonReceiver(PendingIntent mediaIntent, ComponentName target) { + private void pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent, ComponentName target) { // already at top of stack? if (!mRCStack.empty() && mRCStack.peek().mMediaIntent.equals(mediaIntent)) { return; } - Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); RemoteControlStackEntry rcse = null; boolean wasInsideStack = false; - while(stackIterator.hasNext()) { - rcse = (RemoteControlStackEntry)stackIterator.next(); - if(rcse.mMediaIntent.equals(mediaIntent)) { - wasInsideStack = true; - stackIterator.remove(); - break; + try { + for (int index = mRCStack.size()-1; index >= 0; index--) { + rcse = mRCStack.elementAt(index); + if(rcse.mMediaIntent.equals(mediaIntent)) { + // ok to remove element while traversing the stack since we're leaving the loop + mRCStack.removeElementAt(index); + wasInsideStack = true; + break; + } } + } catch (ArrayIndexOutOfBoundsException e) { + // not expected to happen, indicates improper concurrent modification + Log.e(TAG, "Wrong index accessing media button stack, lock error? ", e); } if (!wasInsideStack) { rcse = new RemoteControlStackEntry(mediaIntent, target); } - mRCStack.push(rcse); + mRCStack.push(rcse); // rcse is never null // post message to persist the default media button receiver mAudioHandler.sendMessage( mAudioHandler.obtainMessage( @@ -4994,17 +5000,23 @@ public class AudioService extends IAudioService.Stub implements OnFinished { /** * Helper function: * Remove the remote control receiver from the RC focus stack. + * Called synchronized on mAudioFocusLock, then mRCStack * precondition: pi != null */ - private void removeMediaButtonReceiver(PendingIntent pi) { - Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); - while(stackIterator.hasNext()) { - RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next(); - if(rcse.mMediaIntent.equals(pi)) { - stackIterator.remove(); - rcse.unlinkToRcClientDeath(); - break; + private void removeMediaButtonReceiver_syncAfRcs(PendingIntent pi) { + try { + for (int index = mRCStack.size()-1; index >= 0; index--) { + final RemoteControlStackEntry rcse = mRCStack.elementAt(index); + if (rcse.mMediaIntent.equals(pi)) { + rcse.unlinkToRcClientDeath(); + // ok to remove element while traversing the stack since we're leaving the loop + mRCStack.removeElementAt(index); + break; + } } + } catch (ArrayIndexOutOfBoundsException e) { + // not expected to happen, indicates improper concurrent modification + Log.e(TAG, "Wrong index accessing media button stack, lock error? ", e); } } @@ -5242,7 +5254,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { synchronized(mAudioFocusLock) { synchronized(mRCStack) { - pushMediaButtonReceiver(mediaIntent, eventReceiver); + pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver); // new RC client, assume every type of information shall be queried checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL); } @@ -5260,7 +5272,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { synchronized(mAudioFocusLock) { synchronized(mRCStack) { boolean topOfStackWillChange = isCurrentRcController(mediaIntent); - removeMediaButtonReceiver(mediaIntent); + removeMediaButtonReceiver_syncAfRcs(mediaIntent); if (topOfStackWillChange) { // current RC client will change, assume every type of info needs to be queried checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL); |