From 26b3d1ff38998c7cb80a2950da0589ebd8510897 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Wed, 28 Sep 2011 11:05:15 -0700 Subject: [PATCH] Fix bug 5357295 NPE on display when remote control client dies When a IRemoteControlClient dies, that client is set to null in the stack of remote control entries (mRCStack). This is done by calling registerRemoteControlClient() with a null client. The bug is that registerRemoteControlClient(), after storing the new client, uses it to let it know what the current remote control display is. When that display is non null, the client is sent the current display. So when a client died when there was a display, the client reference was accessed in the part of the method where we haven't yet checked whether it is null or not. The fix consists in moving the setting of the display on the client (method plugRemoteControlDisplay) only after having checked that the client is non-null. Change-Id: Ic74d6cba9e3a3a16e78cd80a1ae5901abfeb3905 --- media/java/android/media/AudioService.java | 28 ++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 8895c9e7348c9..4f4f9297e614a 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -2958,7 +2958,7 @@ public class AudioService extends IAudioService.Stub { Log.w(TAG, " RemoteControlClient died"); // remote control client died, make sure the displays don't use it anymore // by setting its remote control client to null - registerRemoteControlClient(mMediaIntent, null, null/*ignored*/); + registerRemoteControlClient(mMediaIntent, null/*rcClient*/, null/*ignored*/); } public IBinder getBinder() { @@ -3366,7 +3366,12 @@ public class AudioService extends IAudioService.Stub { } } - /** see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...) */ + /** + * see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...) + * Note: using this method with rcClient == null is a way to "disable" the IRemoteControlClient + * without modifying the RC stack, but while still causing the display to refresh (will + * become blank as a result of this) + */ public void registerRemoteControlClient(PendingIntent mediaIntent, IRemoteControlClient rcClient, String callingPackageName) { if (DEBUG_RC) Log.i(TAG, "Register remote control client rcClient="+rcClient); @@ -3384,6 +3389,15 @@ public class AudioService extends IAudioService.Stub { } // save the new remote control client rcse.mRcClient = rcClient; + rcse.mCallingPackageName = callingPackageName; + rcse.mCallingUid = Binder.getCallingUid(); + if (rcClient == null) { + rcse.mRcClientDeathHandler = null; + break; + } + + // there is a new (non-null) client: + // 1/ give the new client the current display (if any) if (mRcDisplay != null) { try { rcse.mRcClient.plugRemoteControlDisplay(mRcDisplay); @@ -3392,14 +3406,8 @@ public class AudioService extends IAudioService.Stub { e.printStackTrace(); } } - rcse.mCallingPackageName = callingPackageName; - rcse.mCallingUid = Binder.getCallingUid(); - if (rcClient == null) { - rcse.mRcClientDeathHandler = null; - break; - } - // monitor the new client's death - IBinder b = rcClient.asBinder(); + // 2/ monitor the new client's death + IBinder b = rcse.mRcClient.asBinder(); RcClientDeathHandler rcdh = new RcClientDeathHandler(b, rcse.mMediaIntent); try {