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

Commit 1d1547b1 authored by Jin Seok Park's avatar Jin Seok Park
Browse files

[Media ML] Copy over ActivityManager#handleIncomingUser

This CL copies over the implementation of
ActivityManager#handleIncomingUser except for the case of
USER_CURRENT_OR_SELF. See go/replace-handleincominguser Section
"New Implementation" for reasoning behind this.

Bug: 163336589
Test: Manually test USER_CURRENT and USER_ALL cases via
PipMediaController and NotificationMediaManager.

Change-Id: Id6dbf61d1e66c8e20fc9608ec2bc1df0486b92e2
parent 3961654d
Loading
Loading
Loading
Loading
+40 −26
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ public final class MediaSessionManager {
     * be provided in priority order with the most important controller at index
     * 0.
     * <p>
     * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL
     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
     * permission be held by the calling app. You may also retrieve this list if
     * your app is an enabled notification listener using the
     * {@link NotificationListenerService} APIs, in which case you must pass the
@@ -196,14 +196,18 @@ public final class MediaSessionManager {
    }

    /**
     * Get active sessions for a specific user. To retrieve actions for a user
     * other than your own you must hold the
     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission
     * in addition to any other requirements. If you are an enabled notification
     * listener you may only get sessions for the users you are enabled for.
     * Get active sessions for the given user.
     * <p>
     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
     * held by the calling app. You may also retrieve this list if your app is an enabled
     * notification listener using the {@link NotificationListenerService} APIs, in which case you
     * must pass the {@link ComponentName} of your enabled listener.
     * <p>
     * The calling application needs to hold the
     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
     * retrieve sessions for user ids that do not belong to current process.
     *
     * @param notificationListener The enabled notification listener component.
     *            May be null.
     * @param notificationListener The enabled notification listener component. May be null.
     * @param userId The user id to fetch sessions for.
     * @return A list of controllers for ongoing sessions.
     * @hide
@@ -248,8 +252,9 @@ public final class MediaSessionManager {
     * Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
     * given user.
     * <p>
     * If you want to get tokens for another user, you must hold the
     * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL permission.
     * The calling application needs to hold the
     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
     * retrieve session tokens for user ids that do not belong to current process.
     *
     * @param userId The user id to fetch sessions for.
     * @return A list of {@link Session2Token}
@@ -267,11 +272,12 @@ public final class MediaSessionManager {
    }

    /**
     * Add a listener to be notified when the list of active sessions changes. This requires the
     * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be held by the calling
     * app. You may also retrieve this list if your app is an enabled notification listener using
     * the {@link NotificationListenerService} APIs, in which case you must pass the
     * {@link ComponentName} of your enabled listener.
     * Add a listener to be notified when the list of active sessions changes.
     * <p>
     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
     * held by the calling app. You may also retrieve this list if your app is an enabled
     * notificationlistener using the {@link NotificationListenerService} APIs, in which case you
     * must pass the {@link ComponentName} of your enabled listener.
     *
     * @param sessionListener The listener to add.
     * @param notificationListener The enabled notification listener component. May be null.
@@ -283,12 +289,13 @@ public final class MediaSessionManager {
    }

    /**
     * Add a listener to be notified when the list of active sessions changes. This requires the
     * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be held by the calling
     * app. You may also retrieve this list if your app is an enabled notification listener using
     * the {@link NotificationListenerService} APIs, in which case you must pass the
     * {@link ComponentName} of your enabled listener. Updates will be posted to the handler
     * specified or to the caller's thread if the handler is null.
     * Add a listener to be notified when the list of active sessions changes.
     * <p>
     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
     * held by the calling app. You may also retrieve this list if your app is an enabled
     * notification listener using the {@link NotificationListenerService} APIs, in which case you
     * must pass the {@link ComponentName} of your enabled listener. Updates will be posted to the
     * handler specified or to the caller's thread if the handler is null.
     *
     * @param sessionListener The listener to add.
     * @param notificationListener The enabled notification listener component. May be null.
@@ -302,15 +309,17 @@ public final class MediaSessionManager {
    }

    /**
     * Add a listener to be notified when the list of active sessions changes for the given user.
     * The calling app must have the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
     * permission if it wants to call this method for a user that is not running the app.
     * Add a listener to be notified when the list of active sessions changes.
     * <p>
     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
     * held by the calling app. You may also retrieve this list if your app is an enabled
     * notification listener using the {@link NotificationListenerService} APIs, in which case you
     * must pass the {@link ComponentName} of your enabled listener. Updates will be posted to the
     * handler specified or to the caller's thread if the handler is null.
     * <p>
     * The calling application needs to hold the
     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
     * add listeners for user ids that do not belong to current process.
     *
     * @param sessionListener The listener to add.
     * @param notificationListener The enabled notification listener component. May be null.
@@ -407,6 +416,10 @@ public final class MediaSessionManager {
     * Library</a> for consistent behavior across all devices.
     * <p>
     * Adds a listener to be notified when the {@link #getSession2Tokens()} changes.
     * <p>
     * The calling application needs to hold the
     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
     * add listeners for user ids that do not belong to current process.
     *
     * @param userId The userId to listen for changes on
     * @param listener The listener to add
@@ -705,8 +718,9 @@ public final class MediaSessionManager {
    /**
     * Checks whether the remote user is a trusted app.
     * <p>
     * An app is trusted if the app holds the android.Manifest.permission.MEDIA_CONTENT_CONTROL
     * permission or has an enabled notification listener.
     * An app is trusted if the app holds the
     * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission or has an enabled
     * notification listener.
     *
     * @param userInfo The remote user info from either
     *            {@link MediaSession#getCurrentControllerInfo()} or
+35 −16
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.media;

import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.os.UserHandle.ALL;
import static android.os.UserHandle.CURRENT;

@@ -1114,8 +1115,7 @@ public class MediaSessionService extends SystemService implements Monitor {
            final long token = Binder.clearCallingIdentity();
            try {
                enforcePackageName(packageName, uid);
                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
                        false /* allowAll */, true /* requireFull */, "createSession", packageName);
                int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
                if (cb == null) {
                    throw new IllegalArgumentException("Controller callback cannot be null");
                }
@@ -1190,11 +1190,8 @@ public class MediaSessionService extends SystemService implements Monitor {
            final long token = Binder.clearCallingIdentity();

            try {
                // Check that they can make calls on behalf of the user and
                // get the final user id
                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
                        true /* allowAll */, true /* requireFull */, "getSession2Tokens",
                        null /* optional packageName */);
                // Check that they can make calls on behalf of the user and get the final user id
                int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
                List<Session2Token> result;
                synchronized (mLock) {
                    FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1261,9 +1258,7 @@ public class MediaSessionService extends SystemService implements Monitor {

            try {
                // Check that they can make calls on behalf of the user and get the final user id.
                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
                        true /* allowAll */, true /* requireFull */, "addSession2TokensListener",
                        null /* optional packageName */);
                int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
                synchronized (mLock) {
                    int index = findIndexOfSession2TokensListenerLocked(listener);
                    if (index >= 0) {
@@ -1980,16 +1975,40 @@ public class MediaSessionService extends SystemService implements Monitor {
                packageName = componentName.getPackageName();
                enforcePackageName(packageName, uid);
            }
            // Check that they can make calls on behalf of the user and
            // get the final user id
            int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
                    true /* allowAll */, true /* requireFull */, "getSessions", packageName);
            // Check if they have the permissions or their component is
            // enabled for the user they're calling from.
            // Check that they can make calls on behalf of the user and get the final user id
            int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
            // Check if they have the permissions or their component is enabled for the user
            // they're calling from.
            enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
            return resolvedUserId;
        }

        // Handles incoming user by checking whether the caller has permission to access the
        // given user id's information or not. Permission is not necessary if the given user id is
        // equal to the caller's user id, but if not, the caller needs to have the
        // INTERACT_ACROSS_USERS_FULL permission. Otherwise, a security exception will be thrown.
        // The return value will be the given user id, unless the given user id is
        // UserHandle.CURRENT, which will return the ActivityManager.getCurrentUser() value instead.
        private int handleIncomingUser(int pid, int uid, int userId, String packageName) {
            int callingUserId = UserHandle.getUserHandleForUid(uid).getIdentifier();
            if (userId == callingUserId) {
                return userId;
            }

            boolean canInteractAcrossUsersFull = mContext.checkPermission(
                    INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED;
            if (canInteractAcrossUsersFull) {
                if (userId == CURRENT.getIdentifier()) {
                    return ActivityManager.getCurrentUser();
                }
                return userId;
            }

            throw new SecurityException("Permission denied while calling from " + packageName
                    + " with user id: " + userId + "; Need to run as either the calling user id ("
                    + callingUserId + "), or with " + INTERACT_ACROSS_USERS_FULL + " permission");
        }

        private boolean hasEnabledNotificationListener(int callingUserId,
                String controllerPackageName, int controllerUid) {
            int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();