Loading core/java/android/app/admin/flags/flags.aconfig +10 −0 Original line number Original line Diff line number Diff line Loading @@ -282,3 +282,13 @@ flag { purpose: PURPOSE_BUGFIX 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 } } services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +48 −15 Original line number Original line Diff line number Diff line Loading @@ -821,6 +821,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public static final long THROW_SECURITY_EXCEPTION_FOR_SENSOR_PERMISSIONS = 277035314L; 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 // 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 // historical data. Do not use negative numbers or zero, logger only handles positive // integers. // integers. Loading Loading @@ -6834,7 +6841,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // If there is a profile owner, redirect to that; otherwise query the device owner. // If there is a profile owner, redirect to that; otherwise query the device owner. ComponentName aliasChooser = getProfileOwnerAsUser(caller.getUserId()); 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()) { synchronized (getLockObject()) { final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked(); final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked(); if (deviceOwnerAdmin != null) { if (deviceOwnerAdmin != null) { Loading Loading @@ -7828,7 +7838,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mInjector.binderWithCleanCallingIdentity(() -> { mInjector.binderWithCleanCallingIdentity(() -> { // First check whether the admin is allowed to wipe the device/user/profile. // First check whether the admin is allowed to wipe the device/user/profile. final String restriction; 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; restriction = UserManager.DISALLOW_FACTORY_RESET; } else if (isManagedProfile(userId)) { } else if (isManagedProfile(userId)) { restriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE; restriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE; Loading @@ -7842,12 +7857,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }); }); boolean isSystemUser = userId == UserHandle.USER_SYSTEM; boolean isSystemUser = userId == UserHandle.USER_SYSTEM; boolean isMainUser = userId == getMainUserId(); boolean wipeDevice; boolean wipeDevice; if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR, if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR, adminPackage, adminPackage, userId)) { userId)) { // Legacy mode // Legacy mode wipeDevice = isSystemUser; wipeDevice = Flags.headlessSingleUserFixes() && getHeadlessDeviceOwnerModeForDeviceOwner() == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER ? isMainUser : isSystemUser; } else { } else { // Explicit behaviour // Explicit behaviour if (factoryReset) { if (factoryReset) { Loading Loading @@ -8185,6 +8203,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { userHandle, /* parent= */ false); userHandle, /* parent= */ false); int max = strictestAdmin != null int max = strictestAdmin != null ? strictestAdmin.maximumFailedPasswordsForWipe : 0; ? strictestAdmin.maximumFailedPasswordsForWipe : 0; if (max > 0 && policy.mFailedPasswordAttempts >= max) { if (max > 0 && policy.mFailedPasswordAttempts >= max) { wipeData = true; wipeData = true; } } Loading Loading @@ -18398,6 +18417,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller) || isFinancedDeviceOwner(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); toggleBackupServiceActive(caller.getUserId(), enabled); if (Flags.backupServiceSecurityLogEventEnabled()) { if (Flags.backupServiceSecurityLogEventEnabled()) { Loading Loading @@ -21745,7 +21772,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Objects.requireNonNull(deviceAdmin, "admin is null."); Objects.requireNonNull(deviceAdmin, "admin is null."); Objects.requireNonNull(provisioningParams.getOwnerName(), "owner name is null."); Objects.requireNonNull(provisioningParams.getOwnerName(), "owner name is null."); final CallerIdentity caller = getCallerIdentity(); final CallerIdentity caller = getCallerIdentity(callerPackage); Preconditions.checkCallAuthorization( Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS) hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS) || (hasCallingOrSelfPermission(permission.PROVISION_DEMO_DEVICE) || (hasCallingOrSelfPermission(permission.PROVISION_DEMO_DEVICE) Loading @@ -21755,6 +21782,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); try { 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( int result = checkProvisioningPreconditionSkipPermission( ACTION_PROVISION_MANAGED_DEVICE, deviceAdmin, caller.getUserId()); ACTION_PROVISION_MANAGED_DEVICE, deviceAdmin, caller.getUserId()); if (result != STATUS_OK) { if (result != STATUS_OK) { Loading @@ -21768,17 +21812,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { setTimeAndTimezone(provisioningParams.getTimeZone(), provisioningParams.getLocalTime()); setTimeAndTimezone(provisioningParams.getTimeZone(), provisioningParams.getLocalTime()); setLocale(provisioningParams.getLocale()); 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() int deviceOwnerUserId = Flags.headlessDeviceOwnerSingleUserEnabled() && isSingleUserMode && isSingleUserMode ? mUserManagerInternal.getMainUserId() : UserHandle.USER_SYSTEM; ? mUserManagerInternal.getMainUserId() : UserHandle.USER_SYSTEM; Loading
core/java/android/app/admin/flags/flags.aconfig +10 −0 Original line number Original line Diff line number Diff line Loading @@ -282,3 +282,13 @@ flag { purpose: PURPOSE_BUGFIX 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 } }
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +48 −15 Original line number Original line Diff line number Diff line Loading @@ -821,6 +821,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public static final long THROW_SECURITY_EXCEPTION_FOR_SENSOR_PERMISSIONS = 277035314L; 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 // 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 // historical data. Do not use negative numbers or zero, logger only handles positive // integers. // integers. Loading Loading @@ -6834,7 +6841,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // If there is a profile owner, redirect to that; otherwise query the device owner. // If there is a profile owner, redirect to that; otherwise query the device owner. ComponentName aliasChooser = getProfileOwnerAsUser(caller.getUserId()); 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()) { synchronized (getLockObject()) { final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked(); final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked(); if (deviceOwnerAdmin != null) { if (deviceOwnerAdmin != null) { Loading Loading @@ -7828,7 +7838,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mInjector.binderWithCleanCallingIdentity(() -> { mInjector.binderWithCleanCallingIdentity(() -> { // First check whether the admin is allowed to wipe the device/user/profile. // First check whether the admin is allowed to wipe the device/user/profile. final String restriction; 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; restriction = UserManager.DISALLOW_FACTORY_RESET; } else if (isManagedProfile(userId)) { } else if (isManagedProfile(userId)) { restriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE; restriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE; Loading @@ -7842,12 +7857,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }); }); boolean isSystemUser = userId == UserHandle.USER_SYSTEM; boolean isSystemUser = userId == UserHandle.USER_SYSTEM; boolean isMainUser = userId == getMainUserId(); boolean wipeDevice; boolean wipeDevice; if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR, if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR, adminPackage, adminPackage, userId)) { userId)) { // Legacy mode // Legacy mode wipeDevice = isSystemUser; wipeDevice = Flags.headlessSingleUserFixes() && getHeadlessDeviceOwnerModeForDeviceOwner() == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER ? isMainUser : isSystemUser; } else { } else { // Explicit behaviour // Explicit behaviour if (factoryReset) { if (factoryReset) { Loading Loading @@ -8185,6 +8203,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { userHandle, /* parent= */ false); userHandle, /* parent= */ false); int max = strictestAdmin != null int max = strictestAdmin != null ? strictestAdmin.maximumFailedPasswordsForWipe : 0; ? strictestAdmin.maximumFailedPasswordsForWipe : 0; if (max > 0 && policy.mFailedPasswordAttempts >= max) { if (max > 0 && policy.mFailedPasswordAttempts >= max) { wipeData = true; wipeData = true; } } Loading Loading @@ -18398,6 +18417,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller) || isFinancedDeviceOwner(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); toggleBackupServiceActive(caller.getUserId(), enabled); if (Flags.backupServiceSecurityLogEventEnabled()) { if (Flags.backupServiceSecurityLogEventEnabled()) { Loading Loading @@ -21745,7 +21772,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Objects.requireNonNull(deviceAdmin, "admin is null."); Objects.requireNonNull(deviceAdmin, "admin is null."); Objects.requireNonNull(provisioningParams.getOwnerName(), "owner name is null."); Objects.requireNonNull(provisioningParams.getOwnerName(), "owner name is null."); final CallerIdentity caller = getCallerIdentity(); final CallerIdentity caller = getCallerIdentity(callerPackage); Preconditions.checkCallAuthorization( Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS) hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS) || (hasCallingOrSelfPermission(permission.PROVISION_DEMO_DEVICE) || (hasCallingOrSelfPermission(permission.PROVISION_DEMO_DEVICE) Loading @@ -21755,6 +21782,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); try { 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( int result = checkProvisioningPreconditionSkipPermission( ACTION_PROVISION_MANAGED_DEVICE, deviceAdmin, caller.getUserId()); ACTION_PROVISION_MANAGED_DEVICE, deviceAdmin, caller.getUserId()); if (result != STATUS_OK) { if (result != STATUS_OK) { Loading @@ -21768,17 +21812,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { setTimeAndTimezone(provisioningParams.getTimeZone(), provisioningParams.getLocalTime()); setTimeAndTimezone(provisioningParams.getTimeZone(), provisioningParams.getLocalTime()); setLocale(provisioningParams.getLocale()); 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() int deviceOwnerUserId = Flags.headlessDeviceOwnerSingleUserEnabled() && isSingleUserMode && isSingleUserMode ? mUserManagerInternal.getMainUserId() : UserHandle.USER_SYSTEM; ? mUserManagerInternal.getMainUserId() : UserHandle.USER_SYSTEM;