diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index fe3e4b12c488f..479dd1e5d84e1 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8052,6 +8052,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { "clearDeviceOwner can only be called by the device owner"); } enforceUserUnlocked(deviceOwnerUserId); + DevicePolicyData policy = getUserData(deviceOwnerUserId); + if (policy.mPasswordTokenHandle != 0) { + mLockPatternUtils.removeEscrowToken(policy.mPasswordTokenHandle, deviceOwnerUserId); + } final ActiveAdmin admin = getDeviceOwnerAdminLocked(); long ident = mInjector.binderClearCallingIdentity(); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index d900910171165..a25e40f8cc13b 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -1212,6 +1212,45 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertTrue(dpm.isDeviceManaged()); } + /** + * Test for: {@link DevicePolicyManager#clearDeviceOwnerApp(String)} + * + * Validates that when the device owner is removed, the reset password token is cleared + */ + public void testClearDeviceOwner_clearResetPasswordToken() throws Exception { + mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS); + mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + + // Install admin1 on system user + setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID); + + // Set admin1 to active admin and device owner + dpm.setActiveAdmin(admin1, /* replace =*/ false); + dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM); + + // Add reset password token + final long handle = 12000; + final byte[] token = new byte[32]; + when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM), + nullable(EscrowTokenStateChangeCallback.class))) + .thenReturn(handle); + assertTrue(dpm.setResetPasswordToken(admin1, token)); + + // Assert reset password token is active + when(getServices().lockPatternUtils.isEscrowTokenActive(eq(handle), + eq(UserHandle.USER_SYSTEM))) + .thenReturn(true); + assertTrue(dpm.isResetPasswordTokenActive(admin1)); + + // Remove the device owner + dpm.clearDeviceOwnerApp(admin1.getPackageName()); + + // Verify password reset password token was removed + verify(getServices().lockPatternUtils).removeEscrowToken(eq(handle), + eq(UserHandle.USER_SYSTEM)); + } + public void testSetProfileOwner() throws Exception { setAsProfileOwner(admin1);