Merge "Single user headless DO fixes" into main
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index ac843cb..f5e0f68 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -282,3 +282,13 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "headless_single_user_fixes"
+ namespace: "enterprise"
+ description: "Various fixes for headless single user mode"
+ bug: "289515470"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7e083ba..be235b3b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -821,6 +821,13 @@
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final long THROW_SECURITY_EXCEPTION_FOR_SENSOR_PERMISSIONS = 277035314L;
+ /**
+ * Allows DPCs to provisioning fully managed headless devices in single-user mode.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = 35)
+ public static final long PROVISION_SINGLE_USER_MODE = 289515470L;
+
// Only add to the end of the list. Do not change or rearrange these values, that will break
// historical data. Do not use negative numbers or zero, logger only handles positive
// integers.
@@ -6834,7 +6841,10 @@
// If there is a profile owner, redirect to that; otherwise query the device owner.
ComponentName aliasChooser = getProfileOwnerAsUser(caller.getUserId());
- if (aliasChooser == null && caller.getUserHandle().isSystem()) {
+ boolean isDoUser = Flags.headlessSingleUserFixes()
+ ? caller.getUserId() == getDeviceOwnerUserId()
+ : caller.getUserHandle().isSystem();
+ if (aliasChooser == null && isDoUser) {
synchronized (getLockObject()) {
final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
if (deviceOwnerAdmin != null) {
@@ -7828,7 +7838,12 @@
mInjector.binderWithCleanCallingIdentity(() -> {
// First check whether the admin is allowed to wipe the device/user/profile.
final String restriction;
- if (userId == UserHandle.USER_SYSTEM) {
+ boolean shouldFactoryReset = userId == UserHandle.USER_SYSTEM;
+ if (Flags.headlessSingleUserFixes() && getHeadlessDeviceOwnerModeForDeviceOwner()
+ == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER) {
+ shouldFactoryReset = userId == getMainUserId();
+ }
+ if (shouldFactoryReset) {
restriction = UserManager.DISALLOW_FACTORY_RESET;
} else if (isManagedProfile(userId)) {
restriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
@@ -7842,12 +7857,15 @@
});
boolean isSystemUser = userId == UserHandle.USER_SYSTEM;
+ boolean isMainUser = userId == getMainUserId();
boolean wipeDevice;
if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR,
adminPackage,
userId)) {
// Legacy mode
- wipeDevice = isSystemUser;
+ wipeDevice = Flags.headlessSingleUserFixes()
+ && getHeadlessDeviceOwnerModeForDeviceOwner()
+ == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER ? isMainUser : isSystemUser;
} else {
// Explicit behaviour
if (factoryReset) {
@@ -8185,6 +8203,7 @@
userHandle, /* parent= */ false);
int max = strictestAdmin != null
? strictestAdmin.maximumFailedPasswordsForWipe : 0;
+
if (max > 0 && policy.mFailedPasswordAttempts >= max) {
wipeData = true;
}
@@ -18398,6 +18417,14 @@
Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
|| isProfileOwner(caller) || isFinancedDeviceOwner(caller));
+ // Backup service has to be enabled on the main user in order for it to be enabled on
+ // secondary users.
+ if (Flags.headlessSingleUserFixes() && isDeviceOwner(caller)
+ && getHeadlessDeviceOwnerModeForDeviceOwner()
+ == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER) {
+ toggleBackupServiceActive(UserHandle.USER_SYSTEM, enabled);
+ }
+
toggleBackupServiceActive(caller.getUserId(), enabled);
if (Flags.backupServiceSecurityLogEventEnabled()) {
@@ -21745,7 +21772,7 @@
Objects.requireNonNull(deviceAdmin, "admin is null.");
Objects.requireNonNull(provisioningParams.getOwnerName(), "owner name is null.");
- final CallerIdentity caller = getCallerIdentity();
+ final CallerIdentity caller = getCallerIdentity(callerPackage);
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
|| (hasCallingOrSelfPermission(permission.PROVISION_DEMO_DEVICE)
@@ -21755,6 +21782,23 @@
final long identity = Binder.clearCallingIdentity();
try {
+ boolean isSingleUserMode;
+ if (Flags.headlessDeviceOwnerProvisioningFixEnabled()) {
+ int headlessDeviceOwnerMode = getHeadlessDeviceOwnerModeForDeviceAdmin(
+ deviceAdmin, caller.getUserId());
+ isSingleUserMode =
+ headlessDeviceOwnerMode == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
+ } else {
+ isSingleUserMode =
+ getHeadlessDeviceOwnerModeForDeviceOwner()
+ == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
+ }
+
+ if (Flags.headlessSingleUserFixes() && isSingleUserMode && !mInjector.isChangeEnabled(
+ PROVISION_SINGLE_USER_MODE, deviceAdmin.getPackageName(), caller.getUserId())) {
+ throw new IllegalStateException("Device admin is not targeting Android V.");
+ }
+
int result = checkProvisioningPreconditionSkipPermission(
ACTION_PROVISION_MANAGED_DEVICE, deviceAdmin, caller.getUserId());
if (result != STATUS_OK) {
@@ -21768,17 +21812,6 @@
setTimeAndTimezone(provisioningParams.getTimeZone(), provisioningParams.getLocalTime());
setLocale(provisioningParams.getLocale());
- boolean isSingleUserMode;
- if (Flags.headlessDeviceOwnerProvisioningFixEnabled()) {
- int headlessDeviceOwnerMode = getHeadlessDeviceOwnerModeForDeviceAdmin(
- deviceAdmin, caller.getUserId());
- isSingleUserMode =
- headlessDeviceOwnerMode == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
- } else {
- isSingleUserMode =
- getHeadlessDeviceOwnerModeForDeviceOwner()
- == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
- }
int deviceOwnerUserId = Flags.headlessDeviceOwnerSingleUserEnabled()
&& isSingleUserMode
? mUserManagerInternal.getMainUserId() : UserHandle.USER_SYSTEM;