From 4fcb05c5ebb9e4f34534d15fea1ccf0f50aec218 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Fri, 19 Aug 2022 17:37:34 +0000 Subject: [PATCH] New @SystemApi: UserManager.getVisibleUsers() Test: atest CtsMultiUserTestCases:android.multiuser.cts.UserManagerTest Test: m update-api Fixes: 242801948 Change-Id: I5ca52e6705662b7e3939101890bb81345a5a831e --- core/api/current.txt | 1 + core/java/android/os/IUserManager.aidl | 1 + core/java/android/os/UserManager.java | 15 ++++++++++ .../android/server/pm/UserManagerService.java | 28 ++++++++++++++++++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/core/api/current.txt b/core/api/current.txt index 9ebd11888822e..39cc31bc4eebd 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -32267,6 +32267,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 62ee408cffbfc..5e6442058ca80 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -128,6 +128,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 ef04f641b0eee..9c919a3af82ab 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -2884,6 +2884,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 025e97318ba90..c4107233d8836 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -910,7 +910,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; @@ -1765,6 +1765,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();