summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java132
4 files changed, 96 insertions, 49 deletions
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a11eaa91b2a6..d828f33ca514 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1786,10 +1786,6 @@
<string name="biometric_dialog_default_title">Verify it\u2019s you</string>
<!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with a biometric (e.g. fingerprint or face). [CHAR LIMIT=70] -->
<string name="biometric_dialog_default_subtitle">Use your biometric to continue</string>
- <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with fingerprint. [CHAR LIMIT=70] -->
- <string name="biometric_dialog_fingerprint_subtitle">Use your fingerprint to continue</string>
- <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with face. [CHAR LIMIT=70] -->
- <string name="biometric_dialog_face_subtitle">Use your face to continue</string>
<!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with a biometric (e.g. fingerprint or face) or their screen lock credential (i.e. PIN, pattern, or password). [CHAR LIMIT=90] -->
<string name="biometric_or_screen_lock_dialog_default_subtitle">Use your biometric or screen lock to continue</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5806e93d4a93..63f29a8fc1c6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2585,8 +2585,6 @@
<java-symbol type="string" name="biometric_or_screen_lock_app_setting_name" />
<java-symbol type="string" name="biometric_dialog_default_title" />
<java-symbol type="string" name="biometric_dialog_default_subtitle" />
- <java-symbol type="string" name="biometric_dialog_face_subtitle" />
- <java-symbol type="string" name="biometric_dialog_fingerprint_subtitle" />
<java-symbol type="string" name="biometric_or_screen_lock_dialog_default_subtitle" />
<java-symbol type="string" name="biometric_error_hw_unavailable" />
<java-symbol type="string" name="biometric_error_user_canceled" />
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 279aaf9d3253..1898b8015462 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -1308,10 +1308,13 @@ public class BiometricService extends SystemService {
.getString(R.string.biometric_dialog_default_subtitle));
} else if (hasEligibleFingerprintSensor) {
promptInfo.setSubtitle(getContext()
- .getString(R.string.biometric_dialog_fingerprint_subtitle));
+ .getString(R.string.fingerprint_dialog_default_subtitle));
} else if (hasEligibleFaceSensor) {
promptInfo.setSubtitle(getContext()
- .getString(R.string.biometric_dialog_face_subtitle));
+ .getString(R.string.face_dialog_default_subtitle));
+ } else {
+ promptInfo.setSubtitle(getContext()
+ .getString(R.string.screen_lock_dialog_default_subtitle));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index fc62e75b7d59..e79ac0986dc8 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -16,6 +16,7 @@
package com.android.server.biometrics;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_CREDENTIAL;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricManager.Authenticators;
@@ -116,9 +117,9 @@ public class BiometricServiceTest {
private static final String ERROR_LOCKOUT = "error_lockout";
private static final String FACE_SUBTITLE = "face_subtitle";
private static final String FINGERPRINT_SUBTITLE = "fingerprint_subtitle";
+ private static final String CREDENTIAL_SUBTITLE = "credential_subtitle";
private static final String DEFAULT_SUBTITLE = "default_subtitle";
-
private static final String FINGERPRINT_ACQUIRED_SENSOR_DIRTY = "sensor_dirty";
private static final int SENSOR_ID_FINGERPRINT = 0;
@@ -143,6 +144,8 @@ public class BiometricServiceTest {
@Mock
IBiometricAuthenticator mFaceAuthenticator;
@Mock
+ IBiometricAuthenticator mCredentialAuthenticator;
+ @Mock
ITrustManager mTrustManager;
@Mock
DevicePolicyManager mDevicePolicyManager;
@@ -196,10 +199,12 @@ public class BiometricServiceTest {
.thenReturn(ERROR_NOT_RECOGNIZED);
when(mResources.getString(R.string.biometric_error_user_canceled))
.thenReturn(ERROR_USER_CANCELED);
- when(mContext.getString(R.string.biometric_dialog_face_subtitle))
+ when(mContext.getString(R.string.face_dialog_default_subtitle))
.thenReturn(FACE_SUBTITLE);
- when(mContext.getString(R.string.biometric_dialog_fingerprint_subtitle))
+ when(mContext.getString(R.string.fingerprint_dialog_default_subtitle))
.thenReturn(FINGERPRINT_SUBTITLE);
+ when(mContext.getString(R.string.screen_lock_dialog_default_subtitle))
+ .thenReturn(CREDENTIAL_SUBTITLE);
when(mContext.getString(R.string.biometric_dialog_default_subtitle))
.thenReturn(DEFAULT_SUBTITLE);
@@ -292,7 +297,8 @@ public class BiometricServiceTest {
mBiometricService.onStart();
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL);
+ Authenticators.DEVICE_CREDENTIAL, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_CREDENTIAL),
@@ -312,7 +318,8 @@ public class BiometricServiceTest {
mBiometricService.onStart();
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL);
+ Authenticators.DEVICE_CREDENTIAL, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertNotNull(mBiometricService.mAuthSession);
@@ -338,7 +345,8 @@ public class BiometricServiceTest {
mBiometricService.onStart();
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_NONE),
@@ -357,7 +365,8 @@ public class BiometricServiceTest {
mFingerprintAuthenticator);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(TYPE_FINGERPRINT),
@@ -370,7 +379,8 @@ public class BiometricServiceTest {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_WEAK);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- Authenticators.BIOMETRIC_STRONG);
+ Authenticators.BIOMETRIC_STRONG, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_NONE),
@@ -429,7 +439,8 @@ public class BiometricServiceTest {
mFingerprintAuthenticator);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(TYPE_FINGERPRINT),
@@ -441,9 +452,9 @@ public class BiometricServiceTest {
public void testAuthenticateFace_shouldShowSubtitleForFace() throws Exception {
setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */,
- null);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, true /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(FACE_SUBTITLE, mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
@@ -453,9 +464,9 @@ public class BiometricServiceTest {
public void testAuthenticateFingerprint_shouldShowSubtitleForFingerprint() throws Exception {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */,
- null);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, true /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(FINGERPRINT_SUBTITLE,
@@ -463,6 +474,19 @@ public class BiometricServiceTest {
}
@Test
+ public void testAuthenticateFingerprint_shouldShowSubtitleForCredential() throws Exception {
+ setupAuthForOnly(TYPE_CREDENTIAL, Authenticators.DEVICE_CREDENTIAL);
+
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, true /* useDefaultSubtitle */,
+ true /* deviceCredentialAllowed */);
+ waitForIdle();
+
+ assertEquals(CREDENTIAL_SUBTITLE,
+ mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
+ }
+
+ @Test
public void testAuthenticateBothFpAndFace_shouldShowDefaultSubtitle() throws Exception {
final int[] modalities = new int[] {
TYPE_FINGERPRINT,
@@ -476,9 +500,9 @@ public class BiometricServiceTest {
setupAuthForMultiple(modalities, strengths);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */,
- null);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, true /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(DEFAULT_SUBTITLE, mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
@@ -492,7 +516,8 @@ public class BiometricServiceTest {
// Disabled in user settings receives onError
when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_NONE),
@@ -506,7 +531,8 @@ public class BiometricServiceTest {
anyInt() /* modality */, anyInt() /* userId */))
.thenReturn(true);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
final byte[] HAT = generateRandomHAT();
@@ -524,7 +550,8 @@ public class BiometricServiceTest {
anyInt() /* modality */, anyInt() /* userId */))
.thenReturn(false);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded(
SENSOR_ID_FACE,
@@ -552,7 +579,8 @@ public class BiometricServiceTest {
throws Exception {
// Start testing the happy path
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
// Creates a pending auth session with the correct initial states
@@ -632,7 +660,8 @@ public class BiometricServiceTest {
.thenReturn(true);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
true /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK);
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK,
+ false /* useDefaultSubtitle*/, false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
@@ -702,7 +731,8 @@ public class BiometricServiceTest {
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
true /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG);
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG,
+ false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(anyInt() /* modality */,
@@ -754,7 +784,8 @@ public class BiometricServiceTest {
false /* requireConfirmation */, null /* authenticators */);
invokeAuthenticate(mBiometricService.mImpl, mReceiver2, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
@@ -887,7 +918,8 @@ public class BiometricServiceTest {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK);
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK,
+ false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState());
@@ -920,8 +952,9 @@ public class BiometricServiceTest {
public void testErrorFromHal_whilePreparingAuthentication_credentialNotAllowed()
throws Exception {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */, null /* authenticators */);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
mBiometricService.mAuthSession.mSensorReceiver.onError(
@@ -957,8 +990,9 @@ public class BiometricServiceTest {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
.thenReturn(lockoutMode);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */, null /* authenticators */);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
// Modality and error are sent
@@ -996,8 +1030,9 @@ public class BiometricServiceTest {
when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
.thenReturn(lockoutMode);
when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */, null /* authenticators */);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
// The lockout error should be sent, instead of ERROR_NONE_ENROLLED. See b/286923477.
@@ -1014,7 +1049,8 @@ public class BiometricServiceTest {
.thenReturn(LockoutTracker.LOCKOUT_PERMANENT);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG);
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG,
+ false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
@@ -1503,7 +1539,8 @@ public class BiometricServiceTest {
assertEquals(BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
invokeCanAuthenticate(mBiometricService, authenticators));
long requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */, authenticators);
+ false /* requireConfirmation */, authenticators, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(TYPE_FINGERPRINT),
@@ -1539,7 +1576,8 @@ public class BiometricServiceTest {
invokeCanAuthenticate(mBiometricService, authenticators));
requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */,
- authenticators);
+ authenticators, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertTrue(Utils.isCredentialRequested(mBiometricService.mAuthSession.mPromptInfo));
verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
@@ -1749,6 +1787,11 @@ public class BiometricServiceTest {
mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FACE, modality, strength,
mFaceAuthenticator);
}
+
+ if ((modality & TYPE_CREDENTIAL) != 0) {
+ when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
+ .thenReturn(true);
+ }
}
// TODO: Reduce duplicated code, currently we cannot start the BiometricService in setUp() for
@@ -1799,7 +1842,8 @@ public class BiometricServiceTest {
Integer authenticators) throws Exception {
// Request auth, creates a pending session
final long requestId = invokeAuthenticate(
- service, receiver, requireConfirmation, authenticators);
+ service, receiver, requireConfirmation, authenticators,
+ false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
waitForIdle();
startPendingAuthSession(mBiometricService);
@@ -1827,7 +1871,8 @@ public class BiometricServiceTest {
private static long invokeAuthenticate(IBiometricService.Stub service,
IBiometricServiceReceiver receiver, boolean requireConfirmation,
- Integer authenticators) throws Exception {
+ Integer authenticators, boolean useDefaultSubtitle,
+ boolean deviceCredentialAllowed) throws Exception {
return service.authenticate(
new Binder() /* token */,
0 /* operationId */,
@@ -1835,7 +1880,8 @@ public class BiometricServiceTest {
receiver,
TEST_PACKAGE_NAME /* packageName */,
createTestPromptInfo(requireConfirmation, authenticators,
- false /* checkDevicePolicy */));
+ false /* checkDevicePolicy */, useDefaultSubtitle,
+ deviceCredentialAllowed));
}
private static long invokeAuthenticateForWorkApp(IBiometricService.Stub service,
@@ -1847,16 +1893,19 @@ public class BiometricServiceTest {
receiver,
TEST_PACKAGE_NAME /* packageName */,
createTestPromptInfo(false /* requireConfirmation */, authenticators,
- true /* checkDevicePolicy */));
+ true /* checkDevicePolicy */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */));
}
private static PromptInfo createTestPromptInfo(
boolean requireConfirmation,
Integer authenticators,
- boolean checkDevicePolicy) {
+ boolean checkDevicePolicy,
+ boolean useDefaultSubtitle,
+ boolean deviceCredentialAllowed) {
final PromptInfo promptInfo = new PromptInfo();
promptInfo.setConfirmationRequested(requireConfirmation);
- promptInfo.setUseDefaultSubtitle(true);
+ promptInfo.setUseDefaultSubtitle(useDefaultSubtitle);
if (authenticators != null) {
promptInfo.setAuthenticators(authenticators);
@@ -1864,6 +1913,7 @@ public class BiometricServiceTest {
if (checkDevicePolicy) {
promptInfo.setDisallowBiometricsIfPolicyExists(checkDevicePolicy);
}
+ promptInfo.setDeviceCredentialAllowed(deviceCredentialAllowed);
return promptInfo;
}