MediaSession2: Ask server whether a controller is trusted

Bug: 73150040
Test: Run all MediaComponents tests once
Change-Id: Ic003a40654a45e6fd367d7389216fddf320a8edc
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 6411ae1..6939537 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -19,6 +19,7 @@
 import static android.media.SessionToken2.TYPE_SESSION;
 
 import android.app.ActivityManager;
+import android.app.AppGlobals;
 import android.app.INotificationManager;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
@@ -30,6 +31,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
@@ -117,12 +119,13 @@
     private final MessageHandler mHandler = new MessageHandler();
     private final PowerManager.WakeLock mMediaEventWakeLock;
     private final int mLongPressTimeout;
+    private final INotificationManager mNotificationManager;
+    private final IPackageManager mPackageManager;
 
     private KeyguardManager mKeyguardManager;
     private IAudioService mAudioService;
     private ContentResolver mContentResolver;
     private SettingsObserver mSettingsObserver;
-    private INotificationManager mNotificationManager;
     private boolean mHasFeatureLeanback;
 
     // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
@@ -150,6 +153,7 @@
         mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
         mNotificationManager = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        mPackageManager = AppGlobals.getPackageManager();
     }
 
     @Override
@@ -1494,6 +1498,59 @@
         }
 
         /**
+         * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL
+         * permission or an enabled notification listener)
+         *
+         * @param uid uid of the controller app
+         * @param packageName package name of the controller app
+         */
+        @Override
+        public boolean isTrusted(int uid, String packageName) throws RemoteException {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                int userId = UserHandle.getUserId(uid);
+                // Sanity check whether uid and packageName matches
+                if (uid != mPackageManager.getPackageUid(packageName, 0, userId)) {
+                    throw new IllegalArgumentException("uid=" + uid + " and packageName="
+                            + packageName + " doesn't match");
+                }
+
+                // Check if it's system server or has MEDIA_CONTENT_CONTROL.
+                // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
+                // check here.
+                if (uid == Process.SYSTEM_UID || mPackageManager.checkPermission(
+                        android.Manifest.permission.MEDIA_CONTENT_CONTROL, packageName, uid)
+                        == PackageManager.PERMISSION_GRANTED) {
+                    return true;
+                }
+                if (DEBUG) {
+                    Log.d(TAG, packageName + " (uid=" + uid + ") hasn't granted"
+                            + " MEDIA_CONTENT_CONTROL");
+                }
+
+                // TODO(jaewan): Add hasEnabledNotificationListener(String pkgName) for
+                //               optimization (Post-P)
+                final List<ComponentName> enabledNotificationListeners =
+                        mNotificationManager.getEnabledNotificationListeners(userId);
+                if (enabledNotificationListeners != null) {
+                    for (int i = 0; i < enabledNotificationListeners.size(); i++) {
+                        if (TextUtils.equals(packageName,
+                                enabledNotificationListeners.get(i).getPackageName())) {
+                            return true;
+                        }
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            if (DEBUG) {
+                Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled notification"
+                        + " listener");
+            }
+            return false;
+        }
+
+        /**
          * Called when a {@link android.media.MediaSession2} instance is created.
          * <p>
          * This does two things.