Merge changes from topic "queryUser"

* changes:
  Add QUERY_USERS permission to some UserManager APIs
  Create new QUERY_USERS permission
This commit is contained in:
Kholoud Mohamed
2021-12-10 21:54:34 +00:00
committed by Android (Google) Code Review
7 changed files with 256 additions and 95 deletions

View File

@@ -32520,7 +32520,7 @@ package android.os {
method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.CREATE_USERS"}) public int getUserCount();
method public long getUserCreationTime(android.os.UserHandle);
method public android.os.UserHandle getUserForSerialNumber(long);
method @NonNull @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED, "android.permission.CREATE_USERS"}, conditional=true) public String getUserName();
method @NonNull @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.CREATE_USERS", "android.permission.QUERY_USERS", android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public String getUserName();
method public java.util.List<android.os.UserHandle> getUserProfiles();
method public android.os.Bundle getUserRestrictions();
method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.os.Bundle getUserRestrictions(android.os.UserHandle);

View File

@@ -219,6 +219,7 @@ package android {
field public static final String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
field public static final String QUERY_ADMIN_POLICY = "android.permission.QUERY_ADMIN_POLICY";
field public static final String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
field public static final String QUERY_USERS = "android.permission.QUERY_USERS";
field public static final String RADIO_SCAN_WITHOUT_LOCATION = "android.permission.RADIO_SCAN_WITHOUT_LOCATION";
field public static final String READ_ACTIVE_EMERGENCY_SESSION = "android.permission.READ_ACTIVE_EMERGENCY_SESSION";
field public static final String READ_APP_SPECIFIC_LOCALES = "android.permission.READ_APP_SPECIFIC_LOCALES";
@@ -9059,31 +9060,31 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearSeedAccountData();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle createProfile(@NonNull String, @NonNull String, @NonNull java.util.Set<java.lang.String>) throws android.os.UserManager.UserOperationException;
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.NewUserResponse createUser(@NonNull android.os.NewUserRequest);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getAllProfiles();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getEnabledProfiles();
method @NonNull public java.util.List<android.os.UserHandle> getAllProfiles();
method @NonNull public java.util.List<android.os.UserHandle> getEnabledProfiles();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle getRestrictedProfileParent();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public android.os.UserHandle getRestrictedProfileParent();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountName();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountType();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public long[] getSerialNumbersOfUsers(boolean);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.os.UserHandle> getUserHandles(boolean);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public android.graphics.Bitmap getUserIcon();
method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public int getUserRestrictionSource(String, android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean hasRestrictedProfiles();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean hasUserRestrictionForUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isAdminUser();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isAdminUser();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isCloneProfile();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isGuestUser();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isManagedProfile(int);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isGuestUser();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isManagedProfile(int);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isMediaSharedWithParent();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isPrimaryUser();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isProfile();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
method public boolean isProfile();
method public boolean isRestrictedProfile();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public boolean isUserNameSet();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUserOfType(@NonNull String);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isUserUnlockingOrUnlocked(@NonNull android.os.UserHandle);

View File

@@ -1818,7 +1818,7 @@ package android.os {
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createRestrictedProfile(@Nullable String);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createUser(@Nullable String, @NonNull String, int);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.Set<java.lang.String> getPreInstallableSystemPackages(@NonNull String);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public String getUserType();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public String getUserType();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
method public static boolean isGuestUserEphemeral();

View File

@@ -2073,7 +2073,8 @@ public class UserManager {
@TestApi
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.CREATE_USERS})
android.Manifest.permission.CREATE_USERS,
android.Manifest.permission.QUERY_USERS})
@UserHandleAware
public @NonNull String getUserType() {
UserInfo userInfo = getUserInfo(mUserId);
@@ -2082,15 +2083,21 @@ public class UserManager {
/**
* Returns the user name of the context user. This call is only available to applications on
* the system image; it requires the {@code android.permission.MANAGE_USERS} or {@code
* android.permission.GET_ACCOUNTS_PRIVILEGED} permissions.
* the system image.
*
* @return the user name
*/
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED,
android.Manifest.permission.CREATE_USERS}, conditional = true)
@UserHandleAware
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.CREATE_USERS,
android.Manifest.permission.QUERY_USERS,
android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED})
@UserHandleAware(
requiresAnyOfPermissionsIfNotCaller = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.CREATE_USERS,
android.Manifest.permission.QUERY_USERS})
public @NonNull String getUserName() {
if (UserHandle.myUserId() == mUserId) {
try {
@@ -2153,8 +2160,10 @@ public class UserManager {
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
@UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public boolean isPrimaryUser() {
final UserInfo user = getUserInfo(getContextUserIfAppropriate());
@@ -2184,7 +2193,8 @@ public class UserManager {
@SystemApi
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
@UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public boolean isAdminUser() {
return isUserAdmin(getContextUserIfAppropriate());
@@ -2196,8 +2206,10 @@ public class UserManager {
* user.
*/
@UnsupportedAppUsage
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
public boolean isUserAdmin(@UserIdInt int userId) {
UserInfo user = getUserInfo(userId);
return user != null && user.isAdmin();
@@ -2394,8 +2406,10 @@ public class UserManager {
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
@UserHandleAware
public @Nullable UserHandle getRestrictedProfileParent() {
final UserInfo info = getUserInfo(mUserId);
@@ -2412,8 +2426,10 @@ public class UserManager {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
public boolean isGuestUser(@UserIdInt int userId) {
UserInfo user = getUserInfo(userId);
return user != null && user.isGuest();
@@ -2426,8 +2442,10 @@ public class UserManager {
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
@UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public boolean isGuestUser() {
UserInfo user = getUserInfo(getContextUserIfAppropriate());
@@ -2456,17 +2474,15 @@ public class UserManager {
/**
* Checks if the calling context user is running in a profile.
*
* Requires {@link android.Manifest.permission#MANAGE_USERS} or
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission, otherwise the
* caller must be in the same profile group of specified user.
*
* @return whether the caller is in a profile.
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
@UserHandleAware
@UserHandleAware(
requiresAnyOfPermissionsIfNotCallerProfileGroup = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS})
public boolean isProfile() {
return isProfile(mUserId);
}
@@ -2502,8 +2518,8 @@ public class UserManager {
enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
requiresAnyOfPermissionsIfNotCallerProfileGroup = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS}
)
android.Manifest.permission.QUERY_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS})
public boolean isManagedProfile() {
return isManagedProfile(getContextUserIfAppropriate());
}
@@ -2511,15 +2527,18 @@ public class UserManager {
/**
* Checks if the specified user is a managed profile.
* Requires {@link android.Manifest.permission#MANAGE_USERS} or
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission, otherwise the caller
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or
* {@link android.Manifest.permission#QUERY_USERS} permission, otherwise the caller
* must be in the same profile group of specified user.
*
* @return whether the specified user is a managed profile.
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
public boolean isManagedProfile(@UserIdInt int userId) {
if (userId == mUserId) {
// No need for synchronization. Once it becomes non-null, it'll be non-null forever.
@@ -2573,8 +2592,10 @@ public class UserManager {
* @return whether the context user is an ephemeral user.
* @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
@UserHandleAware
public boolean isEphemeralUser() {
return isUserEphemeral(mUserId);
@@ -2584,8 +2605,10 @@ public class UserManager {
* Returns whether the specified user is ephemeral.
* @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
public boolean isUserEphemeral(@UserIdInt int userId) {
final UserInfo user = getUserInfo(userId);
return user != null && user.isEphemeral();
@@ -2853,8 +2876,10 @@ public class UserManager {
* @hide
*/
@UnsupportedAppUsage
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
public UserInfo getUserInfo(@UserIdInt int userId) {
try {
return mService.getUserInfo(userId);
@@ -2877,7 +2902,9 @@ public class UserManager {
@Deprecated
@SystemApi
@UserRestrictionSource
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.QUERY_USERS})
public int getUserRestrictionSource(@UserRestrictionKey String restrictionKey,
UserHandle userHandle) {
try {
@@ -2896,7 +2923,9 @@ public class UserManager {
* @return a list of user ids enforcing this restriction.
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_USERS})
public List<EnforcingUser> getUserRestrictionSources(
@UserRestrictionKey String restrictionKey, UserHandle userHandle) {
try {
@@ -3963,15 +3992,17 @@ public class UserManager {
}
/**
* Checks whether it's possible to add more managed profiles. Caller must hold the MANAGE_USERS
* permission.
* Checks whether it's possible to add more managed profiles.
* if allowedToRemoveOne is true and if the user already has a managed profile, then return if
* we could add a new managed profile to this user after removing the existing one.
*
* @return true if more managed profiles can be added, false if limit has been reached.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_USERS
})
public boolean canAddMoreManagedProfiles(@UserIdInt int userId, boolean allowedToRemoveOne) {
try {
return mService.canAddMoreManagedProfiles(userId, allowedToRemoveOne);
@@ -3987,7 +4018,10 @@ public class UserManager {
* @return true if more profiles can be added, false if limit has been reached.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_USERS
})
public boolean canAddMoreProfilesToUser(@NonNull String userType, @UserIdInt int userId) {
try {
return mService.canAddMoreProfilesToUser(userType, userId, false);
@@ -4022,14 +4056,17 @@ public class UserManager {
* <p>Note that this includes all profile types (not including Restricted profiles).
*
* <p>Requires {@link android.Manifest.permission#MANAGE_USERS} or
* {@link android.Manifest.permission#CREATE_USERS} if userId is not the calling user.
* {@link android.Manifest.permission#CREATE_USERS} or
* {@link android.Manifest.permission#QUERY_USERS} if userId is not the calling user.
* @param userId profiles of this user will be returned.
* @return the list of profiles.
* @hide
*/
@UnsupportedAppUsage
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS}, conditional = true)
public List<UserInfo> getProfiles(@UserIdInt int userId) {
try {
return mService.getProfiles(userId, false /* enabledOnly */);
@@ -4048,7 +4085,9 @@ public class UserManager {
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_USERS})
public boolean isSameProfileGroup(@NonNull UserHandle user, @NonNull UserHandle otherUser) {
return isSameProfileGroup(user.getIdentifier(), otherUser.getIdentifier());
}
@@ -4060,7 +4099,9 @@ public class UserManager {
* @return true if the two user ids are in the same profile group.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_USERS})
public boolean isSameProfileGroup(@UserIdInt int userId, int otherUserId) {
try {
return mService.isSameProfileGroup(userId, otherUserId);
@@ -4075,14 +4116,20 @@ public class UserManager {
* <p>Note that this includes all profile types (not including Restricted profiles).
*
* <p>Requires {@link android.Manifest.permission#MANAGE_USERS} or
* {@link android.Manifest.permission#CREATE_USERS} if userId is not the calling user.
* {@link android.Manifest.permission#CREATE_USERS} or
* {@link android.Manifest.permission#QUERY_USERS} if userId is not the calling user.
* @param userId profiles of this user will be returned.
* @return the list of profiles.
* @deprecated use {@link #getUserProfiles()} instead.
*
* @hide
*/
@Deprecated
@UnsupportedAppUsage
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS}, conditional = true)
public List<UserInfo> getEnabledProfiles(@UserIdInt int userId) {
try {
return mService.getProfiles(userId, true /* enabledOnly */);
@@ -4102,8 +4149,8 @@ public class UserManager {
enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
requiresAnyOfPermissionsIfNotCaller = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}
)
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
public List<UserHandle> getUserProfiles() {
int[] userIds = getProfileIds(getContextUserIfAppropriate(), true /* enabledOnly */);
return convertUserIdsToUserHandles(userIds);
@@ -4118,9 +4165,11 @@ public class UserManager {
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
@UserHandleAware
@UserHandleAware(
requiresAnyOfPermissionsIfNotCaller = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
public @NonNull List<UserHandle> getEnabledProfiles() {
return getProfiles(true);
}
@@ -4134,9 +4183,11 @@ public class UserManager {
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
@UserHandleAware
@UserHandleAware(
requiresAnyOfPermissionsIfNotCaller = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
public @NonNull List<UserHandle> getAllProfiles() {
return getProfiles(false);
}
@@ -4149,9 +4200,11 @@ public class UserManager {
* @param enabledOnly whether to return only {@link UserInfo#isEnabled() enabled} profiles
* @return A non-empty list of UserHandles associated with the context user.
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
@UserHandleAware
@UserHandleAware(
requiresAnyOfPermissionsIfNotCaller = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS})
private @NonNull List<UserHandle> getProfiles(boolean enabledOnly) {
final int[] userIds = getProfileIds(mUserId, enabledOnly);
return convertUserIdsToUserHandles(userIds);
@@ -4177,8 +4230,10 @@ public class UserManager {
*
* @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS}, conditional = true)
public @NonNull int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) {
try {
return mService.getProfileIds(userId, enabledOnly);
@@ -4192,8 +4247,10 @@ public class UserManager {
* @hide
*/
@UnsupportedAppUsage
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS}, conditional = true)
public int[] getProfileIdsWithDisabled(@UserIdInt int userId) {
return getProfileIds(userId, false /* enabledOnly */);
}
@@ -4202,8 +4259,10 @@ public class UserManager {
* @see #getProfileIds(int, boolean)
* @hide
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS}, conditional = true)
public int[] getEnabledProfileIds(@UserIdInt int userId) {
return getProfileIds(userId, true /* enabledOnly */);
}

View File

@@ -2791,6 +2791,11 @@
<permission android:name="android.permission.CREATE_USERS"
android:protectionLevel="signature" />
<!-- @SystemApi @hide Allows an application to call APIs that allow it to query users on the
device. -->
<permission android:name="android.permission.QUERY_USERS"
android:protectionLevel="signature|role" />
<!-- Allows an application to access data blobs across users. -->
<permission android:name="android.permission.ACCESS_BLOBS_ACROSS_USERS"
android:protectionLevel="signature|privileged|development|role" />

View File

@@ -200,6 +200,7 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.CREATE_USERS" />
<uses-permission android:name="android.permission.QUERY_USERS" />
<uses-permission android:name="android.permission.CREATE_VIRTUAL_DEVICE" />
<uses-permission android:name="android.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />

View File

@@ -865,7 +865,7 @@ public class UserManagerService extends IUserManager.Stub {
public List<UserInfo> getProfiles(@UserIdInt int userId, boolean enabledOnly) {
boolean returnFullInfo;
if (userId != UserHandle.getCallingUserId()) {
checkManageOrCreateUsersPermission("getting profiles related to user " + userId);
checkQueryOrCreateUsersPermission("getting profiles related to user " + userId);
returnFullInfo = true;
} else {
returnFullInfo = hasManageOrCreateUsersPermission();
@@ -898,7 +898,7 @@ public class UserManagerService extends IUserManager.Stub {
public int[] getProfileIds(@UserIdInt int userId, @Nullable String userType,
boolean enabledOnly) {
if (userId != UserHandle.getCallingUserId()) {
checkManageOrCreateUsersPermission("getting profiles related to user " + userId);
checkQueryOrCreateUsersPermission("getting profiles related to user " + userId);
}
final long ident = Binder.clearCallingIdentity();
try {
@@ -987,7 +987,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public boolean isSameProfileGroup(@UserIdInt int userId, int otherUserId) {
if (userId == otherUserId) return true;
checkManageUsersPermission("check if in the same profile group");
checkQueryUsersPermission("check if in the same profile group");
return isSameProfileGroupNoChecks(userId, otherUserId);
}
@@ -1388,7 +1388,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public UserInfo getUserInfo(@UserIdInt int userId) {
checkManageOrCreateUsersPermission("query user");
checkQueryOrCreateUsersPermission("query user");
synchronized (mUsersLock) {
return userWithName(getUserInfoLU(userId));
}
@@ -1519,7 +1519,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public boolean isProfile(@UserIdInt int userId) {
checkManageOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isProfile");
checkQueryOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isProfile");
synchronized (mUsersLock) {
UserInfo userInfo = getUserInfoLU(userId);
return userInfo != null && userInfo.isProfile();
@@ -1528,7 +1528,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public boolean isManagedProfile(@UserIdInt int userId) {
checkManageOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isManagedProfile");
checkQueryOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isManagedProfile");
synchronized (mUsersLock) {
UserInfo userInfo = getUserInfoLU(userId);
return userInfo != null && userInfo.isManagedProfile();
@@ -1592,7 +1592,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public String getUserName() {
final int callingUid = Binder.getCallingUid();
if (!hasManageOrCreateUsersPermission()
if (!hasQueryOrCreateUsersPermission()
&& !hasPermissionGranted(
android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED, callingUid)) {
throw new SecurityException("You need MANAGE_USERS or CREATE_USERS or "
@@ -1628,18 +1628,59 @@ public class UserManagerService extends IUserManager.Stub {
}
}
/**
* Enforces that the calling user is in the same profile group as {@code userId} or that only
* the system UID or root's UID or apps that have the
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS INTERACT_ACROSS_USERS}
* {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
* can make certain calls to the UserManager.
*
* @param name used as message if SecurityException is thrown
* @throws SecurityException if the caller lacks the required permissions.
*/
private void checkManageOrInteractPermissionIfCallerInOtherProfileGroup(@UserIdInt int userId,
String name) {
final int callingUserId = UserHandle.getCallingUserId();
if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId) ||
hasManageUsersPermission()) {
if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId)) {
return;
}
if (!hasPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS,
Binder.getCallingUid())) {
throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS permission "
+ "to: check " + name);
if (hasManageUsersPermission()) {
return;
}
if (hasPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS,
Binder.getCallingUid())) {
return;
}
throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS permission "
+ "to: check " + name);
}
/**
* Enforces that the calling user is in the same profile group as {@code userId} or that only
* the system UID or root's UID or apps that have the
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS INTERACT_ACROSS_USERS}
* {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
* {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}
* can make certain calls to the UserManager.
*
* @param name used as message if SecurityException is thrown
* @throws SecurityException if the caller lacks the required permissions.
*/
private void checkQueryOrInteractPermissionIfCallerInOtherProfileGroup(
@UserIdInt int userId, String name) {
final int callingUserId = UserHandle.getCallingUserId();
if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId)) {
return;
}
if (hasQueryUsersPermission()) {
return;
}
if (hasPermissionGranted(
Manifest.permission.INTERACT_ACROSS_USERS, Binder.getCallingUid())) {
return;
}
throw new SecurityException("You need INTERACT_ACROSS_USERS, MANAGE_USERS, or QUERY_USERS "
+ "permission to: check " + name);
}
@Override
@@ -2147,7 +2188,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public List<EnforcingUser> getUserRestrictionSources(
String restrictionKey, @UserIdInt int userId) {
checkManageUsersPermission("getUserRestrictionSource");
checkQueryUsersPermission("call getUserRestrictionSources.");
// Shortcut for the most common case
if (!hasUserRestriction(restrictionKey, userId)) {
@@ -2426,7 +2467,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public boolean canAddMoreProfilesToUser(String userType, @UserIdInt int userId,
boolean allowedToRemoveOne) {
checkManageUsersPermission("check if more profiles can be added.");
checkQueryUsersPermission("check if more profiles can be added.");
final UserTypeDetails type = mUserTypes.get(userType);
if (type == null || !type.isEnabled()) {
return false;
@@ -2545,6 +2586,40 @@ public class UserManagerService extends IUserManager.Stub {
}
}
/**
* Enforces that only the system UID or root's UID or apps that have the
* {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
* {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}
* can make certain calls to the UserManager.
*
* @param message used as message if SecurityException is thrown
* @throws SecurityException if the caller lacks the required permissions.
*/
private static final void checkQueryUsersPermission(String message) {
if (!hasQueryUsersPermission()) {
throw new SecurityException(
"You either need MANAGE_USERS or QUERY_USERS permission to: " + message);
}
}
/**
* Enforces that only the system UID or root's UID or apps that have the
* {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
* {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} or
* {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}
* can make certain calls to the UserManager.
*
* @param message used as message if SecurityException is thrown
* @throws SecurityException if the caller lacks the required permissions.
*/
private static final void checkQueryOrCreateUsersPermission(String message) {
if (!hasQueryOrCreateUsersPermission()) {
throw new SecurityException(
"You either need MANAGE_USERS, CREATE_USERS, or QUERY_USERS permission to: "
+ message);
}
}
/**
* Similar to {@link #checkManageOrCreateUsersPermission(String)} but when the caller is tries
* to create user/profiles other than what is allowed for
@@ -2601,6 +2676,26 @@ public class UserManagerService extends IUserManager.Stub {
return hasManageUsersOrPermission(android.Manifest.permission.CREATE_USERS);
}
/**
* @return whether the calling UID is system UID or root's UID or the calling app has the
* {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
* {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}.
*/
private static final boolean hasQueryUsersPermission() {
return hasManageUsersOrPermission(android.Manifest.permission.QUERY_USERS);
}
/**
* @return whether the calling UID is system UID or root's UID or the calling app has
* {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
* {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} or
* {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}.
*/
private static final boolean hasQueryOrCreateUsersPermission() {
return hasManageOrCreateUsersPermission()
|| hasPermissionGranted(Manifest.permission.QUERY_USERS, Binder.getCallingUid());
}
/**
* Enforces that only the system UID or root's UID (on any user) can make certain calls to the
* UserManager.