Merge "Check if getSystemSessionInfo requested by a Proxy Router" into main
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 7727078..63cb945 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -50,7 +50,7 @@
     // MediaRouterService.java for readability.
 
     // Methods for MediaRouter2
-    List<MediaRoute2Info> getSystemRoutes();
+    List<MediaRoute2Info> getSystemRoutes(String callerPackageName, boolean isProxyRouter);
     RoutingSessionInfo getSystemSessionInfo();
 
     void registerRouter2(IMediaRouter2 router, String packageName);
@@ -75,7 +75,8 @@
 
     // Methods for MediaRouter2Manager
     List<RoutingSessionInfo> getRemoteSessions(IMediaRouter2Manager manager);
-    RoutingSessionInfo getSystemSessionInfoForPackage(String packageName);
+    RoutingSessionInfo getSystemSessionInfoForPackage(String callerPackageName,
+        String targetPackageName);
     void registerManager(IMediaRouter2Manager manager, String packageName);
     void registerProxyRouter(IMediaRouter2Manager manager, String callingPackageName, String targetPackageName, in UserHandle targetUser);
     void unregisterManager(IMediaRouter2Manager manager);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index e0258ba..3f9440b 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -613,7 +613,7 @@
         mImpl = new LocalMediaRouter2Impl(mContext.getPackageName());
         mHandler = new Handler(Looper.getMainLooper());
 
-        loadSystemRoutes();
+        loadSystemRoutes(/* isProxyRouter */ false);
 
         RoutingSessionInfo currentSystemSessionInfo = mImpl.getSystemSessionInfo();
         if (currentSystemSessionInfo == null) {
@@ -631,21 +631,22 @@
                 IMediaRouterService.Stub.asInterface(
                         ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
 
-        loadSystemRoutes();
+        loadSystemRoutes(/* isProxyRouter */ true);
 
         mSystemController =
                 new SystemRoutingController(
                         ProxyMediaRouter2Impl.getSystemSessionInfoImpl(
-                                mMediaRouterService, clientPackageName));
+                                mMediaRouterService, mContext.getPackageName(), clientPackageName));
 
         mImpl = new ProxyMediaRouter2Impl(context, clientPackageName, user);
     }
 
     @GuardedBy("mLock")
-    private void loadSystemRoutes() {
+    private void loadSystemRoutes(boolean isProxyRouter) {
         List<MediaRoute2Info> currentSystemRoutes = null;
         try {
-            currentSystemRoutes = mMediaRouterService.getSystemRoutes();
+            currentSystemRoutes = mMediaRouterService.getSystemRoutes(mContext.getPackageName(),
+                    isProxyRouter);
         } catch (RemoteException ex) {
             ex.rethrowFromSystemServer();
         }
@@ -2644,7 +2645,8 @@
 
         @Override
         public RoutingSessionInfo getSystemSessionInfo() {
-            return getSystemSessionInfoImpl(mMediaRouterService, mClientPackageName);
+            return getSystemSessionInfoImpl(
+                    mMediaRouterService, mContext.getPackageName(), mClientPackageName);
         }
 
         /**
@@ -3049,9 +3051,11 @@
          * <p>Extracted into a static method to allow calling this from the constructor.
          */
         /* package */ static RoutingSessionInfo getSystemSessionInfoImpl(
-                @NonNull IMediaRouterService service, @NonNull String clientPackageName) {
+                @NonNull IMediaRouterService service,
+                @NonNull String callerPackageName,
+                @NonNull String clientPackageName) {
             try {
-                return service.getSystemSessionInfoForPackage(clientPackageName);
+                return service.getSystemSessionInfoForPackage(callerPackageName, clientPackageName);
             } catch (RemoteException ex) {
                 throw ex.rethrowFromSystemServer();
             }
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 7756d93..e62d112 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -81,6 +81,7 @@
     @GuardedBy("sLock")
     private static MediaRouter2Manager sInstance;
 
+    private final Context mContext;
     private final MediaSessionManager mMediaSessionManager;
     private final Client mClient;
     private final IMediaRouterService mMediaRouterService;
@@ -120,6 +121,7 @@
     }
 
     private MediaRouter2Manager(Context context) {
+        mContext = context.getApplicationContext();
         mMediaRouterService = IMediaRouterService.Stub.asInterface(
                 ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
         mMediaSessionManager = (MediaSessionManager) context
@@ -374,16 +376,17 @@
     }
 
     /**
-     * Gets the system routing session for the given {@code packageName}.
-     * Apps can select a route that is not the global route. (e.g. an app can select the device
-     * route while BT route is available.)
+     * Gets the system routing session for the given {@code targetPackageName}. Apps can select a
+     * route that is not the global route. (e.g. an app can select the device route while BT route
+     * is available.)
      *
-     * @param packageName the package name of the application.
+     * @param targetPackageName the package name of the application.
      */
     @Nullable
-    public RoutingSessionInfo getSystemRoutingSession(@Nullable String packageName) {
+    public RoutingSessionInfo getSystemRoutingSession(@Nullable String targetPackageName) {
         try {
-            return mMediaRouterService.getSystemSessionInfoForPackage(packageName);
+            return mMediaRouterService.getSystemSessionInfoForPackage(
+                    mContext.getPackageName(), targetPackageName);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index ae6a7e9..ec15ff3 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -221,18 +221,27 @@
     // Start of methods that implement MediaRouter2 operations.
 
     @NonNull
-    public List<MediaRoute2Info> getSystemRoutes() {
+    public List<MediaRoute2Info> getSystemRoutes(@NonNull String callerPackageName,
+            boolean isProxyRouter) {
         final int uid = Binder.getCallingUid();
         final int pid = Binder.getCallingPid();
         final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
-        final boolean hasSystemRoutingPermission = checkCallerHasSystemRoutingPermissions(pid, uid);
+
+        boolean hasSystemRoutingPermissions;
+        if (!isProxyRouter) {
+            hasSystemRoutingPermissions = checkCallerHasSystemRoutingPermissions(pid, uid);
+        } else {
+            // Request from ProxyRouter.
+            hasSystemRoutingPermissions =
+                    checkCallerHasPrivilegedRoutingPermissions(pid, uid, callerPackageName);
+        }
 
         final long token = Binder.clearCallingIdentity();
         try {
             Collection<MediaRoute2Info> systemRoutes;
             synchronized (mLock) {
                 UserRecord userRecord = getOrCreateUserRecordLocked(userId);
-                if (hasSystemRoutingPermission) {
+                if (hasSystemRoutingPermissions) {
                     MediaRoute2ProviderInfo providerInfo =
                             userRecord.mHandler.mSystemProvider.getProviderInfo();
                     if (providerInfo != null) {
@@ -795,12 +804,21 @@
 
     @Nullable
     public RoutingSessionInfo getSystemSessionInfo(
-            @Nullable String packageName, boolean setDeviceRouteSelected) {
+            @NonNull String callerPackageName,
+            @Nullable String targetPackageName,
+            boolean setDeviceRouteSelected) {
         final int uid = Binder.getCallingUid();
         final int pid = Binder.getCallingPid();
         final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
-        final boolean hasSystemRoutingPermissions =
-                checkCallerHasSystemRoutingPermissions(pid, uid);
+
+        boolean hasSystemRoutingPermissions;
+        if (targetPackageName == null) {
+            hasSystemRoutingPermissions = checkCallerHasSystemRoutingPermissions(pid, uid);
+        } else {
+            // Request from ProxyRouter.
+            hasSystemRoutingPermissions =
+                    checkCallerHasPrivilegedRoutingPermissions(pid, uid, callerPackageName);
+        }
 
         final long token = Binder.clearCallingIdentity();
         try {
@@ -812,14 +830,14 @@
                         // Return a fake system session that shows the device route as selected and
                         // available bluetooth routes as transferable.
                         return userRecord.mHandler.mSystemProvider
-                                .generateDeviceRouteSelectedSessionInfo(packageName);
+                                .generateDeviceRouteSelectedSessionInfo(targetPackageName);
                     } else {
                         sessionInfos = userRecord.mHandler.mSystemProvider.getSessionInfos();
                         if (!sessionInfos.isEmpty()) {
                             // Return a copy of the current system session with no modification,
                             // except setting the client package name.
                             return new RoutingSessionInfo.Builder(sessionInfos.get(0))
-                                    .setClientPackageName(packageName)
+                                    .setClientPackageName(targetPackageName)
                                     .build();
                         } else {
                             Slog.w(TAG, "System provider does not have any session info.");
@@ -828,7 +846,7 @@
                 } else {
                     return new RoutingSessionInfo.Builder(
                                     userRecord.mHandler.mSystemProvider.getDefaultSessionInfo())
-                            .setClientPackageName(packageName)
+                            .setClientPackageName(targetPackageName)
                             .build();
                 }
             }
@@ -843,6 +861,12 @@
                 || checkCallerHasBluetoothPermissions(pid, uid);
     }
 
+    private boolean checkCallerHasPrivilegedRoutingPermissions(
+            int pid, int uid, @NonNull String callerPackageName) {
+        return checkMediaContentControlPermission(uid, pid)
+                || checkMediaRoutingControlPermission(uid, pid, callerPackageName);
+    }
+
     private boolean checkCallerHasModifyAudioRoutingPermission(int pid, int uid) {
         return mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_ROUTING, pid, uid)
                 == PackageManager.PERMISSION_GRANTED;
@@ -864,30 +888,29 @@
                 Manifest.permission.MEDIA_CONTENT_CONTROL
             })
     private void enforcePrivilegedRoutingPermissions(
-            int callerUid, int callerPid, @Nullable String callerPackageName) {
-        if (hasMediaContentControlPermission(callerUid, callerPid)) {
+            int callerUid, int callerPid, @NonNull String callerPackageName) {
+        if (checkMediaContentControlPermission(callerUid, callerPid)) {
             return;
         }
 
-        if (!Flags.enablePrivilegedRoutingForMediaRoutingControl()) {
-            throw new SecurityException("Must hold MEDIA_CONTENT_CONTROL");
-        }
-
         if (!checkMediaRoutingControlPermission(callerUid, callerPid, callerPackageName)) {
             throw new SecurityException(
                     "Must hold MEDIA_CONTENT_CONTROL or MEDIA_ROUTING_CONTROL permissions.");
         }
     }
 
-    @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
-    private boolean hasMediaContentControlPermission(int callerUid, int callerPid) {
+    private boolean checkMediaContentControlPermission(int callerUid, int callerPid) {
         return mContext.checkPermission(
                         Manifest.permission.MEDIA_CONTENT_CONTROL, callerPid, callerUid)
                 == PackageManager.PERMISSION_GRANTED;
     }
 
     private boolean checkMediaRoutingControlPermission(
-            int callerUid, int callerPid, @Nullable String callerPackageName) {
+            int callerUid, int callerPid, @NonNull String callerPackageName) {
+        if (!Flags.enablePrivilegedRoutingForMediaRoutingControl()) {
+            return false;
+        }
+
         return PermissionChecker.checkPermissionForDataDelivery(
                         mContext,
                         Manifest.permission.MEDIA_ROUTING_CONTROL,
@@ -1520,7 +1543,7 @@
         boolean hasMediaRoutingControl =
                 checkMediaRoutingControlPermission(callerUid, callerPid, callerPackageName);
 
-        boolean hasMediaContentControl = hasMediaContentControlPermission(callerUid, callerPid);
+        boolean hasMediaContentControl = checkMediaContentControlPermission(callerUid, callerPid);
 
         Slog.i(
                 TAG,
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 6af3480..76b8db6 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -411,15 +411,21 @@
 
     // Binder call
     @Override
-    public List<MediaRoute2Info> getSystemRoutes() {
-        return mService2.getSystemRoutes();
+    public List<MediaRoute2Info> getSystemRoutes(@NonNull String callerPackageName,
+            boolean isProxyRouter) {
+        if (!validatePackageName(Binder.getCallingUid(), callerPackageName)) {
+            throw new SecurityException("callerPackageName does not match calling uid.");
+        }
+        return mService2.getSystemRoutes(callerPackageName, isProxyRouter);
     }
 
     // Binder call
     @Override
     public RoutingSessionInfo getSystemSessionInfo() {
         return mService2.getSystemSessionInfo(
-                null /* packageName */, false /* setDeviceRouteSelected */);
+                /* callerPackageName */ null,
+                /* targetPackageName */ null, /* setDeviceRouteSelected */
+                false);
     }
 
     // Binder call
@@ -530,16 +536,22 @@
 
     // Binder call
     @Override
-    public RoutingSessionInfo getSystemSessionInfoForPackage(@Nullable String packageName) {
+    public RoutingSessionInfo getSystemSessionInfoForPackage(
+            @NonNull String callerPackageName, @Nullable String targetPackageName) {
         final int uid = Binder.getCallingUid();
         final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+
+        if (!validatePackageName(uid, callerPackageName)) {
+            throw new SecurityException("callerPackageName does not match calling uid.");
+        }
+
         boolean setDeviceRouteSelected = false;
         synchronized (mLock) {
             UserRecord userRecord = mUserRecords.get(userId);
             List<ClientRecord> userClientRecords =
                     userRecord != null ? userRecord.mClientRecords : Collections.emptyList();
             for (ClientRecord clientRecord : userClientRecords) {
-                if (TextUtils.equals(clientRecord.mPackageName, packageName)) {
+                if (TextUtils.equals(clientRecord.mPackageName, targetPackageName)) {
                     if (mDefaultAudioRouteId.equals(clientRecord.mSelectedRouteId)) {
                         setDeviceRouteSelected = true;
                         break;
@@ -547,7 +559,8 @@
                 }
             }
         }
-        return mService2.getSystemSessionInfo(packageName, setDeviceRouteSelected);
+        return mService2.getSystemSessionInfo(
+                callerPackageName, targetPackageName, setDeviceRouteSelected);
     }
 
     // Binder call