[Media ML] Add get/setSessionPolicies APIs

This allows vendor/OEMs to dynamically change whether sessions should
be used as buttons sessions or not.

Bug: 147027868
Test: Manually
Change-Id: I9db0d298d5caca0b61b41d94455e8f8f1b1ea685
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 6c1b2a6..5fd8f73 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -75,4 +75,6 @@
     boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
     void setCustomMediaKeyDispatcherForTesting(String name);
     void setCustomSessionPolicyProviderForTesting(String name);
+    int getSessionPolicies(in MediaSession.Token token);
+    void setSessionPolicies(in MediaSession.Token token, int policies);
 }
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 4d01301..2fd721e 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -913,6 +913,34 @@
     }
 
     /**
+     * Get session policies of the specified {@link MediaSession.Token}.
+     *
+     * @hide
+     */
+    @Nullable
+    public int getSessionPolicies(@NonNull MediaSession.Token token) {
+        try {
+            return mService.getSessionPolicies(token);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get session policies", e);
+        }
+        return 0;
+    }
+
+    /**
+     * Set new session policies to the specified {@link MediaSession.Token}.
+     *
+     * @hide
+     */
+    public void setSessionPolicies(@NonNull MediaSession.Token token, @Nullable int policies) {
+        try {
+            mService.setSessionPolicies(token, policies);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to set session policies", e);
+        }
+    }
+
+    /**
      * Listens for changes to the list of active sessions. This can be added
      * using {@link #addOnActiveSessionsChangedListener}.
      */
diff --git a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
index b0bccb8..55e0795 100644
--- a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
+++ b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
@@ -166,7 +166,7 @@
      * Cleans up the sorted list of audio playback client UIDs with given {@param
      * mediaButtonSessionUid}.
      * <p>UIDs whose audio playback are inactive and have started before the media button session's
-     * audio playback cannot be the lastly played media app. So they won't needed anymore.
+     * audio playback cannot be the lastly played media app. So they won't be needed anymore.
      *
      * @param mediaButtonSessionUid UID of the media button session.
      */
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index a6930dd..5757b1a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1973,6 +1973,34 @@
             instantiateCustomProvider(name);
         }
 
+        @Override
+        public int getSessionPolicies(MediaSession.Token token) {
+            synchronized (mLock) {
+                MediaSessionRecord record = getMediaSessionRecordLocked(token);
+                if (record != null) {
+                    return record.getSessionPolicies();
+                }
+            }
+            return 0;
+        }
+
+        @Override
+        public void setSessionPolicies(MediaSession.Token token, int policies) {
+            final long callingIdentityToken = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    MediaSessionRecord record = getMediaSessionRecordLocked(token);
+                    FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+                    if (record != null && user != null) {
+                        record.setSessionPolicies(policies);
+                        user.mPriorityStack.updateMediaButtonSessionIfNeeded();
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentityToken);
+            }
+        }
+
         // For MediaSession
         private int verifySessionsRequest(ComponentName componentName, int userId, final int pid,
                 final int uid) {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 367f131..bd98b9c 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -156,7 +156,11 @@
         if (mMediaButtonSession != null && mMediaButtonSession.getUid() == record.getUid()) {
             MediaSessionRecordImpl newMediaButtonSession =
                     findMediaButtonSession(mMediaButtonSession.getUid());
-            if (newMediaButtonSession != mMediaButtonSession) {
+            if (newMediaButtonSession != mMediaButtonSession
+                    && (newMediaButtonSession.getSessionPolicies()
+                    & SessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_SESSION) == 0) {
+                // Check if the policy states that this session should not be updated as a media
+                // button session.
                 updateMediaButtonSession(newMediaButtonSession);
             }
         }
@@ -187,14 +191,15 @@
         for (int i = 0; i < audioPlaybackUids.size(); i++) {
             MediaSessionRecordImpl mediaButtonSession =
                     findMediaButtonSession(audioPlaybackUids.get(i));
-            if (mediaButtonSession != null
-                    && (mediaButtonSession.getSessionPolicies()
-                            & SessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_SESSION) == 0) {
-                // Found the media button session.
-                mAudioPlayerStateMonitor.cleanUpAudioPlaybackUids(mediaButtonSession.getUid());
-                if (mMediaButtonSession != mediaButtonSession) {
-                    updateMediaButtonSession(mediaButtonSession);
-                }
+            if (mediaButtonSession == null) continue;
+            boolean ignoreButtonSession = (mediaButtonSession.getSessionPolicies()
+                    & SessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_SESSION) != 0;
+            if (mediaButtonSession == mMediaButtonSession && ignoreButtonSession) {
+                updateMediaButtonSession(null);
+                return;
+            }
+            if (mediaButtonSession != mMediaButtonSession && !ignoreButtonSession) {
+                updateMediaButtonSession(mediaButtonSession);
                 return;
             }
         }
@@ -276,15 +281,6 @@
     }
 
     private void updateMediaButtonSession(MediaSessionRecordImpl newMediaButtonSession) {
-        // Check if the policy states that this session should not be updated as a media button
-        // session.
-        if (newMediaButtonSession != null) {
-            int policies = newMediaButtonSession.getSessionPolicies();
-            if ((policies & SessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_SESSION) != 0) {
-                return;
-            }
-        }
-
         MediaSessionRecordImpl oldMediaButtonSession = mMediaButtonSession;
         mMediaButtonSession = newMediaButtonSession;
         mOnMediaButtonSessionChangedListener.onMediaButtonSessionChanged(