diff --git a/core/api/current.txt b/core/api/current.txt index 5f7e33093c08b..868ab317aecc7 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -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 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); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 1437ab6af7043..142aff6088c2d 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -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) 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 getAllProfiles(); - method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List getEnabledProfiles(); + method @NonNull public java.util.List getAllProfiles(); + method @NonNull public java.util.List 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 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 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 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); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index fee4ed85cf4d8..fbfcc81684121 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -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 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 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(); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index bc6dbd8c098f0..1d54c05b62122 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -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 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 { *

Note that this includes all profile types (not including Restricted profiles). * *

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 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 { *

Note that this includes all profile types (not including Restricted profiles). * *

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 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 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 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 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 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 */); } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index bc4c8b058f7e7..f6895195781c3 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -865,7 +865,7 @@ public class UserManagerService extends IUserManager.Stub { public List 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 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.