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

Commit dc151e2b authored by Eric Biggers's avatar Eric Biggers
Browse files

Make PasswordMetrics#computeForPasswordOrPin() private

PasswordMetrics#computeForPasswordOrPin() has unnecessarily broad
visibility and was being misused by the clockwork settings app (fixed by
http://ag/23923392).  Now it is only used by PasswordMetrics itself and
unit tests, but the unit tests can just use computeForCredential()
instead.  Do that, and make computeForPasswordOrPin() a private method.

Test: atest PasswordMetricsTest com.android.server.devicepolicy.DevicePolicyManagerTest
Change-Id: I1028e946ac97bd51c489e630d2de6df7685d454f
Merged-In: I1028e946ac97bd51c489e630d2de6df7685d454f
(cherry picked from commit 3226b81b)
parent 2b32467e
Loading
Loading
Loading
Loading
+8 −14
Original line number Diff line number Diff line
@@ -179,17 +179,11 @@ public final class PasswordMetrics implements Parcelable {
    };

    /**
     * Returns the {@code PasswordMetrics} for a given credential.
     *
     * If the credential is a pin or a password, equivalent to
     * {@link #computeForPasswordOrPin(byte[], boolean)}. {@code credential} cannot be null
     * when {@code type} is
     * {@link com.android.internal.widget.LockPatternUtils#CREDENTIAL_TYPE_PASSWORD}.
     * Returns the {@code PasswordMetrics} for the given credential.
     */
    public static PasswordMetrics computeForCredential(LockscreenCredential credential) {
        if (credential.isPassword() || credential.isPin()) {
            return PasswordMetrics.computeForPasswordOrPin(credential.getCredential(),
                    credential.isPin());
            return computeForPasswordOrPin(credential.getCredential(), credential.isPin());
        } else if (credential.isPattern())  {
            PasswordMetrics metrics = new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
            metrics.length = credential.size();
@@ -202,10 +196,10 @@ public final class PasswordMetrics implements Parcelable {
    }

    /**
     * Returns the {@code PasswordMetrics} for a given password or pin
     * Returns the {@code PasswordMetrics} for the given password or pin.
     */
    public static PasswordMetrics computeForPasswordOrPin(byte[] password, boolean isPin) {
        // Analyse the characters used
    private static PasswordMetrics computeForPasswordOrPin(byte[] credential, boolean isPin) {
        // Analyze the characters used.
        int letters = 0;
        int upperCase = 0;
        int lowerCase = 0;
@@ -213,8 +207,8 @@ public final class PasswordMetrics implements Parcelable {
        int symbols = 0;
        int nonLetter = 0;
        int nonNumeric = 0;
        final int length = password.length;
        for (byte b : password) {
        final int length = credential.length;
        for (byte b : credential) {
            switch (categoryChar((char) b)) {
                case CHAR_LOWER_CASE:
                    letters++;
@@ -239,7 +233,7 @@ public final class PasswordMetrics implements Parcelable {
        }

        final int credType = isPin ? CREDENTIAL_TYPE_PIN : CREDENTIAL_TYPE_PASSWORD;
        final int seqLength = maxLengthSequence(password);
        final int seqLength = maxLengthSequence(credential);
        return new PasswordMetrics(credType, length, letters, upperCase, lowerCase,
                numeric, symbols, nonLetter, nonNumeric, seqLength);
    }
+19 −30
Original line number Diff line number Diff line
@@ -97,8 +97,7 @@ public class PasswordMetricsTest {

    @Test
    public void testComputeForPassword_metrics() {
        final PasswordMetrics metrics = PasswordMetrics.computeForPasswordOrPin(
                "6B~0z1Z3*8A".getBytes(), /* isPin */ false);
        final PasswordMetrics metrics = metricsForPassword("6B~0z1Z3*8A");
        assertEquals(11, metrics.length);
        assertEquals(4, metrics.letters);
        assertEquals(3, metrics.upperCase);
@@ -136,72 +135,54 @@ public class PasswordMetricsTest {

    @Test
    public void testDetermineComplexity_lowNumeric() {
        assertEquals(PASSWORD_COMPLEXITY_LOW,
                PasswordMetrics.computeForPasswordOrPin("1234".getBytes(),
                        /* isPin */true).determineComplexity());
        assertEquals(PASSWORD_COMPLEXITY_LOW, metricsForPin("1234").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_lowNumericComplex() {
        assertEquals(PASSWORD_COMPLEXITY_LOW,
                PasswordMetrics.computeForPasswordOrPin("124".getBytes(),
                        /* isPin */ true).determineComplexity());
        assertEquals(PASSWORD_COMPLEXITY_LOW, metricsForPin("124").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_lowAlphabetic() {
        assertEquals(PASSWORD_COMPLEXITY_LOW,
                PasswordMetrics.computeForPasswordOrPin("a!".getBytes(),
                        /* isPin */ false).determineComplexity());
        assertEquals(PASSWORD_COMPLEXITY_LOW, metricsForPassword("a!").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_lowAlphanumeric() {
        assertEquals(PASSWORD_COMPLEXITY_LOW,
                PasswordMetrics.computeForPasswordOrPin("a!1".getBytes(),
                        /* isPin */ false).determineComplexity());
        assertEquals(PASSWORD_COMPLEXITY_LOW, metricsForPassword("a!1").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_mediumNumericComplex() {
        assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
                PasswordMetrics.computeForPasswordOrPin("1238".getBytes(),
                        /* isPin */ true).determineComplexity());
        assertEquals(PASSWORD_COMPLEXITY_MEDIUM, metricsForPin("1238").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_mediumAlphabetic() {
        assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
                PasswordMetrics.computeForPasswordOrPin("ab!c".getBytes(),
                        /* isPin */ false).determineComplexity());
        assertEquals(PASSWORD_COMPLEXITY_MEDIUM, metricsForPassword("ab!c").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_mediumAlphanumeric() {
        assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
                PasswordMetrics.computeForPasswordOrPin("ab!1".getBytes(),
                        /* isPin */ false).determineComplexity());
        assertEquals(PASSWORD_COMPLEXITY_MEDIUM, metricsForPassword("ab!1").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_highNumericComplex() {
        assertEquals(PASSWORD_COMPLEXITY_HIGH,
                PasswordMetrics.computeForPasswordOrPin("12389647!".getBytes(),
                        /* isPin */ true).determineComplexity());
        assertEquals(PASSWORD_COMPLEXITY_HIGH, metricsForPin("12389647!").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_highAlphabetic() {
        assertEquals(PASSWORD_COMPLEXITY_HIGH,
                PasswordMetrics.computeForPasswordOrPin("alphabetic!".getBytes(),
                        /* isPin */ false).determineComplexity());
                metricsForPassword("alphabetic!").determineComplexity());
    }

    @Test
    public void testDetermineComplexity_highAlphanumeric() {
        assertEquals(PASSWORD_COMPLEXITY_HIGH,
                PasswordMetrics.computeForPasswordOrPin("alphanumeric123!".getBytes(),
                        /* isPin */ false).determineComplexity());
                metricsForPassword("alphanumeric123!").determineComplexity());
    }

    @Test
@@ -425,6 +406,14 @@ public class PasswordMetricsTest {
                patternString.getBytes()));
    }

    private static PasswordMetrics metricsForPassword(String password) {
        return PasswordMetrics.computeForCredential(LockscreenCredential.createPassword(password));
    }

    private static PasswordMetrics metricsForPin(String pin) {
        return PasswordMetrics.computeForCredential(LockscreenCredential.createPin(pin));
    }

    @Test
    public void testValidateCredential_pattern() {
        PasswordMetrics adminMetrics = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
+24 −21
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_EAP
import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_OPEN;
import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_PERSONAL;
import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
import static android.app.admin.PasswordMetrics.computeForPasswordOrPin;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.GPS_PROVIDER;
@@ -5479,8 +5478,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        reset(mContext.spiedContext);

        PasswordMetrics passwordMetricsNoSymbols = computeForPasswordOrPin(
                "abcdXYZ5".getBytes(), /* isPin */ false);
        PasswordMetrics passwordMetricsNoSymbols = metricsForPassword("abcdXYZ5");

        setActivePasswordState(passwordMetricsNoSymbols);
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
@@ -5507,8 +5505,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        reset(mContext.spiedContext);
        assertThat(dpm.isActivePasswordSufficient()).isFalse();

        PasswordMetrics passwordMetricsWithSymbols = computeForPasswordOrPin(
                "abcd.XY5".getBytes(), /* isPin */ false);
        PasswordMetrics passwordMetricsWithSymbols = metricsForPassword("abcd.XY5");

        setActivePasswordState(passwordMetricsWithSymbols);
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
@@ -5564,7 +5561,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        parentDpm.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_MEDIUM);

        when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
                .thenReturn(computeForPasswordOrPin("184342".getBytes(), /* isPin */ true));
                .thenReturn(metricsForPin("184342"));

        // Numeric password is compliant with current requirement (QUALITY_NUMERIC set explicitly
        // on the parent admin)
@@ -5685,7 +5682,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Set a work challenge and verify profile.isActivePasswordSufficient is now true
        when(getServices().lockSettingsInternal.getUserPasswordMetrics(managedProfileUserId))
                .thenReturn(computeForPasswordOrPin("abcdXYZ5".getBytes(), /* isPin */ false));
                .thenReturn(metricsForPassword("abcdXYZ5"));
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
        assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
    }
@@ -5710,7 +5707,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Set a work challenge and verify profile.isActivePasswordSufficient is now true
        when(getServices().lockSettingsInternal.getUserPasswordMetrics(managedProfileUserId))
                .thenReturn(computeForPasswordOrPin("5156".getBytes(), /* isPin */ true));
                .thenReturn(metricsForPin("5156"));
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
        assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
    }
@@ -5735,7 +5732,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Set a device lockscreen and verify parent.isActivePasswordSufficient is now true
        when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
                .thenReturn(computeForPasswordOrPin("acbdXYZ5".getBytes(), /* isPin */ false));
                .thenReturn(metricsForPassword("acbdXYZ5"));
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
        assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
    }
@@ -5758,7 +5755,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Set a device lockscreen and verify parent.isActivePasswordSufficient is now true
        when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
                .thenReturn(computeForPasswordOrPin("1234".getBytes(), /* isPin */ true));
                .thenReturn(metricsForPin("1234"));
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
        assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
    }
@@ -5783,7 +5780,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Set a device lockscreen and verify {profile, parent}.isActivePasswordSufficient is true
        when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
                .thenReturn(computeForPasswordOrPin("abcdXYZ5".getBytes(), /* isPin */ false));
                .thenReturn(metricsForPassword("abcdXYZ5"));
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
        assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
    }
@@ -5806,7 +5803,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Set a device lockscreen and verify {profile, parent}.isActivePasswordSufficient is true
        when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
                .thenReturn(computeForPasswordOrPin("51567548".getBytes(), /* isPin */ true));
                .thenReturn(metricsForPin("51567548"));
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
        assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
    }
@@ -5831,7 +5828,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Set a device lockscreen and verify {profile, parent}.isActivePasswordSufficient is true
        when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
                .thenReturn(computeForPasswordOrPin("abcdXYZ5".getBytes(), /* isPin */ false));
                .thenReturn(metricsForPassword("abcdXYZ5"));
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
        assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
    }
@@ -5854,7 +5851,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Set a device lockscreen and verify {profile, parent}.isActivePasswordSufficient is true
        when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
                .thenReturn(computeForPasswordOrPin("5156".getBytes(), /* isPin */ true));
                .thenReturn(metricsForPin("5156"));
        assertThat(dpm.isActivePasswordSufficient()).isTrue();
        assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
    }
@@ -6909,7 +6906,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
                .thenReturn(CALLER_USER_HANDLE);
        when(getServices().lockSettingsInternal
                .getUserPasswordMetrics(CALLER_USER_HANDLE))
                .thenReturn(computeForPasswordOrPin("asdf".getBytes(), /* isPin */ false));
                .thenReturn(metricsForPassword("asdf"));

        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_MEDIUM);
    }
@@ -6929,10 +6926,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        when(getServices().lockSettingsInternal
                .getUserPasswordMetrics(CALLER_USER_HANDLE))
                .thenReturn(computeForPasswordOrPin("asdf".getBytes(), /* isPin */ false));
                .thenReturn(metricsForPassword("asdf"));
        when(getServices().lockSettingsInternal
                .getUserPasswordMetrics(parentUser.id))
                .thenReturn(computeForPasswordOrPin("parentUser".getBytes(), /* isPin */ false));
                .thenReturn(metricsForPassword("parentUser"));

        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_HIGH);
    }
@@ -7654,15 +7651,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_NONE);

        reset(mContext.spiedContext);
        PasswordMetrics passwordMetricsNoSymbols = computeForPasswordOrPin(
                "1234".getBytes(), /* isPin */ true);
        PasswordMetrics passwordMetricsNoSymbols = metricsForPin("1234");
        setActivePasswordState(passwordMetricsNoSymbols);
        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_LOW);
        assertThat(dpm.isActivePasswordSufficient()).isFalse();

        reset(mContext.spiedContext);
        passwordMetricsNoSymbols = computeForPasswordOrPin(
                "84125312943a".getBytes(), /* isPin */ false);
        passwordMetricsNoSymbols = metricsForPassword("84125312943a");
        setActivePasswordState(passwordMetricsNoSymbols);
        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_HIGH);
        // using isActivePasswordSufficient
@@ -8838,4 +8833,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        assumeTrue("device doesn't support deprecated password APIs",
                isDeprecatedPasswordApisSupported());
    }

    private static PasswordMetrics metricsForPassword(String password) {
        return PasswordMetrics.computeForCredential(LockscreenCredential.createPassword(password));
    }

    private static PasswordMetrics metricsForPin(String pin) {
        return PasswordMetrics.computeForCredential(LockscreenCredential.createPin(pin));
    }
}