Move CredentialEnrolledTests to regular CTS
Bug: 152240892
Test: atest CtsBiometricsTestCases
Change-Id: I5434526c856bbc794823122d11262be9095c420f
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 611e911..721410a 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1435,27 +1435,6 @@
</activity>
<activity
- android:name=".biometrics.CredentialEnrolledTests"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/biometric_test_credential_enrolled_label" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data android:name="test_category" android:value="@string/biometric_test_category_credential" />
- <meta-data android:name="test_parent"
- android:value="com.android.cts.verifier.biometrics.BiometricTestList" />
- <meta-data android:name="test_required_features" android:value="android.software.secure_lock_screen" />
- <meta-data android:name="test_excluded_features"
- android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch" />
- <meta-data android:name="display_mode"
- android:value="multi_display_mode" />
- </activity>
-
- <activity
android:name=".biometrics.CredentialCryptoTests"
android:configChanges="keyboardHidden|orientation|screenSize"
android:exported="true"
diff --git a/apps/CtsVerifier/res/layout/biometric_test_credential_enrolled_tests.xml b/apps/CtsVerifier/res/layout/biometric_test_credential_enrolled_tests.xml
deleted file mode 100644
index 41c4e53..0000000
--- a/apps/CtsVerifier/res/layout/biometric_test_credential_enrolled_tests.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <TextView
- style="@style/InstructionsFont"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:gravity="center"
- android:text="@string/biometric_test_credential_enrolled_instructions" />
-
- <Button
- android:id="@+id/enroll_credential_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:text="@string/biometric_test_credential_enroll_button"/>
-
- <Button
- android:id="@+id/bm_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:enabled="false"
- android:text="@string/biometric_test_credential_enrolled_bm_button"/>
-
- <Button
- android:id="@+id/setAllowedAuthenticators_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:enabled="false"
- android:text="@string/biometric_test_credential_enrolled_bp_setAllowedAuthenticators_button"/>
-
- <Button
- android:id="@+id/setDeviceCredentialAllowed_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:enabled="false"
- android:text="@string/biometric_test_credential_enrolled_bp_setDeviceCredentialAllowed_button"/>
- <Button
- android:id="@+id/authenticate_cancellation_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:text="@string/biometric_test_cancellation_button"
- android:enabled="false"/>
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"/>
-
- <include
- layout="@layout/pass_fail_buttons"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index abce310..6755439 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -252,14 +252,6 @@
<string name="biometric_test_category_weak">3) Weak Biometric Tests</string>
<string name="biometric_test_category_combination">4) setUserAuthParams Tests</string>
- <string name="biometric_test_credential_enrolled_label">1b: Credential Enrolled Tests</string>
- <string name="biometric_test_credential_enrolled_instructions">This test checks that apps are able to request credential enrollment, and that the BiometricManager/BiometricPrompt
- APIs return results consistent with credential (PIN/Pattern/Password) state.</string>
- <string name="biometric_test_credential_enroll_button">Enroll credential</string>
- <string name="biometric_test_credential_enrolled_bm_button">Check BiometricManager</string>
- <string name="biometric_test_credential_enrolled_bp_setAllowedAuthenticators_button">Check BiometricPrompt setAllowedAuthenticators(DEVICE_CREDENTIAL)</string>
- <string name="biometric_test_credential_enrolled_bp_setDeviceCredentialAllowed_button">Check BiometricPrompt setDeviceCredentialAllowed(true)</string>
-
<string name="biometric_test_credential_crypto_label">1c: Credential Crypto</string>
<string name="biometric_test_credential_crypto_instructions">This test checks that PIN/Pattern/Password successfully unlocks the relevant KeyStore operations. Please
ensure that you have a PIN/Pattern/Password set up.</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/CredentialEnrolledTests.java b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/CredentialEnrolledTests.java
deleted file mode 100644
index ee866eb..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/CredentialEnrolledTests.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.biometrics;
-
-import android.content.Intent;
-import android.hardware.biometrics.BiometricManager;
-import android.hardware.biometrics.BiometricManager.Authenticators;
-import android.hardware.biometrics.BiometricPrompt;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.Settings;
-import android.widget.Button;
-
-import com.android.cts.verifier.R;
-
-import java.util.concurrent.Executor;
-
-/**
- * This test checks that when a credential is enrolled, and biometrics are not enrolled,
- * BiometricManager and BiometricPrompt receive the correct results.
- */
-public class CredentialEnrolledTests extends AbstractBaseTest {
- private static final String TAG = "CredentialEnrolledTests";
-
- private static final int REQUEST_ENROLL = 1;
-
- private Button mEnrollButton;
- private Button mBiometricManagerButton;
- private Button mBPSetAllowedAuthenticatorsButton;
- private Button mBPSetDeviceCredentialAllowedButton;
- private Button mCancellationButton;
-
- private boolean mEnrollPass;
- private boolean mBiometricManagerPass;
- private boolean mBiometricPromptSetAllowedAuthenticatorsPass;
- private boolean mBiometricPromptSetDeviceCredentialAllowedPass;
- private boolean mCancellationPass;
-
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final Executor mExecutor = mHandler::post;
-
- @Override
- protected String getTag() {
- return TAG;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.biometric_test_credential_enrolled_tests);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- final BiometricManager bm = getSystemService(BiometricManager.class);
-
- mEnrollButton = findViewById(R.id.enroll_credential_button);
- mEnrollButton.setOnClickListener((view) -> {
- final int biometricResult = bm.canAuthenticate(Authenticators.DEVICE_CREDENTIAL);
- if (biometricResult != BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
- showToastAndLog("Please ensure you do not have a PIN/Pattern/Password set");
- return;
- }
-
- requestCredentialEnrollment(REQUEST_ENROLL);
- });
-
- // Test BiometricManager#canAuthenticate(DEVICE_CREDENTIAL)
- mBiometricManagerButton = findViewById(R.id.bm_button);
- mBiometricManagerButton.setOnClickListener((view) -> {
-
- final int biometricResult = bm.canAuthenticate(Authenticators.BIOMETRIC_WEAK);
- switch (biometricResult) {
- case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
- case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
- // OK
- break;
- case BiometricManager.BIOMETRIC_SUCCESS:
- showToastAndLog("Unexpected result: " + biometricResult +
- ". Please make sure the device does not have a biometric enrolled");
- return;
- default:
- showToastAndLog("Unexpected result: " + biometricResult);
- return;
- }
-
- final int credentialResult = bm.canAuthenticate(Authenticators.DEVICE_CREDENTIAL);
- if (credentialResult == BiometricManager.BIOMETRIC_SUCCESS) {
- mBiometricManagerButton.setEnabled(false);
- mBiometricManagerPass = true;
- updatePassButton();
- } else {
- showToastAndLog("Unexpected result: " + credentialResult
- + ". Please make sure the device"
- + " has a PIN/Pattern/Password set");
- }
- });
-
- // Test setAllowedAuthenticators(DEVICE_CREDENTIAL)
- mBPSetAllowedAuthenticatorsButton = findViewById(R.id.setAllowedAuthenticators_button);
- mBPSetAllowedAuthenticatorsButton.setOnClickListener((view) -> {
- BiometricPrompt.Builder builder = new BiometricPrompt.Builder(this);
- builder.setTitle("Title");
- builder.setSubtitle("Subtitle");
- builder.setDescription("Description");
- builder.setAllowedAuthenticators(Authenticators.DEVICE_CREDENTIAL);
- BiometricPrompt bp = builder.build();
- bp.authenticate(new CancellationSignal(), mExecutor,
- new BiometricPrompt.AuthenticationCallback() {
- @Override
- public void onAuthenticationSucceeded(
- BiometricPrompt.AuthenticationResult result) {
- final int authenticator = result.getAuthenticationType();
- if (authenticator ==
- BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL) {
- mBPSetAllowedAuthenticatorsButton.setEnabled(false);
- mBiometricPromptSetAllowedAuthenticatorsPass = true;
- updatePassButton();
- } else {
- showToastAndLog("Unexpected authenticator: " + authenticator);
- }
- }
-
- @Override
- public void onAuthenticationError(int errorCode, CharSequence errString) {
- showToastAndLog("Unexpected error: " + errorCode + ", " + errString);
- }
- });
- });
-
- // Test setDeviceCredentialAllowed(true)
- mBPSetDeviceCredentialAllowedButton = findViewById(R.id.setDeviceCredentialAllowed_button);
- mBPSetDeviceCredentialAllowedButton.setOnClickListener((view) -> {
- BiometricPrompt.Builder builder = new BiometricPrompt.Builder(this);
- builder.setTitle("Title");
- builder.setSubtitle("Subtitle");
- builder.setDescription("Description");
- builder.setDeviceCredentialAllowed(true);
- BiometricPrompt bp = builder.build();
- bp.authenticate(new CancellationSignal(), mExecutor,
- new BiometricPrompt.AuthenticationCallback() {
- @Override
- public void onAuthenticationSucceeded(
- BiometricPrompt.AuthenticationResult result) {
- final int authenticator = result.getAuthenticationType();
- if (authenticator ==
- BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL) {
- mBPSetDeviceCredentialAllowedButton.setEnabled(false);
- mBiometricPromptSetDeviceCredentialAllowedPass = true;
- updatePassButton();
- } else {
- showToastAndLog("Unexpected authenticator: " + authenticator
- + ". Please ensure the device does not have a biometric"
- + " enrolled.");
- }
- }
-
- @Override
- public void onAuthenticationError(int errorCode, CharSequence errString) {
- showToastAndLog("Unexpected error: " + errorCode + ", " + errString);
- }
- });
- });
-
- mCancellationButton = findViewById(R.id.authenticate_cancellation_button);
- mCancellationButton.setOnClickListener((view) -> {
- testCancellationSignal(Authenticators.DEVICE_CREDENTIAL, () -> {
- mCancellationButton.setEnabled(false);
- mCancellationPass = true;
- updatePassButton();
- });
- });
- }
-
- @Override
- protected boolean isOnPauseAllowed() {
- // Allow user to go to Settings, etc to figure out why this test isn't passing.
- return !mBiometricManagerPass;
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == REQUEST_ENROLL) {
- final BiometricManager bm = getSystemService(BiometricManager.class);
- final int result = bm.canAuthenticate(Authenticators.DEVICE_CREDENTIAL);
- if (result == BiometricManager.BIOMETRIC_SUCCESS) {
- mEnrollPass = true;
- mEnrollButton.setEnabled(false);
- mBiometricManagerButton.setEnabled(true);
- mBPSetAllowedAuthenticatorsButton.setEnabled(true);
- mBPSetDeviceCredentialAllowedButton.setEnabled(true);
- mCancellationButton.setEnabled(true);
- } else {
- showToastAndLog("Unexpected result: " + result + ". Please ensure that tapping"
- + " the button sends you to credential enrollment, and that you have"
- + " enrolled a credential.");
- }
- }
- }
-
- private void requestCredentialEnrollment(int requestCode) {
- final Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
- enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
- Authenticators.DEVICE_CREDENTIAL);
-
- startActivityForResult(enrollIntent, requestCode);
- }
-
- private void updatePassButton() {
- if (mEnrollPass && mBiometricManagerPass && mBiometricPromptSetAllowedAuthenticatorsPass
- && mBiometricPromptSetDeviceCredentialAllowedPass && mCancellationPass) {
- showToastAndLog("All tests passed");
- getPassButton().setEnabled(true);
- }
- }
-}
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
index c14cc0e..eccc471 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
@@ -19,7 +19,6 @@
import static android.server.biometrics.Components.CLASS_2_BIOMETRIC_ACTIVITY;
import static android.server.biometrics.Components.CLASS_2_BIOMETRIC_OR_CREDENTIAL_ACTIVITY;
-import static com.android.server.biometrics.nano.BiometricServiceStateProto.STATE_AUTH_IDLE;
import static com.android.server.biometrics.nano.BiometricServiceStateProto.STATE_AUTH_PAUSED;
import static com.android.server.biometrics.nano.BiometricServiceStateProto.STATE_AUTH_STARTED_UI_SHOWING;
import static com.android.server.biometrics.nano.BiometricServiceStateProto.STATE_SHOWING_DEVICE_CREDENTIAL;
@@ -36,7 +35,6 @@
import android.platform.test.annotations.Presubmit;
import android.server.wm.TestJournalProvider;
import android.server.wm.WindowManagerState;
-import android.support.test.uiautomator.UiObject2;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -307,26 +305,8 @@
waitForState(STATE_SHOWING_DEVICE_CREDENTIAL);
}
- // All sensors are idle, BiometricService is waiting for device credential
- state = getCurrentState();
- assertTrue(state.toString(), state.mSensorStates.areAllSensorsIdle());
- assertEquals(state.toString(), STATE_SHOWING_DEVICE_CREDENTIAL, state.mState);
+ successfullyEnterCredential();
- // Wait for any animations to complete. Ideally, this should be reflected in
- // STATE_SHOWING_DEVICE_CREDENTIAL, but SysUI and BiometricService are different processes
- // so we'd need to add some additional plumbing. We can improve this in the future.
- Thread.sleep(1000);
-
- // Enter credential. AuthSession done, authentication callback received
- final UiObject2 passwordField = findView(VIEW_ID_PASSWORD_FIELD);
- Log.d(TAG, "Focusing, entering, submitting credential");
- passwordField.click();
- passwordField.setText(LOCK_CREDENTIAL);
- mDevice.pressEnter();
- waitForState(STATE_AUTH_IDLE);
-
- state = getCurrentState();
- assertEquals(state.toString(), STATE_AUTH_IDLE, state.mState);
callbackState = getCallbackState(journal);
assertEquals(callbackState.toString(), 0, callbackState.mNumAuthRejected);
assertEquals(callbackState.toString(), 1, callbackState.mNumAuthAccepted);
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
index 3594a5d..fb454fc 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
@@ -28,6 +28,7 @@
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricTestSession;
import android.hardware.biometrics.SensorProperties;
+import android.os.CancellationSignal;
import android.platform.test.annotations.Presubmit;
import com.android.server.biometrics.nano.SensorStateProto;
@@ -91,9 +92,8 @@
// Second case above
BiometricPrompt.AuthenticationCallback callback =
mock(BiometricPrompt.AuthenticationCallback.class);
- showCredentialOnlyBiometricPrompt(callback);
- mInstrumentation.waitForIdleSync();
- Utils.waitForIdleService(this::getSensorStates);
+ showCredentialOnlyBiometricPrompt(callback, new CancellationSignal(),
+ false /* shouldShow */);
verify(callback).onAuthenticationError(
eq(BiometricPrompt.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL),
any());
@@ -101,12 +101,62 @@
// Third case above. Since the deprecated API is intended to allow credential in addition
// to biometrics, we should be receiving BIOMETRIC_ERROR_NO_BIOMETRICS.
callback = mock(BiometricPrompt.AuthenticationCallback.class);
- showDeviceCredentialAllowedBiometricPrompt(callback);
- mInstrumentation.waitForIdleSync();
- Utils.waitForIdleService(this::getSensorStates);
+ showDeviceCredentialAllowedBiometricPrompt(callback, new CancellationSignal(),
+ false /* shouldShow */);
verify(callback).onAuthenticationError(
eq(BiometricPrompt.BIOMETRIC_ERROR_NO_BIOMETRICS),
any());
}
+ /**
+ * When device credential is enrolled, check the behavior for
+ * 1) BiometricManager#canAuthenticate(DEVICE_CREDENTIAL)
+ * 2a) Successfully authenticating BiometricPrompt#setAllowedAuthenticators(DEVICE_CREDENTIAL)
+ * 2b) Cancelling authentication for the above
+ * 3a) @deprecated BiometricPrompt#setDeviceCredentialALlowed(true)
+ * 3b) Cancelling authentication for the above
+ * 4) Cancelling auth for options 2) and 3)
+ */
+ @Test
+ public void testWhenCredentialEnrolled() throws Exception {
+ try (CredentialSession session = new CredentialSession()) {
+ session.setCredential();
+
+ // First case above
+ final int result = mBiometricManager.canAuthenticate(BiometricManager
+ .Authenticators.DEVICE_CREDENTIAL);
+ assertEquals(BiometricManager.BIOMETRIC_SUCCESS, result);
+
+ // 2a above
+ BiometricPrompt.AuthenticationCallback callback =
+ mock(BiometricPrompt.AuthenticationCallback.class);
+ showCredentialOnlyBiometricPrompt(callback, new CancellationSignal(),
+ true /* shouldShow */);
+ successfullyEnterCredential();
+ verify(callback).onAuthenticationSucceeded(any());
+
+ // 2b above
+ CancellationSignal cancel = new CancellationSignal();
+ callback = mock(BiometricPrompt.AuthenticationCallback.class);
+ showCredentialOnlyBiometricPrompt(callback, cancel, true /* shouldShow */);
+ cancelAuthentication(cancel);
+ verify(callback).onAuthenticationError(eq(BiometricPrompt.BIOMETRIC_ERROR_CANCELED),
+ any());
+
+ // 3a above
+ callback = mock(BiometricPrompt.AuthenticationCallback.class);
+ showDeviceCredentialAllowedBiometricPrompt(callback, new CancellationSignal(),
+ true /* shouldShow */);
+ successfullyEnterCredential();
+ verify(callback).onAuthenticationSucceeded(any());
+
+ // 3b above
+ cancel = new CancellationSignal();
+ callback = mock(BiometricPrompt.AuthenticationCallback.class);
+ showDeviceCredentialAllowedBiometricPrompt(callback, cancel, true /* shouldShow */);
+ cancelAuthentication(cancel);
+ verify(callback).onAuthenticationError(eq(BiometricPrompt.BIOMETRIC_ERROR_CANCELED),
+ any());
+ }
+ }
}
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
index 4724232..0484357 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
@@ -25,9 +25,11 @@
import static com.android.server.biometrics.nano.BiometricServiceStateProto.STATE_AUTH_IDLE;
import static com.android.server.biometrics.nano.BiometricServiceStateProto.STATE_AUTH_PENDING_CONFIRM;
import static com.android.server.biometrics.nano.BiometricServiceStateProto.STATE_AUTH_STARTED_UI_SHOWING;
+import static com.android.server.biometrics.nano.BiometricServiceStateProto.STATE_SHOWING_DEVICE_CREDENTIAL;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
@@ -196,6 +198,37 @@
}
}
+ protected void successfullyEnterCredential() throws Exception {
+ waitForState(STATE_SHOWING_DEVICE_CREDENTIAL);
+ BiometricServiceState state = getCurrentState();
+ assertTrue(state.toString(), state.mSensorStates.areAllSensorsIdle());
+ assertEquals(state.toString(), STATE_SHOWING_DEVICE_CREDENTIAL, state.mState);
+
+ // Wait for any animations to complete. Ideally, this should be reflected in
+ // STATE_SHOWING_DEVICE_CREDENTIAL, but SysUI and BiometricService are different processes
+ // so we'd need to add some additional plumbing. We can improve this in the future.
+ Thread.sleep(1000);
+
+ // Enter credential. AuthSession done, authentication callback received
+ final UiObject2 passwordField = findView(VIEW_ID_PASSWORD_FIELD);
+ Log.d(TAG, "Focusing, entering, submitting credential");
+ passwordField.click();
+ passwordField.setText(LOCK_CREDENTIAL);
+ mDevice.pressEnter();
+ waitForState(STATE_AUTH_IDLE);
+
+ state = getCurrentState();
+ assertEquals(state.toString(), STATE_AUTH_IDLE, state.mState);
+ }
+
+ protected void cancelAuthentication(@NonNull CancellationSignal cancel) throws Exception {
+ cancel.cancel();
+ mInstrumentation.waitForIdleSync();
+ waitForState(STATE_AUTH_IDLE);
+ BiometricServiceState state = getCurrentState();
+ assertEquals("Not idle after requesting cancellation", state.mState, STATE_AUTH_IDLE);
+ }
+
protected void waitForAllUnenrolled() throws Exception {
for (int i = 0; i < 20; i++) {
if (anyEnrollmentsExist()) {
@@ -212,7 +245,9 @@
* Shows a BiometricPrompt that specifies {@link Authenticators#DEVICE_CREDENTIAL}.
*/
protected void showCredentialOnlyBiometricPrompt(
- @NonNull BiometricPrompt.AuthenticationCallback callback) {
+ @NonNull BiometricPrompt.AuthenticationCallback callback,
+ @NonNull CancellationSignal cancellationSignal,
+ boolean shouldShow) throws Exception {
final Handler handler = new Handler(Looper.getMainLooper());
final Executor executor = handler::post;
final BiometricPrompt prompt = new BiometricPrompt.Builder(mContext)
@@ -223,7 +258,16 @@
.setAllowBackgroundAuthentication(true)
.build();
- prompt.authenticate(new CancellationSignal(), executor, callback);
+ prompt.authenticate(cancellationSignal, executor, callback);
+
+ mInstrumentation.waitForIdleSync();
+ if (shouldShow) {
+ waitForState(STATE_SHOWING_DEVICE_CREDENTIAL);
+ BiometricServiceState state = getCurrentState();
+ assertEquals(state.toString(), STATE_SHOWING_DEVICE_CREDENTIAL, state.mState);
+ } else {
+ Utils.waitForIdleService(this::getSensorStates);
+ }
}
/**
@@ -231,7 +275,9 @@
* {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)} to true.
*/
protected void showDeviceCredentialAllowedBiometricPrompt(
- @NonNull BiometricPrompt.AuthenticationCallback callback) {
+ @NonNull BiometricPrompt.AuthenticationCallback callback,
+ @NonNull CancellationSignal cancellationSignal,
+ boolean shouldShow) throws Exception {
final Handler handler = new Handler(Looper.getMainLooper());
final Executor executor = handler::post;
final BiometricPrompt prompt = new BiometricPrompt.Builder(mContext)
@@ -242,7 +288,16 @@
.setAllowBackgroundAuthentication(true)
.build();
- prompt.authenticate(new CancellationSignal(), executor, callback);
+ prompt.authenticate(cancellationSignal, executor, callback);
+
+ mInstrumentation.waitForIdleSync();
+ if (shouldShow) {
+ waitForState(STATE_SHOWING_DEVICE_CREDENTIAL);
+ BiometricServiceState state = getCurrentState();
+ assertEquals(state.toString(), STATE_SHOWING_DEVICE_CREDENTIAL, state.mState);
+ } else {
+ Utils.waitForIdleService(this::getSensorStates);
+ }
}
/**