Fallback to default volume handling when session is released

Volume key events can be ignored when the foreground activity has
specified the MediaSession for handling media/volume key events
(via Activity#setMediaController()) but the session is released
(i.e. destroyed). Such enforcement was introduced not to use the
released session's information when picking the volume stream for
control.

This CL relaxes the behavior by falling back to the default volume
handling logic when the session is released.

Bug: 135966139
Test: Tested with the problematic app in the bug, and also with my own
      test app.
Change-Id: I976b0e8d18976f6cfdc3303cabdda55d2a101b4f
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index adc1561..5bd4b20 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -54,6 +54,7 @@
 import android.media.session.ISession2TokensListener;
 import android.media.session.ISessionCallback;
 import android.media.session.ISessionManager;
+import android.media.session.MediaController;
 import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
 import android.net.Uri;
@@ -1183,6 +1184,9 @@
         }
 
         /**
+         * Dispaches media key events. This is called when the foreground activity didn't handled
+         * the incoming media key event.
+         * <p>
          * Handles the dispatching of the media button events to one of the
          * registered listeners, or if there was none, broadcast an
          * ACTION_MEDIA_BUTTON intent to the rest of the system.
@@ -1262,6 +1266,18 @@
             }
         }
 
+        /**
+         * Dispatches media key events to session as system service. This is used only when the
+         * foreground activity has set
+         * {@link android.app.Activity#setMediaController(MediaController)} and a media key was
+         * pressed.
+         *
+         * @param packageName The caller's package name, obtained by Context#getPackageName()
+         * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
+         * @param sessionToken token for the session that the controller is pointing to
+         * @param keyEvent media key event
+         * @see #dispatchVolumeKeyEvent
+         */
         @Override
         public boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
                 MediaSession.Token sessionToken, KeyEvent keyEvent) {
@@ -1272,9 +1288,7 @@
                 synchronized (mLock) {
                     MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
                     if (record == null) {
-                        if (DEBUG) {
-                            Log.d(TAG, "Failed to find session to dispatch key event.");
-                        }
+                        Log.w(TAG, "Failed to find session to dispatch key event.");
                         return false;
                     }
                     if (DEBUG) {
@@ -1452,9 +1466,12 @@
         }
 
         /**
+         * Dispaches volume key events. This is called when the foreground activity didn't handled
+         * the incoming volume key event.
+         * <p>
          * Handles the dispatching of the volume button events to one of the
          * registered listeners. If there's a volume key long-press listener and
-         * there's no active global priority session, long-pressess will be sent to the
+         * there's no active global priority session, long-presses will be sent to the
          * long-press listener instead of adjusting volume.
          *
          * @param packageName The caller's package name, obtained by Context#getPackageName()
@@ -1471,6 +1488,7 @@
          *            or {@link KeyEvent#KEYCODE_VOLUME_MUTE}.
          * @param stream stream type to adjust volume.
          * @param musicOnly true if both UI nor haptic feedback aren't needed when adjust volume.
+         * @see #dispatchVolumeKeyEventToSessionAsSystemService
          */
         @Override
         public void dispatchVolumeKeyEvent(String packageName, String opPackageName,
@@ -1597,6 +1615,18 @@
             }
         }
 
+        /**
+         * Dispatches volume key events to session as system service. This is used only when the
+         * foreground activity has set
+         * {@link android.app.Activity#setMediaController(MediaController)} and a hardware volume
+         * key was pressed.
+         *
+         * @param packageName The caller's package name, obtained by Context#getPackageName()
+         * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
+         * @param sessionToken token for the session that the controller is pointing to
+         * @param keyEvent volume key event
+         * @see #dispatchVolumeKeyEvent
+         */
         @Override
         public void dispatchVolumeKeyEventToSessionAsSystemService(String packageName,
                 String opPackageName, MediaSession.Token sessionToken, KeyEvent keyEvent) {
@@ -1607,9 +1637,10 @@
                 synchronized (mLock) {
                     MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
                     if (record == null) {
-                        if (DEBUG) {
-                            Log.d(TAG, "Failed to find session to dispatch key event.");
-                        }
+                        Log.w(TAG, "Failed to find session to dispatch key event, token="
+                                + sessionToken + ". Fallbacks to the default handling.");
+                        dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid, true,
+                                keyEvent, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
                         return;
                     }
                     if (DEBUG) {