Fix corner case when auth is canceled but credential was already confirmed
Bug: 145991060
Test: atest AuthControllerTest
Change-Id: I94cd579c47b1299c498e0736d7f584e32d903029
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index e0ca1ac..875619a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -338,7 +338,13 @@
@Override
public void hideAuthenticationDialog() {
- if (DEBUG) Log.d(TAG, "hideAuthenticationDialog");
+ if (DEBUG) Log.d(TAG, "hideAuthenticationDialog: " + mCurrentDialog);
+
+ if (mCurrentDialog == null) {
+ // Could be possible if the caller canceled authentication after credential success
+ // but before the client was notified.
+ return;
+ }
mCurrentDialog.dismissFromSystemServer();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index c0e92e0..65399bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -20,7 +20,6 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
-import static junit.framework.TestCase.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -292,6 +291,24 @@
// Corner case tests
@Test
+ public void testCancelAuthentication_whenCredentialConfirmed_doesntCrash() throws Exception {
+ // It's possible that before the client is notified that credential is confirmed, the client
+ // requests to cancel authentication.
+ //
+ // Test that the following sequence of events does not crash SystemUI:
+ // 1) Credential is confirmed
+ // 2) Client cancels authentication
+
+ showDialog(Authenticators.DEVICE_CREDENTIAL, BiometricPrompt.TYPE_NONE);
+ verify(mDialog1).show(any(), any());
+
+ mAuthController.onDismissed(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED);
+ verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED);
+
+ mAuthController.hideAuthenticationDialog();
+ }
+
+ @Test
public void testShowNewDialog_beforeOldDialogDismissed_SkipsAnimations() {
showDialog(Authenticators.BIOMETRIC_WEAK, BiometricPrompt.TYPE_FACE);
verify(mDialog1).show(any(), any());