Do not request cancel authentication unless currently authenticating

Currently we always send cancel() if ConfirmDeviceCredentialActivity
goes into the background. However, if the biometric state is no longer
authenticating, requesting cancel() in this state will result in an
inconsistent state between BiometricService/client and
ConfirmDeviceCredentials.

BiometricService/client will receive the ERROR_CANCELED message incorrectly,
while ConfirmDeviceCredential is showing / pending user password. When
the password is entered, its result is ignored.

The correct behavior is for ConfirmDeviceCredentialActivity to invoke
cancel() only if it's still authenticating. Otherwise BiometricService
and its client will receive ERROR_CANCELED, instead of the actual password
auth result.

Bug: 138279856

Test: BiometricPromptDemo, enable device credential fallback, get into
      lockout state, successfully enter password. API result is
      success instead of "canceled" now.

Change-Id: I6521e896d0402fe856dc85476f51149c9b3084a8
Merged-In: I6521e896d0402fe856dc85476f51149c9b3084a8
(cherry picked from commit 49c7d0765090750f88f11153dfcf9ec378b0c84d)
diff --git a/src/com/android/settings/password/BiometricFragment.java b/src/com/android/settings/password/BiometricFragment.java
index bd5a10d..66b665b 100644
--- a/src/com/android/settings/password/BiometricFragment.java
+++ b/src/com/android/settings/password/BiometricFragment.java
@@ -58,11 +58,13 @@
     private Bundle mBundle;
     private BiometricPrompt mBiometricPrompt;
     private CancellationSignal mCancellationSignal;
+    private boolean mAuthenticating;
 
     private AuthenticationCallback mAuthenticationCallback =
             new AuthenticationCallback() {
         @Override
         public void onAuthenticationError(int error, @NonNull CharSequence message) {
+            mAuthenticating = false;
             mClientExecutor.execute(() -> {
                 mClientCallback.onAuthenticationError(error, message);
             });
@@ -71,6 +73,7 @@
 
         @Override
         public void onAuthenticationSucceeded(AuthenticationResult result) {
+            mAuthenticating = false;
             mClientExecutor.execute(() -> {
                 mClientCallback.onAuthenticationSucceeded(result);
             });
@@ -134,6 +137,10 @@
         }
     }
 
+    boolean isAuthenticating() {
+        return mAuthenticating;
+    }
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -180,6 +187,7 @@
         mCancellationSignal = new CancellationSignal();
 
         // TODO: CC doesn't use crypto for now
+        mAuthenticating = true;
         mBiometricPrompt.authenticateUser(mCancellationSignal, mClientExecutor,
                 mAuthenticationCallback, mUserId, mCancelCallback);
     }
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index 53841e8..8476f92 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -251,7 +251,10 @@
         if (!isChangingConfigurations()) {
             mGoingToBackground = true;
             if (mBiometricFragment != null) {
-                mBiometricFragment.cancel();
+                Log.d(TAG, "Authenticating: " + mBiometricFragment.isAuthenticating());
+                if (mBiometricFragment.isAuthenticating()) {
+                    mBiometricFragment.cancel();
+                }
             }
 
             if (mIsFallback && !mCCLaunched) {