Add QUERY_USERS permission to some UserManager APIs

The followings APIs now accept QUERY_USERS
(and any other APIs that depends on them):

* getUserRestrictionSources
* isSameProfileGroup
* getAllProfiles
* isManagedProfile
* canAddMoreManagedProfiles

Also exposed isProfile as public, and deprecated getEnabledProfiles

Test: atest android.multiuser.cts.UserManagerTest
Bug: 188410712
Bug: 205707885
Bug: 206106797
Change-Id: I4cc4f7078271e42a2bcaa6965c107a6e249e00fc
This commit is contained in:
kholoud mohamed
2021-11-10 18:38:46 +00:00
committed by Kholoud Mohamed
parent d0fe35e8b4
commit 2d7bded79d
5 changed files with 249 additions and 95 deletions

View File

@@ -32477,7 +32477,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

@@ -9018,31 +9018,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

@@ -1823,7 +1823,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

@@ -2034,7 +2034,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);
@@ -2043,15 +2044,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 {
@@ -2114,8 +2121,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());
@@ -2145,7 +2154,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());
@@ -2157,8 +2167,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();
@@ -2355,8 +2367,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);
@@ -2373,8 +2387,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();
@@ -2387,8 +2403,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());
@@ -2417,17 +2435,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);
}
@@ -2463,8 +2479,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());
}
@@ -2472,15 +2488,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.
@@ -2534,8 +2553,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);
@@ -2545,8 +2566,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();
@@ -2814,8 +2837,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);
@@ -2838,7 +2863,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 {
@@ -2857,7 +2884,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 {
@@ -3924,15 +3953,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);
@@ -3948,7 +3979,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);
@@ -3983,14 +4017,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 */);
@@ -4009,7 +4046,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());
}
@@ -4021,7 +4060,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);
@@ -4036,14 +4077,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 */);
@@ -4063,8 +4110,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);
@@ -4079,9 +4126,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);
}
@@ -4095,9 +4144,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);
}
@@ -4110,9 +4161,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);
@@ -4138,8 +4191,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);
@@ -4153,8 +4208,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 */);
}
@@ -4163,8 +4220,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

@@ -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.