Merge "Make PasswordMetrics#computeForPasswordOrPin() private" into main

This commit is contained in:
Eric Biggers
2023-07-11 15:55:02 +00:00
committed by Android (Google) Code Review
3 changed files with 51 additions and 65 deletions

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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
@@ -8837,4 +8832,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));
}
}