OTA only adds Main if isMainUserPermanentAdmin

On OTA to Android U, we bestow upon one user the MainUser title. Not all
devices need to have a MainUser though, depnding on their configuration.
Nonetheless, we were previously always adding MainUser on OTA.

For HSUM devices that do NOT have config_isMainUserPermanentAdmin, we should
not be setting a MainUser on OTA, so we fix this here.

On non-HSUM, we continue to make user 0 the MainUser on OTA regardless
of configuration; non-HSUM user 0 being Main is just an invariant.

Moreover, we update the emulation logic to also take into account
config_isMainUserPermanentAdmin and the invariance.
The updated logic of emulation is:

non-HSUM -> emulate HSUM
Rule: in HSUM, we never have Sys be Main. We set a new main iff the config says to.
Scenarios:
* if main=Sys (usual phone case): Remove Main from system; if isMainUserPermanentAdmin(), switch/set a new Main.
* if no main (severly aberrant case): if isMainUserPermanentAdmin(), set a new Main.
* if main=other (aberrant case): leave as is

HSUM -> emulate non-HSUM
Rule: in non-HSUM, we always make Sys to be Main
Scenarios:
* if main=Sys (severely aberrant case): leave as is
* if no main (usual for Auto):  always make Sys the Main
* if main=other (usual for tablet): always switch Main to system

Test: manual OTA from T to U
Test: manual emulate different modes
Bug: 272295293
Change-Id: Id915203fe07b65cdd0e7e08df92fe93454be4f6f
This commit is contained in:
Adam Bookatz
2023-03-08 13:34:17 -08:00
parent 3521df06db
commit bd1e947f2f
2 changed files with 22 additions and 18 deletions

View File

@@ -3473,15 +3473,15 @@ public class UserManagerService extends IUserManager.Stub {
return;
}
final int oldMainUserId = getMainUserIdUnchecked();
final int oldFlags = systemUserData.info.flags;
final int newFlags;
final int oldSysFlags = systemUserData.info.flags;
final int newSysFlags;
final String newUserType;
if (newHeadlessSystemUserMode) {
newUserType = UserManager.USER_TYPE_SYSTEM_HEADLESS;
newFlags = oldFlags & ~UserInfo.FLAG_FULL & ~UserInfo.FLAG_MAIN;
newSysFlags = oldSysFlags & ~UserInfo.FLAG_FULL & ~UserInfo.FLAG_MAIN;
} else {
newUserType = UserManager.USER_TYPE_FULL_SYSTEM;
newFlags = oldFlags | UserInfo.FLAG_FULL;
newSysFlags = oldSysFlags | UserInfo.FLAG_FULL | UserInfo.FLAG_MAIN;
}
if (systemUserData.info.userType.equals(newUserType)) {
@@ -3492,18 +3492,19 @@ public class UserManagerService extends IUserManager.Stub {
Slogf.i(LOG_TAG, "Persisting emulated system user data: type changed from %s to "
+ "%s, flags changed from %s to %s",
systemUserData.info.userType, newUserType,
UserInfo.flagsToString(oldFlags), UserInfo.flagsToString(newFlags));
UserInfo.flagsToString(oldSysFlags), UserInfo.flagsToString(newSysFlags));
systemUserData.info.userType = newUserType;
systemUserData.info.flags = newFlags;
systemUserData.info.flags = newSysFlags;
writeUserLP(systemUserData);
// Switch the MainUser to a reasonable choice if needed.
// (But if there was no MainUser, we deliberately continue to have no MainUser.)
// Designate the MainUser to a reasonable choice if needed.
final UserData oldMain = getUserDataNoChecks(oldMainUserId);
if (newHeadlessSystemUserMode) {
if (oldMain != null && (oldMain.info.flags & UserInfo.FLAG_SYSTEM) != 0) {
// System was MainUser. So we need a new choice for Main. Pick the oldest.
final boolean mainIsAlreadyNonSystem =
oldMain != null && (oldMain.info.flags & UserInfo.FLAG_SYSTEM) == 0;
if (!mainIsAlreadyNonSystem && isMainUserPermanentAdmin()) {
// We need a new choice for Main. Pick the oldest.
// If no oldest, don't set any. Let the BootUserInitializer do that later.
final UserInfo newMainUser = getEarliestCreatedFullUser();
if (newMainUser != null) {
@@ -3513,16 +3514,16 @@ public class UserManagerService extends IUserManager.Stub {
}
}
} else {
// We already made user 0 Main above. Now strip it from the old Main user.
// TODO(b/256624031): For now, we demand the Main user (if there is one) is
// always the system in non-HSUM. In the future, when we relax this, change how
// we handle MAIN.
if (oldMain != null && (oldMain.info.flags & UserInfo.FLAG_SYSTEM) == 0) {
// Someone else was the MainUser; transfer it to System.
Slogf.i(LOG_TAG, "Transferring Main to user 0 from " + oldMain.info.id);
oldMain.info.flags &= ~UserInfo.FLAG_MAIN;
systemUserData.info.flags |= UserInfo.FLAG_MAIN;
writeUserLP(oldMain);
writeUserLP(systemUserData);
} else {
Slogf.i(LOG_TAG, "Designated user 0 to be Main");
}
}
}
@@ -3779,12 +3780,14 @@ public class UserManagerService extends IUserManager.Stub {
if (userVersion < 11) {
// Add FLAG_MAIN
if (isHeadlessSystemUserMode()) {
final UserInfo earliestCreatedUser = getEarliestCreatedFullUser();
if (earliestCreatedUser != null) {
earliestCreatedUser.flags |= UserInfo.FLAG_MAIN;
userIdsToWrite.add(earliestCreatedUser.id);
if (isMainUserPermanentAdmin()) {
final UserInfo earliestCreatedUser = getEarliestCreatedFullUser();
if (earliestCreatedUser != null) {
earliestCreatedUser.flags |= UserInfo.FLAG_MAIN;
userIdsToWrite.add(earliestCreatedUser.id);
}
}
} else {
} else { // not isHeadlessSystemUserMode
synchronized (mUsersLock) {
final UserData userData = mUsers.get(UserHandle.USER_SYSTEM);
userData.info.flags |= UserInfo.FLAG_MAIN;

View File

@@ -376,6 +376,7 @@ public class UserManagerServiceShellCommand extends ShellCommand {
final int pid = Process.myPid();
Slogf.i(LOG_TAG, "Restarting Android runtime(PID=%d) to finalize changes", pid);
pw.println("Restarting Android runtime to finalize changes");
pw.println("The restart may trigger a 'Broken pipe' message; this is to be expected.");
pw.flush();
// Ideally there should be a cleaner / safer option to restart system_server, but