diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 802e61403fc39..8887686d5d40b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -10042,6 +10042,7 @@ package android.os { 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 public java.util.List getAllProfiles(); method @NonNull public java.util.List getEnabledProfiles(); + method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public android.os.UserHandle getMainUser(); 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 @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public int getRemainingCreatableProfileCount(@NonNull String); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public int getRemainingCreatableUserCount(@NonNull String); diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index a887f2a6ef29d..eae7ce06008c7 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -58,6 +58,7 @@ interface IUserManager { void setUserIcon(int userId, in Bitmap icon); ParcelFileDescriptor getUserIcon(int userId); UserInfo getPrimaryUser(); + int getMainUserId(); List getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated); List getProfiles(int userId, boolean enabledOnly); int[] getProfileIds(int userId, boolean enabledOnly); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 1f21bfe6cd729..954d1fca4ce07 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -2377,14 +2377,16 @@ public class UserManager { } /** - * Returns true if the context user is the designated "main user" of the device. This user may - * have access to certain features which are limited to at most one user. + * Returns {@code true} if the context user is the designated "main user" of the device. This + * user may have access to certain features which are limited to at most one user. There will + * never be more than one main user on a device. * - *

Currently, the first human user on the device will be the main user; in the future, the - * concept may be transferable, so a different user (or even no user at all) may be designated - * the main user instead. + *

Currently, on most form factors the first human user on the device will be the main user; + * in the future, the concept may be transferable, so a different user (or even no user at all) + * may be designated the main user instead. On other form factors there might not be a main + * user. * - *

Note that this will be the not be the system user on devices for which + *

Note that this will not be the system user on devices for which * {@link #isHeadlessSystemUserMode()} returns true. * @hide */ @@ -2399,6 +2401,29 @@ public class UserManager { return user != null && user.isMain(); } + /** + * Returns the designated "main user" of the device, or {@code null} if there is no main user. + * + * @see #isMainUser() + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + Manifest.permission.MANAGE_USERS, + Manifest.permission.CREATE_USERS, + Manifest.permission.QUERY_USERS}) + public @Nullable UserHandle getMainUser() { + try { + final int mainUserId = mService.getMainUserId(); + if (mainUserId == UserHandle.USER_NULL) { + return null; + } + return UserHandle.of(mainUserId); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + /** * Used to check if the context user is an admin user. An admin user is allowed to * modify or configure certain settings that aren't available to non-admin users, diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java index 1027f4c031277..df132a97418a0 100644 --- a/services/core/java/com/android/server/pm/UserManagerInternal.java +++ b/services/core/java/com/android/server/pm/UserManagerInternal.java @@ -441,4 +441,12 @@ public abstract class UserManagerInternal { /** Return the integer types of the given user IDs. Only used for reporting metrics to statsd. */ public abstract int[] getUserTypesForStatsd(@UserIdInt int[] userIds); + + /** + * Returns the user id of the main user, or {@link android.os.UserHandle#USER_NULL} if there is + * no main user. + * + * @see UserManager#isMainUser() + */ + public abstract @UserIdInt int getMainUserId(); } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 88e12fa9a6045..c8dffedfd1419 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -901,6 +901,25 @@ public class UserManagerService extends IUserManager.Stub { return null; } + @Override + public @UserIdInt int getMainUserId() { + checkQueryOrCreateUsersPermission("get main user id"); + return getMainUserIdUnchecked(); + } + + private @UserIdInt int getMainUserIdUnchecked() { + synchronized (mUsersLock) { + final int userSize = mUsers.size(); + for (int i = 0; i < userSize; i++) { + final UserInfo user = mUsers.valueAt(i).info; + if (user.isMain() && !mRemovingUserIds.get(user.id)) { + return user.id; + } + } + } + return UserHandle.USER_NULL; + } + public @NonNull List getUsers(boolean excludeDying) { return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */ true); @@ -6898,6 +6917,12 @@ public class UserManagerService extends IUserManager.Stub { } return userTypes; } + + @Override + public @UserIdInt int getMainUserId() { + return getMainUserIdUnchecked(); + } + } // class LocalService