[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
This commit is contained in:
@@ -180,7 +180,7 @@ public final class MediaSessionManager {
|
|||||||
* be provided in priority order with the most important controller at index
|
* be provided in priority order with the most important controller at index
|
||||||
* 0.
|
* 0.
|
||||||
* <p>
|
* <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
|
* permission be held by the calling app. You may also retrieve this list if
|
||||||
* your app is an enabled notification listener using the
|
* your app is an enabled notification listener using the
|
||||||
* {@link NotificationListenerService} APIs, in which case you must pass 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
|
* Get active sessions for the given user.
|
||||||
* other than your own you must hold the
|
* <p>
|
||||||
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission
|
* This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
|
||||||
* in addition to any other requirements. If you are an enabled notification
|
* held by the calling app. You may also retrieve this list if your app is an enabled
|
||||||
* listener you may only get sessions for the users you are enabled for.
|
* 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.
|
* @param notificationListener The enabled notification listener component. May be null.
|
||||||
* May be null.
|
|
||||||
* @param userId The user id to fetch sessions for.
|
* @param userId The user id to fetch sessions for.
|
||||||
* @return A list of controllers for ongoing sessions.
|
* @return A list of controllers for ongoing sessions.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -248,8 +252,9 @@ public final class MediaSessionManager {
|
|||||||
* Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
|
* Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
|
||||||
* given user.
|
* given user.
|
||||||
* <p>
|
* <p>
|
||||||
* If you want to get tokens for another user, you must hold the
|
* The calling application needs to hold the
|
||||||
* android.Manifest.permission#INTERACT_ACROSS_USERS_FULL permission.
|
* {@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.
|
* @param userId The user id to fetch sessions for.
|
||||||
* @return A list of {@link Session2Token}
|
* @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
|
* Add a listener to be notified when the list of active sessions changes.
|
||||||
* {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be held by the calling
|
* <p>
|
||||||
* app. You may also retrieve this list if your app is an enabled notification listener using
|
* This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
|
||||||
* the {@link NotificationListenerService} APIs, in which case you must pass the
|
* held by the calling app. You may also retrieve this list if your app is an enabled
|
||||||
* {@link ComponentName} of your enabled listener.
|
* 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 sessionListener The listener to add.
|
||||||
* @param notificationListener The enabled notification listener component. May be null.
|
* @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
|
* Add a listener to be notified when the list of active sessions changes.
|
||||||
* {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be held by the calling
|
* <p>
|
||||||
* app. You may also retrieve this list if your app is an enabled notification listener using
|
* This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
|
||||||
* the {@link NotificationListenerService} APIs, in which case you must pass the
|
* held by the calling app. You may also retrieve this list if your app is an enabled
|
||||||
* {@link ComponentName} of your enabled listener. Updates will be posted to the handler
|
* notification listener using the {@link NotificationListenerService} APIs, in which case you
|
||||||
* specified or to the caller's thread if the handler is null.
|
* 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 sessionListener The listener to add.
|
||||||
* @param notificationListener The enabled notification listener component. May be null.
|
* @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.
|
* Add a listener to be notified when the list of active sessions changes.
|
||||||
* 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.
|
|
||||||
* <p>
|
* <p>
|
||||||
* This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
|
* 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
|
* 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
|
* 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
|
* 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.
|
* 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 sessionListener The listener to add.
|
||||||
* @param notificationListener The enabled notification listener component. May be null.
|
* @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.
|
* Library</a> for consistent behavior across all devices.
|
||||||
* <p>
|
* <p>
|
||||||
* Adds a listener to be notified when the {@link #getSession2Tokens()} changes.
|
* 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 userId The userId to listen for changes on
|
||||||
* @param listener The listener to add
|
* @param listener The listener to add
|
||||||
@@ -705,8 +718,9 @@ public final class MediaSessionManager {
|
|||||||
/**
|
/**
|
||||||
* Checks whether the remote user is a trusted app.
|
* Checks whether the remote user is a trusted app.
|
||||||
* <p>
|
* <p>
|
||||||
* An app is trusted if the app holds the android.Manifest.permission.MEDIA_CONTENT_CONTROL
|
* An app is trusted if the app holds the
|
||||||
* permission or has an enabled notification listener.
|
* {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission or has an enabled
|
||||||
|
* notification listener.
|
||||||
*
|
*
|
||||||
* @param userInfo The remote user info from either
|
* @param userInfo The remote user info from either
|
||||||
* {@link MediaSession#getCurrentControllerInfo()} or
|
* {@link MediaSession#getCurrentControllerInfo()} or
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.media;
|
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.ALL;
|
||||||
import static android.os.UserHandle.CURRENT;
|
import static android.os.UserHandle.CURRENT;
|
||||||
|
|
||||||
@@ -1114,8 +1115,7 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
enforcePackageName(packageName, uid);
|
enforcePackageName(packageName, uid);
|
||||||
int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
|
int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
|
||||||
false /* allowAll */, true /* requireFull */, "createSession", packageName);
|
|
||||||
if (cb == null) {
|
if (cb == null) {
|
||||||
throw new IllegalArgumentException("Controller callback cannot be 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();
|
final long token = Binder.clearCallingIdentity();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check that they can make calls on behalf of the user and
|
// Check that they can make calls on behalf of the user and get the final user id
|
||||||
// get the final user id
|
int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
|
||||||
int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
|
|
||||||
true /* allowAll */, true /* requireFull */, "getSession2Tokens",
|
|
||||||
null /* optional packageName */);
|
|
||||||
List<Session2Token> result;
|
List<Session2Token> result;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
FullUserRecord user = getFullUserRecordLocked(userId);
|
FullUserRecord user = getFullUserRecordLocked(userId);
|
||||||
@@ -1261,9 +1258,7 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Check that they can make calls on behalf of the user and get the final user id.
|
// Check that they can make calls on behalf of the user and get the final user id.
|
||||||
int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
|
int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
|
||||||
true /* allowAll */, true /* requireFull */, "addSession2TokensListener",
|
|
||||||
null /* optional packageName */);
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
int index = findIndexOfSession2TokensListenerLocked(listener);
|
int index = findIndexOfSession2TokensListenerLocked(listener);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
@@ -1980,16 +1975,40 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
packageName = componentName.getPackageName();
|
packageName = componentName.getPackageName();
|
||||||
enforcePackageName(packageName, uid);
|
enforcePackageName(packageName, uid);
|
||||||
}
|
}
|
||||||
// Check that they can make calls on behalf of the user and
|
// Check that they can make calls on behalf of the user and get the final user id
|
||||||
// get the final user id
|
int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
|
||||||
int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
|
// Check if they have the permissions or their component is enabled for the user
|
||||||
true /* allowAll */, true /* requireFull */, "getSessions", packageName);
|
// they're calling from.
|
||||||
// Check if they have the permissions or their component is
|
|
||||||
// enabled for the user they're calling from.
|
|
||||||
enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
|
enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
|
||||||
return 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,
|
private boolean hasEnabledNotificationListener(int callingUserId,
|
||||||
String controllerPackageName, int controllerUid) {
|
String controllerPackageName, int controllerUid) {
|
||||||
int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
|
int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
|
||||||
|
|||||||
Reference in New Issue
Block a user