Add isMainUser system API.
This adds an API to determine if the context user is the designated main user on the device. This user may have access to features which are limited to a single user on the device. In Android U, this will be the first user to go through setup. On regular devices, this will be the system user, but on devices in No Primary User / Headless System User Mode, it will be a different user. The isPrimaryUser System API is confusing because it actually always returns the system user, even in headless mode. That API is deprecated in this change. On devices that are upgrading, if they are non-headless, the system user will be the main user. If they are headless, the full user with the earliest creation date will be given the flag. Bug: 256624031 Test: atest UserManagerTest Change-Id: Ib36f3b372f9bf33cbb097c4af63eb43515ac835b
This commit is contained in:
@@ -9968,9 +9968,10 @@ package android.os {
|
||||
method public boolean isCloneProfile();
|
||||
method public boolean isCredentialSharableWithParent();
|
||||
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.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isMainUser();
|
||||
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 public boolean isMediaSharedWithParent();
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
|
||||
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
|
||||
method public static boolean isRemoveResultSuccessful(int);
|
||||
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);
|
||||
|
||||
@@ -904,6 +904,7 @@ package android.content.pm {
|
||||
method public boolean isFull();
|
||||
method public boolean isGuest();
|
||||
method public boolean isInitialized();
|
||||
method public boolean isMain();
|
||||
method public boolean isManagedProfile();
|
||||
method public boolean isPrimary();
|
||||
method public boolean isProfile();
|
||||
@@ -922,6 +923,7 @@ package android.content.pm {
|
||||
field public static final int FLAG_FULL = 1024; // 0x400
|
||||
field @Deprecated public static final int FLAG_GUEST = 4; // 0x4
|
||||
field public static final int FLAG_INITIALIZED = 16; // 0x10
|
||||
field public static final int FLAG_MAIN = 16384; // 0x4000
|
||||
field @Deprecated public static final int FLAG_MANAGED_PROFILE = 32; // 0x20
|
||||
field public static final int FLAG_PRIMARY = 1; // 0x1
|
||||
field public static final int FLAG_PROFILE = 4096; // 0x1000
|
||||
|
||||
@@ -158,6 +158,18 @@ public class UserInfo implements Parcelable {
|
||||
*/
|
||||
public static final int FLAG_EPHEMERAL_ON_CREATE = 0x00002000;
|
||||
|
||||
/**
|
||||
* Indicates that this user is the designated main user on the device. This user may have access
|
||||
* to certain features which are limited to at most one user.
|
||||
*
|
||||
* <p>Currently, this will be the first user to go through setup on the device, but in future
|
||||
* releases this status may be transferable or may even not be given to any users.
|
||||
*
|
||||
* <p>This is not necessarily the system user. For example, it will not be the system user on
|
||||
* devices for which {@link UserManager#isHeadlessSystemUserMode()} returns true.
|
||||
*/
|
||||
public static final int FLAG_MAIN = 0x00004000;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -175,7 +187,8 @@ public class UserInfo implements Parcelable {
|
||||
FLAG_FULL,
|
||||
FLAG_SYSTEM,
|
||||
FLAG_PROFILE,
|
||||
FLAG_EPHEMERAL_ON_CREATE
|
||||
FLAG_EPHEMERAL_ON_CREATE,
|
||||
FLAG_MAIN
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface UserInfoFlag {
|
||||
@@ -368,6 +381,13 @@ public class UserInfo implements Parcelable {
|
||||
return (flags & FLAG_FULL) == FLAG_FULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #FLAG_MAIN
|
||||
*/
|
||||
public boolean isMain() {
|
||||
return (flags & FLAG_MAIN) == FLAG_MAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the user is a split system user.
|
||||
* <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
|
||||
|
||||
@@ -2306,12 +2306,18 @@ public class UserManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if the context user is the primary user. The primary user
|
||||
* is the first human user on a device. This is not supported in headless system user mode.
|
||||
* Used to check if the context user is the primary user. The primary user is the first human
|
||||
* user on a device. This is not supported in headless system user mode.
|
||||
*
|
||||
* @return whether the context user is the primary user.
|
||||
*
|
||||
* @deprecated This method always returns true for the system user, who may not be a full user
|
||||
* if {@link #isHeadlessSystemUserMode} is true. Use {@link #isSystemUser}, {@link #isAdminUser}
|
||||
* or {@link #isMainUser} instead.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
@SystemApi
|
||||
@RequiresPermission(anyOf = {
|
||||
Manifest.permission.MANAGE_USERS,
|
||||
@@ -2335,6 +2341,29 @@ public class UserManager {
|
||||
return getContextUserIfAppropriate() == UserHandle.USER_SYSTEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <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>Note that this will be the not be the system user on devices for which
|
||||
* {@link #isHeadlessSystemUserMode()} returns true.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(anyOf = {
|
||||
Manifest.permission.MANAGE_USERS,
|
||||
Manifest.permission.CREATE_USERS,
|
||||
Manifest.permission.QUERY_USERS})
|
||||
@UserHandleAware
|
||||
public boolean isMainUser() {
|
||||
final UserInfo user = getUserInfo(mUserId);
|
||||
return user != null && user.isMain();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
|
||||
@@ -261,7 +261,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
@VisibleForTesting
|
||||
static final int MAX_RECENTLY_REMOVED_IDS_SIZE = 100;
|
||||
|
||||
private static final int USER_VERSION = 10;
|
||||
private static final int USER_VERSION = 11;
|
||||
|
||||
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
|
||||
|
||||
@@ -3330,6 +3330,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
final int oldFlags = systemUserData.info.flags;
|
||||
final int newFlags;
|
||||
final String newUserType;
|
||||
// TODO(b/256624031): Also handle FLAG_MAIN
|
||||
if (newHeadlessSystemUserMode) {
|
||||
newUserType = UserManager.USER_TYPE_SYSTEM_HEADLESS;
|
||||
newFlags = oldFlags & ~UserInfo.FLAG_FULL;
|
||||
@@ -3622,6 +3623,22 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
userVersion = 10;
|
||||
}
|
||||
|
||||
if (userVersion < 11) {
|
||||
// Add FLAG_MAIN
|
||||
if (isHeadlessSystemUserMode()) {
|
||||
final UserInfo earliestCreatedUser = getEarliestCreatedFullUser();
|
||||
earliestCreatedUser.flags |= UserInfo.FLAG_MAIN;
|
||||
userIdsToWrite.add(earliestCreatedUser.id);
|
||||
} else {
|
||||
synchronized (mUsersLock) {
|
||||
final UserData userData = mUsers.get(UserHandle.USER_SYSTEM);
|
||||
userData.info.flags |= UserInfo.FLAG_MAIN;
|
||||
userIdsToWrite.add(userData.info.id);
|
||||
}
|
||||
}
|
||||
userVersion = 11;
|
||||
}
|
||||
|
||||
// Reminder: If you add another upgrade, make sure to increment USER_VERSION too.
|
||||
|
||||
// Done with userVersion changes, moving on to deal with userTypeVersion upgrades
|
||||
@@ -3751,6 +3768,21 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
|
||||
}
|
||||
|
||||
private UserInfo getEarliestCreatedFullUser() {
|
||||
final List<UserInfo> users = getUsersInternal(true, true, true);
|
||||
UserInfo earliestUser = users.get(0);
|
||||
long earliestCreationTime = earliestUser.creationTime;
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
final UserInfo info = users.get(i);
|
||||
if (info.isFull() && info.creationTime > 0
|
||||
&& info.creationTime < earliestCreationTime) {
|
||||
earliestCreationTime = info.creationTime;
|
||||
earliestUser = info;
|
||||
}
|
||||
}
|
||||
return earliestUser;
|
||||
}
|
||||
|
||||
@GuardedBy({"mPackagesLock"})
|
||||
private void fallbackToSingleUserLP() {
|
||||
int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
|
||||
|
||||
@@ -260,7 +260,8 @@ public final class UserTypeFactory {
|
||||
private static UserTypeDetails.Builder getDefaultTypeFullSystem() {
|
||||
return new UserTypeDetails.Builder()
|
||||
.setName(USER_TYPE_FULL_SYSTEM)
|
||||
.setBaseType(FLAG_SYSTEM | FLAG_FULL);
|
||||
.setBaseType(FLAG_SYSTEM | FLAG_FULL)
|
||||
.setDefaultUserInfoPropertyFlags(UserInfo.FLAG_MAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,9 +83,10 @@ final class BootUserInitializer {
|
||||
Slogf.d(TAG, "Creating initial user");
|
||||
t.traceBegin("create-initial-user");
|
||||
try {
|
||||
int flags = UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN;
|
||||
// TODO(b/204091126): proper name for user
|
||||
UserInfo newUser = um.createUserEvenWhenDisallowed("Real User",
|
||||
UserManager.USER_TYPE_FULL_SECONDARY, UserInfo.FLAG_ADMIN,
|
||||
UserManager.USER_TYPE_FULL_SECONDARY, flags,
|
||||
/* disallowedPackages= */ null, /* token= */ null);
|
||||
Slogf.i(TAG, "Created initial user: %s", newUser.toFullString());
|
||||
initialUserId = newUser.id;
|
||||
|
||||
Reference in New Issue
Block a user