diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e5e010beeebb7..7d4fad7fa8f8b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -5274,7 +5274,7 @@ package android.media { method @NonNull public java.util.List getAllRoutes(); method @Nullable public String getClientPackageName(); method @Nullable public android.media.MediaRouter2.RoutingController getController(@NonNull String); - method @Nullable public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context, @NonNull String); + method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context, @NonNull String); method public void setRouteVolume(@NonNull android.media.MediaRoute2Info, int); method public void startScan(); method public void stopScan(); diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index 4b8a8adade1f8..f817a3c3c3530 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -48,6 +48,7 @@ interface IMediaRouterService { // MediaRouterService.java for readability. // Methods for MediaRouter2 + void checkModifyAudioRoutingPermission(); List getSystemRoutes(); RoutingSessionInfo getSystemSessionInfo(); diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 1f6855a4ae8e7..90fa9a52f5cf2 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -21,6 +21,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.Context; @@ -159,9 +160,11 @@ public final class MediaRouter2 { * Finally, it will have no effect to call {@link #setOnGetControllerHintsListener}. * * @param clientPackageName the package name of the app to control + * @throws SecurityException if the caller doesn't have MODIFY_AUDIO_ROUTING permission. * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) @Nullable public static MediaRouter2 getInstance(@NonNull Context context, @NonNull String clientPackageName) { @@ -179,13 +182,20 @@ public final class MediaRouter2 { synchronized (sSystemRouterLock) { MediaRouter2 instance = sSystemMediaRouter2Map.get(clientPackageName); if (instance == null) { - // TODO: Add permission check here using MODIFY_AUDIO_ROUTING. if (sManager == null) { + IMediaRouterService serviceBinder = IMediaRouterService.Stub.asInterface( + ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE)); + try { + // MediaRouterService will throw a SecurityException if the caller + // doesn't have MODIFY_AUDIO_ROUTING permission. + serviceBinder.checkModifyAudioRoutingPermission(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } sManager = MediaRouter2Manager.getInstance(context.getApplicationContext()); } instance = new MediaRouter2(context, clientPackageName); sSystemMediaRouter2Map.put(clientPackageName, instance); - // TODO: Remove router instance once it is not needed. instance.registerManagerCallbackForSystemRouter(); } return instance; @@ -281,9 +291,9 @@ public final class MediaRouter2 { mDiscoveryPreference = new RouteDiscoveryPreference.Builder( sManager.getPreferredFeatures(clientPackageName), true).build(); updateAllRoutesFromManager(); - mMediaRouterService = null; // TODO: Make this non-null and check permission. // Only used by non-system MediaRouter2. + mMediaRouterService = null; mPackageName = null; } diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 31edf43679e90..5286bce67b373 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -112,6 +112,22 @@ class MediaRouter2ServiceImpl { //// - Should not have @NonNull/@Nullable on any arguments //////////////////////////////////////////////////////////////// + @NonNull + public void checkModifyAudioRoutingPermission() { + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + + try { + if (mContext.checkPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING, pid, uid) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Must hold the MODIFY_AUDIO_ROUTING permission."); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + @NonNull public List getSystemRoutes() { final int uid = Binder.getCallingUid(); diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index b6d6cc48d0cdb..b85cea7a637d0 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -436,6 +436,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub } } + // Binder call + @Override + public void checkModifyAudioRoutingPermission() { + mService2.checkModifyAudioRoutingPermission(); + } + // Binder call @Override public List getSystemRoutes() {