Fix disappearing biometric prompt for the managed profile

In several circumstances, the ConfirmDeviceCredentialActivity
may be started while the device is being unlocked - particularly, when
the managed profile on the device has a separate challenge and the user
is attempting to start an activity associated with the locked, managed
profile. For example, by double-tapping a notification from the managed
profile or trying to reply to such a notification.

When the ConfirmDeviceCredentialActivity is started after the user has
entered the primary lockscreen challenge but before the keyguard is
fully dismissed, the activity may be started and immediately paused.
If the activity then calls finish() in onPause(), the biometric prompt
will disappear and the user will not have a chance to authenticate.

Fix the issue by only calling finish() in onPause() if the biometric
prompt has not been shown.

The flag indicating whether the activity is waiting for biometric
prompt or not needs to be cleared whenever the biometric prompt invokes
the callback, so that the activity will correctly call finish() if the
user does abort authentication.

Bug: 153689182
Bug: 141470517
Test: Manual, set up a work profile and double-tap a work notification
or try to Reply to a work GMail notification.

Change-Id: I9d3d3000b99d0eb4b44b90f5a0c2856db5f32144
This commit is contained in:
Eran Messeri
2020-05-21 18:42:41 +01:00
parent 946e3adeda
commit 4f2090ddc0

View File

@@ -107,6 +107,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
private int mUserId;
private int mCredentialMode;
private boolean mGoingToBackground;
private boolean mWaitingForBiometricCallback;
private Executor mExecutor = (runnable -> {
mHandler.post(runnable);
@@ -116,6 +117,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
if (!mGoingToBackground) {
mWaitingForBiometricCallback = false;
if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED
|| errorCode == BiometricPrompt.BIOMETRIC_ERROR_CANCELED) {
finish();
@@ -123,11 +125,15 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
// All other errors go to some version of CC
showConfirmCredentials();
}
} else if (mWaitingForBiometricCallback) { // mGoingToBackground is true
mWaitingForBiometricCallback = false;
finish();
}
}
@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
mWaitingForBiometricCallback = false;
mTrustManager.setDeviceLockedForUser(mUserId, false);
final boolean isStrongAuth = result.getAuthenticationType()
== BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL;
@@ -142,6 +148,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
@Override
public void onAuthenticationFailed() {
mWaitingForBiometricCallback = false;
mDevicePolicyManager.reportFailedBiometricAttempt(mUserId);
}
@@ -262,6 +269,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
finish();
} else if (launchedBiometric) {
// Keep this activity alive until BiometricPrompt goes away
mWaitingForBiometricCallback = true;
} else {
Log.d(TAG, "No pattern, password or PIN set.");
setResult(Activity.RESULT_OK);
@@ -320,7 +328,9 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
super.onPause();
if (!isChangingConfigurations()) {
mGoingToBackground = true;
finish();
if (!mWaitingForBiometricCallback) {
finish();
}
} else {
mGoingToBackground = false;
}