Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f0bca14 authored by Alex Dadukin's avatar Alex Dadukin
Browse files

Check if getSystemSessionInfo requested by a Proxy Router

ProxyRouter (inside MediaRouter2) calls getSystemSessionInfoForPackage
to request the initial RoutingSessionInfo. The method was designed for
LocalRouter and does not take into account calls from proxy routers,
therefore returns DEFAULT_ROUTE when requested by system router but
without bluetooth or modify audio routing permissions.

Bug: b/325755852
Test: N/A
Change-Id: I9fa38fb731c17e06927e1a927d6acc030ebb2135
parent 9ab91206
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ interface IMediaRouterService {
    // 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 @@ interface IMediaRouterService {

    // 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);
+12 −8
Original line number Diff line number Diff line
@@ -613,7 +613,7 @@ public final class MediaRouter2 {
        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 @@ public final class MediaRouter2 {
                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 @@ public final class MediaRouter2 {

        @Override
        public RoutingSessionInfo getSystemSessionInfo() {
            return getSystemSessionInfoImpl(mMediaRouterService, mClientPackageName);
            return getSystemSessionInfoImpl(
                    mMediaRouterService, mContext.getPackageName(), mClientPackageName);
        }

        /**
@@ -3049,9 +3051,11 @@ public final class MediaRouter2 {
         * <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();
            }
+9 −6
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ public final class MediaRouter2Manager {
    @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 @@ public final class MediaRouter2Manager {
    }

    private MediaRouter2Manager(Context context) {
        mContext = context.getApplicationContext();
        mMediaRouterService = IMediaRouterService.Stub.asInterface(
                ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
        mMediaSessionManager = (MediaSessionManager) context
@@ -374,16 +376,17 @@ public final class MediaRouter2Manager {
    }

    /**
     * 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();
        }
+42 −19
Original line number Diff line number Diff line
@@ -221,18 +221,27 @@ class MediaRouter2ServiceImpl {
    // 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 @@ class MediaRouter2ServiceImpl {

    @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 @@ class MediaRouter2ServiceImpl {
                        // 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 @@ class MediaRouter2ServiceImpl {
                } else {
                    return new RoutingSessionInfo.Builder(
                                    userRecord.mHandler.mSystemProvider.getDefaultSessionInfo())
                            .setClientPackageName(packageName)
                            .setClientPackageName(targetPackageName)
                            .build();
                }
            }
@@ -843,6 +861,12 @@ class MediaRouter2ServiceImpl {
                || 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 @@ class MediaRouter2ServiceImpl {
                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 @@ class MediaRouter2ServiceImpl {
        boolean hasMediaRoutingControl =
                checkMediaRoutingControlPermission(callerUid, callerPid, callerPackageName);

        boolean hasMediaContentControl = hasMediaContentControlPermission(callerUid, callerPid);
        boolean hasMediaContentControl = checkMediaContentControlPermission(callerUid, callerPid);

        Slog.i(
                TAG,
+19 −6
Original line number Diff line number Diff line
@@ -411,15 +411,21 @@ public final class MediaRouterService extends IMediaRouterService.Stub

    // 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 @@ public final class MediaRouterService extends IMediaRouterService.Stub

    // 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 @@ public final class MediaRouterService extends IMediaRouterService.Stub
                }
            }
        }
        return mService2.getSystemSessionInfo(packageName, setDeviceRouteSelected);
        return mService2.getSystemSessionInfo(
                callerPackageName, targetPackageName, setDeviceRouteSelected);
    }

    // Binder call