Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c34160c authored by Rubin Xu's avatar Rubin Xu Committed by Android (Google) Code Review
Browse files

Merge "Recognize numeric PIN in resetPasswordWithToken()" into sc-dev

parents d7b7e55d f5d0b425
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -691,6 +691,19 @@ public final class PasswordMetrics implements Parcelable {
        return minMetrics;
    }

    /**
     * Returns true if password is non-empty and contains digits only.
     * @param password
     * @return
     */
    public static boolean isNumericOnly(@NonNull String password) {
        if (password.length() == 0) return false;
        for (int i = 0; i < password.length(); i++) {
            if (categoryChar(password.charAt(i)) != CHAR_DIGIT) return false;
        }
        return true;
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (this == o) return true;
+9 −4
Original line number Diff line number Diff line
@@ -4954,6 +4954,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            int flags, CallerIdentity caller) {
        final int callingUid = caller.getUid();
        final int userHandle = UserHandle.getUserId(callingUid);
        final boolean isPin = PasswordMetrics.isNumericOnly(password);
        synchronized (getLockObject()) {
            final PasswordMetrics minMetrics = getPasswordMinimumMetricsUnchecked(userHandle);
            final List<PasswordValidationError> validationErrors;
@@ -4961,12 +4962,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            // TODO: Consider changing validation API to take LockscreenCredential.
            if (password.isEmpty()) {
                validationErrors = PasswordMetrics.validatePasswordMetrics(
                        minMetrics, complexity, false /* isPin */,
                        minMetrics, complexity, isPin,
                        new PasswordMetrics(CREDENTIAL_TYPE_NONE));
            } else {
                // TODO(b/120484642): remove getBytes() below
                validationErrors = PasswordMetrics.validatePassword(
                        minMetrics, complexity, false, password.getBytes());
                        minMetrics, complexity, isPin, password.getBytes());
            }
            if (!validationErrors.isEmpty()) {
@@ -4992,8 +4993,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        // Don't do this with the lock held, because it is going to call
        // back in to the service.
        final long ident = mInjector.binderClearCallingIdentity();
        final LockscreenCredential newCredential =
                LockscreenCredential.createPasswordOrNone(password);
        final LockscreenCredential newCredential;
        if (isPin) {
            newCredential = LockscreenCredential.createPin(password);
        } else {
            newCredential = LockscreenCredential.createPasswordOrNone(password);
        }
        try {
            if (tokenHandle == 0 || token == null) {
                if (!mLockPatternUtils.setLockCredential(newCredential,
+40 −0
Original line number Diff line number Diff line
@@ -5089,6 +5089,46 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        assertThat(dpm.clearResetPasswordToken(admin1)).isTrue();
    }

    @Test
    public void resetPasswordWithToken_NumericPin() throws Exception {
        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
        setupDeviceOwner();
        // adding a token
        final byte[] token = new byte[32];
        final long handle = 123456;
        when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
                nullable(EscrowTokenStateChangeCallback.class)))
                .thenReturn(handle);
        assertThat(dpm.setResetPasswordToken(admin1, token)).isTrue();

        // Test resetting with a numeric pin
        final String pin = "123456";
        when(getServices().lockPatternUtils.setLockCredentialWithToken(
                LockscreenCredential.createPin(pin), handle, token,
                UserHandle.USER_SYSTEM)).thenReturn(true);
        assertThat(dpm.resetPasswordWithToken(admin1, pin, token, 0)).isTrue();
    }

    @Test
    public void resetPasswordWithToken_EmptyPassword() throws Exception {
        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
        setupDeviceOwner();
        // adding a token
        final byte[] token = new byte[32];
        final long handle = 123456;
        when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
                nullable(EscrowTokenStateChangeCallback.class)))
                .thenReturn(handle);
        assertThat(dpm.setResetPasswordToken(admin1, token)).isTrue();

        // Test resetting with an empty password
        final String password = "";
        when(getServices().lockPatternUtils.setLockCredentialWithToken(
                LockscreenCredential.createNone(), handle, token,
                UserHandle.USER_SYSTEM)).thenReturn(true);
        assertThat(dpm.resetPasswordWithToken(admin1, password, token, 0)).isTrue();
    }

    @Test
    public void testIsActivePasswordSufficient() throws Exception {
        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;