Limit RemoteControlClient generation ID changes

At the beginning of each song, the Music app re-registers its
 media button event and requests audio focus, which causes
 the reevaluation of each corresponding stack of clients. Each
 reevaluation is accompanied by the incrementation of the
 RemoteControlClient generation ID, which causes RemoteController
 to issue a notification that the client has changed. The lockscreen
 correctly interprets this as a reason to dump the current
 RemoteControlClient data (including the artwork) because it will
 receive the new data if new one is available. This is what causes
 the "flashing" of the wallpaper on the lockscreen: for an instant,
 no client data is available.
The fix consists in not causing the client generation ID to be
 incremented when registrations don't cause any change in the
 RemoteControlClient stack. Even though Music re-registers everything,
 nothing has changed: it still is the current media button receiver,
 and it still has the same RemoteControlClient.

Bug 11307382

Change-Id: I4d2404b571e88aeedb0eca6bd19d39f7ec4fc8b1
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index 07d91ac..59d411d 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -1476,16 +1476,17 @@
      * Set the new remote control receiver at the top of the RC focus stack.
      * Called synchronized on mAudioFocusLock, then mRCStack
      * precondition: mediaIntent != null
+     * @return true if mRCStack was changed, false otherwise
      */
-    private void pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent, ComponentName target,
-            IBinder token) {
+    private boolean pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent,
+            ComponentName target, IBinder token) {
         // already at top of stack?
         if (!mRCStack.empty() && mRCStack.peek().mMediaIntent.equals(mediaIntent)) {
-            return;
+            return false;
         }
         if (mAppOps.noteOp(AppOpsManager.OP_TAKE_MEDIA_BUTTONS, Binder.getCallingUid(),
                 mediaIntent.getCreatorPackage()) != AppOpsManager.MODE_ALLOWED) {
-            return;
+            return false;
         }
         RemoteControlStackEntry rcse = null;
         boolean wasInsideStack = false;
@@ -1513,6 +1514,9 @@
             mEventHandler.sendMessage( mEventHandler.obtainMessage(
                     MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
         }
+
+        // RC stack was modified
+        return true;
     }
 
     /**
@@ -1856,9 +1860,10 @@
 
         synchronized(mAudioFocusLock) {
             synchronized(mRCStack) {
-                pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver, token);
-                // new RC client, assume every type of information shall be queried
-                checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
+                if (pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver, token)) {
+                    // new RC client, assume every type of information shall be queried
+                    checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
+                }
             }
         }
     }
@@ -1925,6 +1930,7 @@
         int rccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
         synchronized(mAudioFocusLock) {
             synchronized(mRCStack) {
+                boolean wasCurrentRcController = isCurrentRcController(mediaIntent);
                 // store the new display information
                 try {
                     for (int index = mRCStack.size()-1; index >= 0; index--) {
@@ -1971,9 +1977,9 @@
                     Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
                 }
 
-                // if the eventReceiver is at the top of the stack
+                // if the eventReceiver is now at the top of the stack but wasn't before
                 // then check for potential refresh of the remote controls
-                if (isCurrentRcController(mediaIntent)) {
+                if (isCurrentRcController(mediaIntent) && !wasCurrentRcController) {
                     checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
                 }
             }//synchronized(mRCStack)