Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d38aca0 authored by Oli Lan's avatar Oli Lan
Browse files

Add a system API to get the main user.

This adds a system API to get the designated main user on the device.

The documentation for the existing isMainUser API is updated to make
clear that a main user might not exist on the device, particular for
non-phone/tablet form factors, but there will always be at most one
main user.

The CTS tests for isMainUser are updated to reflect that documentation,
and to no longer enforce that the main user is the first user on the
device

Bug: 259476886
Bug: 256624031
Test: atest UserManagerTest
Change-Id: Id1739b188d7c1c0f9006bc473de35a88d09cad95
parent f7d1c837
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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<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.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);
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ interface IUserManager {
    void setUserIcon(int userId, in Bitmap icon);
    ParcelFileDescriptor getUserIcon(int userId);
    UserInfo getPrimaryUser();
    int getMainUserId();
    List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
    List<UserInfo> getProfiles(int userId, boolean enabledOnly);
    int[] getProfileIds(int userId, boolean enabledOnly);
+31 −6
Original line number Diff line number Diff line
@@ -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.
     *
     * <p>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.
     * <p>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.
     *
     * <p>Note that this will be the not be the system user on devices for which
     * <p>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,
+8 −0
Original line number Diff line number Diff line
@@ -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();
}
+25 −0
Original line number Diff line number Diff line
@@ -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<UserInfo> 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