summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2022-11-02 21:01:25 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-11-02 21:01:25 +0000
commitcfbc9e029a4ce4959bfc535352c8b3adfa74e643 (patch)
tree1ed1aff9d692693928c0757290c221f5fcdd5045
parenta956334f692dacdb11cacb41b8c75af11e3e8492 (diff)
parentaeffc9de3c542006fdbd19596cff12b5972778ca (diff)
Merge "Changing hsum property in OTA won't alter mode"
-rw-r--r--core/java/android/os/IUserManager.aidl1
-rw-r--r--core/java/android/os/UserManager.java38
-rw-r--r--core/java/com/android/internal/os/RoSystemProperties.java9
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java77
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)");