diff options
| author | 2022-11-02 21:01:25 +0000 | |
|---|---|---|
| committer | 2022-11-02 21:01:25 +0000 | |
| commit | cfbc9e029a4ce4959bfc535352c8b3adfa74e643 (patch) | |
| tree | 1ed1aff9d692693928c0757290c221f5fcdd5045 | |
| parent | a956334f692dacdb11cacb41b8c75af11e3e8492 (diff) | |
| parent | aeffc9de3c542006fdbd19596cff12b5972778ca (diff) | |
Merge "Changing hsum property in OTA won't alter mode"
| -rw-r--r-- | core/java/android/os/IUserManager.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/os/UserManager.java | 38 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/RoSystemProperties.java | 9 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 77 |
4 files changed, 73 insertions, 52 deletions
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 933769a352e9..8eaa5ad7fe94 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -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); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index f1879dd792a3..3d20d6373ae2 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -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; } /** diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java index 98d81c9598b8..6870d09c8a7f 100644 --- a/core/java/com/android/internal/os/RoSystemProperties.java +++ b/core/java/com/android/internal/os/RoSystemProperties.java @@ -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); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index d2af78b05772..f85b11da252e 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -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)"); |