Merge "Changing hsum property in OTA won't alter mode"

This commit is contained in:
TreeHugger Robot
2022-11-02 21:01:25 +00:00
committed by Android (Google) Code Review
4 changed files with 73 additions and 52 deletions

View File

@@ -69,6 +69,7 @@ interface IUserManager {
boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne);
UserInfo getProfileParent(int userId);
boolean isSameProfileGroup(int userId, int otherUserHandle);
boolean isHeadlessSystemUserMode();
boolean isUserOfType(int userId, in String userType);
@UnsupportedAppUsage
UserInfo getUserInfo(int userId);

View File

@@ -91,7 +91,6 @@ import java.util.Set;
public class UserManager {
private static final String TAG = "UserManager";
private static final boolean VERBOSE = false;
@UnsupportedAppUsage
private final IUserManager mService;
@@ -104,6 +103,9 @@ public class UserManager {
/** The userType of UserHandle.myUserId(); empty string if not a profile; null until cached. */
private String mProfileTypeOfProcessUser = null;
/** Whether the device is in headless system user mode; null until cached. */
private static Boolean sIsHeadlessSystemUser = null;
/**
* User type representing a {@link UserHandle#USER_SYSTEM system} user that is a human user.
* This type of user cannot be created; it can only pre-exist on first boot.
@@ -2068,28 +2070,20 @@ public class UserManager {
* @return whether the device is running in a headless system user mode.
*/
public static boolean isHeadlessSystemUserMode() {
final boolean realMode = RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER;
if (!Build.isDebuggable()) {
return realMode;
}
final String emulatedMode = SystemProperties.get(SYSTEM_USER_MODE_EMULATION_PROPERTY);
switch (emulatedMode) {
case SYSTEM_USER_MODE_EMULATION_FULL:
if (VERBOSE) Log.v(TAG, "isHeadlessSystemUserMode(): emulating as false");
return false;
case SYSTEM_USER_MODE_EMULATION_HEADLESS:
if (VERBOSE) Log.v(TAG, "isHeadlessSystemUserMode(): emulating as true");
return true;
case SYSTEM_USER_MODE_EMULATION_DEFAULT:
case "": // property not set
return realMode;
default:
Log.wtf(TAG, "isHeadlessSystemUserMode(): invalid value of property "
+ SYSTEM_USER_MODE_EMULATION_PROPERTY + " (" + emulatedMode + "); using"
+ " default value (headless=" + realMode + ")");
return realMode;
// No need for synchronization. Once it becomes non-null, it'll be non-null forever.
// (Its value is determined when UMS is constructed and cannot change.)
// Worst case we might end up calling the AIDL method multiple times but that's fine.
if (sIsHeadlessSystemUser == null) {
// Unfortunately this API is static, but the property no longer is. So go fetch the UMS.
try {
final IUserManager service = IUserManager.Stub.asInterface(
ServiceManager.getService(Context.USER_SERVICE));
sIsHeadlessSystemUser = service.isHeadlessSystemUserMode();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
return sIsHeadlessSystemUser;
}
/**

View File

@@ -51,6 +51,15 @@ public class RoSystemProperties {
// ------ ro.fw.* ------------ //
public static final boolean FW_SYSTEM_USER_SPLIT =
SystemProperties.getBoolean("ro.fw.system_user_split", false);
/**
* Indicates whether the device should run in headless system user mode,
* in which user 0 only runs the system, not a real user.
* <p>WARNING about changing this value during an non-wiping update (OTA):
* <li>If this value is modified via an update, the change will have no effect, since an
* already-existing system user cannot change its mode.
* <li>Changing this value during an OTA from a pre-R device is not permitted; attempting to
* do so will corrupt the system user.
*/
public static final boolean MULTIUSER_HEADLESS_SYSTEM_USER =
SystemProperties.getBoolean("ro.fw.mu.headless_system_user", false);

View File

@@ -19,6 +19,7 @@ package com.android.server.pm;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.UserManager.DISALLOW_USER_SWITCH;
import static android.os.UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY;
import android.Manifest;
import android.accounts.Account;
@@ -314,7 +315,7 @@ public class UserManagerService extends IUserManager.Stub {
@VisibleForTesting
static class UserData {
// Basic user information and properties
UserInfo info;
@NonNull UserInfo info;
// Account name used when there is a strong association between a user and an account
String account;
// Account information for seeding into a newly created user. This could also be
@@ -3268,11 +3269,39 @@ public class UserManagerService extends IUserManager.Stub {
}
}
/** Checks whether the device is currently in headless system user mode (for any reason). */
@Override
public boolean isHeadlessSystemUserMode() {
synchronized (mUsersLock) {
final UserData systemUserData = mUsers.get(UserHandle.USER_SYSTEM);
return !systemUserData.info.isFull();
}
}
/**
* Checks whether the device is really headless system user mode, ignoring system user mode
* emulation.
* Checks whether the default state of the device is headless system user mode, i.e. what the
* mode would be if we did a fresh factory reset.
* If the mode is being emulated (via SYSTEM_USER_MODE_EMULATION_PROPERTY) then that will be
* returned instead.
* Note that, even in the absence of emulation, a device might deviate from the current default
* due to an OTA changing the default (which won't change the already-decided mode).
*/
private boolean isReallyHeadlessSystemUserMode() {
private boolean isDefaultHeadlessSystemUserMode() {
if (!Build.isDebuggable()) {
return RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER;
}
final String emulatedValue = SystemProperties.get(SYSTEM_USER_MODE_EMULATION_PROPERTY);
if (!TextUtils.isEmpty(emulatedValue)) {
if (UserManager.SYSTEM_USER_MODE_EMULATION_HEADLESS.equals(emulatedValue)) return true;
if (UserManager.SYSTEM_USER_MODE_EMULATION_FULL.equals(emulatedValue)) return false;
if (!UserManager.SYSTEM_USER_MODE_EMULATION_DEFAULT.equals(emulatedValue)) {
Slogf.e(LOG_TAG, "isDefaultHeadlessSystemUserMode(): ignoring invalid valued of "
+ "property %s: %s",
SYSTEM_USER_MODE_EMULATION_PROPERTY, emulatedValue);
}
}
return RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER;
}
@@ -3284,30 +3313,11 @@ public class UserManagerService extends IUserManager.Stub {
if (!Build.isDebuggable()) {
return;
}
final String emulatedValue = SystemProperties
.get(UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY);
if (TextUtils.isEmpty(emulatedValue)) {
if (TextUtils.isEmpty(SystemProperties.get(SYSTEM_USER_MODE_EMULATION_PROPERTY))) {
return;
}
final boolean newHeadlessSystemUserMode;
switch (emulatedValue) {
case UserManager.SYSTEM_USER_MODE_EMULATION_FULL:
newHeadlessSystemUserMode = false;
break;
case UserManager.SYSTEM_USER_MODE_EMULATION_HEADLESS:
newHeadlessSystemUserMode = true;
break;
case UserManager.SYSTEM_USER_MODE_EMULATION_DEFAULT:
newHeadlessSystemUserMode = isReallyHeadlessSystemUserMode();
break;
default:
Slogf.wtf(LOG_TAG, "emulateSystemUserModeIfNeeded(): ignoring invalid valued of "
+ "property %s: %s", UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY,
emulatedValue);
return;
}
final boolean newHeadlessSystemUserMode = isDefaultHeadlessSystemUserMode();
// Update system user type
synchronized (mPackagesLock) {
@@ -3343,7 +3353,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
// Update emulated mode, which will used to triger an update on user packages
// Update emulated mode, which will used to trigger an update on user packages
mUpdatingSystemUserMode = true;
}
@@ -3533,7 +3543,11 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mUsersLock) {
UserData userData = mUsers.get(UserHandle.USER_SYSTEM);
userData.info.flags |= UserInfo.FLAG_SYSTEM;
if (!UserManager.isHeadlessSystemUserMode()) {
// We assume that isDefaultHeadlessSystemUserMode() does not change during the OTA
// from userVersion < 8 since it is documented that pre-R devices do not support its
// modification. Therefore, its current value should be the same as the pre-update
// version.
if (!isDefaultHeadlessSystemUserMode()) {
userData.info.flags |= UserInfo.FLAG_FULL;
}
userIdsToWrite.add(userData.info.id);
@@ -3742,7 +3756,7 @@ public class UserManagerService extends IUserManager.Stub {
int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
| UserInfo.FLAG_PRIMARY;
// Create the system user
String systemUserType = UserManager.isHeadlessSystemUserMode()
String systemUserType = isDefaultHeadlessSystemUserMode()
? UserManager.USER_TYPE_SYSTEM_HEADLESS
: UserManager.USER_TYPE_FULL_SYSTEM;
flags |= mUserTypes.get(systemUserType).getDefaultUserInfoFlags();
@@ -6210,9 +6224,12 @@ public class UserManagerService extends IUserManager.Stub {
com.android.internal.R.bool.config_guestUserEphemeral));
pw.println(" Force ephemeral users: " + mForceEphemeralUsers);
pw.println(" Is split-system user: " + UserManager.isSplitSystemUser());
final boolean isHeadlessSystemUserMode = UserManager.isHeadlessSystemUserMode();
final boolean isHeadlessSystemUserMode = isHeadlessSystemUserMode();
pw.println(" Is headless-system mode: " + isHeadlessSystemUserMode);
if (isHeadlessSystemUserMode != isReallyHeadlessSystemUserMode()) {
if (isHeadlessSystemUserMode != RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER) {
pw.println(" (differs from the current default build value)");
}
if (!TextUtils.isEmpty(SystemProperties.get(SYSTEM_USER_MODE_EMULATION_PROPERTY))) {
pw.println(" (emulated by 'cmd user set-system-user-mode-emulation')");
if (mUpdatingSystemUserMode) {
pw.println(" (and being updated after boot)");