From ffa9d87b1f4691e542fc56693350358a16d4fbae Mon Sep 17 00:00:00 2001 From: Curtis Belmonte Date: Thu, 24 Oct 2019 12:55:01 -0700 Subject: [PATCH] Check for null receiver in biometric AuthController We've witnessed at least one crash due to mReceiver being null while trying to handle callbacks such as onTryAgainPressed in AuthController (formerly BiometricDialogImpl). In these cases, not running the callback is likely better than crashing, so this commit adds null-checks where they're currently missing. It also adds unit test cases to exercise the new logic. Test: atest AuthControllerTest Fixes: 143251337 Change-Id: I3c46c7fab0dfe802de499180c7bb0c756f7e652b --- .../systemui/biometrics/AuthController.java | 17 ++++++++++++++--- .../systemui/biometrics/AuthControllerTest.java | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index b758731000259..446ed2572bab2 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -93,8 +93,11 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, Log.w(TAG, "Evicting client due to: " + topPackage); mCurrentDialog.dismissWithoutCallback(true /* animate */); mCurrentDialog = null; - mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL); - mReceiver = null; + if (mReceiver != null) { + mReceiver.onDialogDismissed( + BiometricPrompt.DISMISSED_REASON_USER_CANCEL); + mReceiver = null; + } } } } catch (RemoteException e) { @@ -105,6 +108,10 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, @Override public void onTryAgainPressed() { + if (mReceiver == null) { + Log.e(TAG, "onTryAgainPressed: Receiver is null"); + return; + } try { mReceiver.onTryAgainPressed(); } catch (RemoteException e) { @@ -114,6 +121,10 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, @Override public void onDeviceCredentialPressed() { + if (mReceiver == null) { + Log.e(TAG, "onDeviceCredentialPressed: Receiver is null"); + return; + } try { mReceiver.onDeviceCredentialPressed(); } catch (RemoteException e) { @@ -161,7 +172,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, private void sendResultAndCleanUp(@DismissedReason int reason) { if (mReceiver == null) { - Log.e(TAG, "Receiver is null"); + Log.e(TAG, "sendResultAndCleanUp: Receiver is null"); return; } try { 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 b089b740fc476..85d818ac8be34 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -389,6 +389,20 @@ public class AuthControllerTest extends SysuiTestCase { verify(mReceiver).onDialogDismissed(eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL)); } + @Test + public void testDoesNotCrash_whenTryAgainPressedAfterDismissal() { + showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); + mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED); + mAuthController.onTryAgainPressed(); + } + + @Test + public void testDoesNotCrash_whenDeviceCredentialPressedAfterDismissal() { + showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); + mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED); + mAuthController.onDeviceCredentialPressed(); + } + // Helpers private void showDialog(int authenticators, int biometricModality) {