diff --git a/core/api/current.txt b/core/api/current.txt index 795c43056d041..317f8eb5c6b5e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -32264,6 +32264,7 @@ package android.os { method @NonNull @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.QUERY_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.content.pm.UserProperties getUserProperties(@NonNull android.os.UserHandle); 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); + method @NonNull @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}) public java.util.List getVisibleUsers(); method public boolean hasUserRestriction(String); method public boolean isDemoUser(); method public static boolean isHeadlessSystemUserMode(); diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index fa6b1189f1da4..88649cbf9e425 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -129,6 +129,7 @@ interface IUserManager { boolean isUserRunning(int userId); boolean isUserForeground(int userId); boolean isUserVisible(int userId); + List getVisibleUsers(); boolean isUserNameSet(int userId); boolean hasRestrictedProfiles(int userId); boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userId, in IntentSender target, int flags); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 738f9c9c4f138..f6aaee8e3de0b 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -2885,6 +2885,21 @@ public class UserManager { } } + /** + * Gets the visible users (as defined by {@link #isUserVisible()}. + * + * @return visible users at the moment. + */ + @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, + Manifest.permission.INTERACT_ACROSS_USERS}) + public @NonNull List getVisibleUsers() { + try { + return mService.getVisibleUsers(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + /** * Return whether the context user is running in an "unlocked" state. *

diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index e423ea9170d71..672c13c2dbf9d 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -911,7 +911,7 @@ public class UserManagerService extends IUserManager.Stub { private @NonNull List getUsersInternal(boolean excludePartial, boolean excludeDying, boolean excludePreCreated) { synchronized (mUsersLock) { - ArrayList users = new ArrayList(mUsers.size()); + ArrayList users = new ArrayList<>(mUsers.size()); final int userSize = mUsers.size(); for (int i = 0; i < userSize; i++) { UserInfo ui = mUsers.valueAt(i).info; @@ -1766,6 +1766,32 @@ public class UserManagerService extends IUserManager.Stub { } } + @Override + public List getVisibleUsers() { + if (!hasManageUsersOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)) { + throw new SecurityException("Caller needs MANAGE_USERS or INTERACT_ACROSS_USERS " + + "permission to get list of visible users"); + } + final long ident = Binder.clearCallingIdentity(); + try { + // TODO(b/2399825580): refactor into UserDisplayAssigner + synchronized (mUsersLock) { + int usersSize = mUsers.size(); + ArrayList visibleUsers = new ArrayList<>(usersSize); + for (int i = 0; i < usersSize; i++) { + UserInfo ui = mUsers.valueAt(i).info; + if (!ui.partial && !ui.preCreated && !mRemovingUserIds.get(ui.id) + && isUserVisibleUnchecked(ui.id)) { + visibleUsers.add(UserHandle.of(ui.id)); + } + } + return visibleUsers; + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + @Override public @NonNull String getUserName() { final int callingUid = Binder.getCallingUid();