(3/N) Biometric error dialog

Add an error dialog to help user recover from biometric error for
for identity check for enrollment, changing LSKF and accessing
biometrics settings

Flag: android.hardware.biometrics.flag.mandatory_biometrics
Bug: 358641110
Bug: 358179610
Test: Manual
Change-Id: Iaf1986d3c1892b6158808bc3ded96145f410dc62
This commit is contained in:
Diya Bera
2024-09-17 17:30:42 +00:00
parent 1c604f29ef
commit fc711494b9
7 changed files with 97 additions and 14 deletions

View File

@@ -58,6 +58,7 @@ import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockPattern;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.transition.TransitionHelper;
@@ -452,7 +453,9 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST, mUserId, true /* hideBackground */);
} else if (biometricStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(this,
biometricStatus);
}
}
} else {
@@ -486,7 +489,11 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
}
break;
case BIOMETRIC_AUTH_REQUEST:
if (resultCode != RESULT_OK) {
if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(this,
Utils.BiometricStatus.LOCKOUT);
} else if (resultCode != RESULT_OK) {
finish();
}
default:

View File

@@ -39,6 +39,7 @@ import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.password.SetupSkipDialog;
import com.google.android.setupcompat.template.FooterBarMixin;
@@ -425,7 +426,9 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST, mUserId, true /* hideBackground */);
} else if (biometricStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(this,
biometricStatus);
}
} else {
setResult(resultCode, data);
@@ -457,9 +460,15 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
}
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
if (resultCode != RESULT_OK) {
if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(this,
Utils.BiometricStatus.LOCKOUT);
} else {
finish();
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}

View File

@@ -50,9 +50,11 @@ public class IdentityCheckBiometricErrorDialog extends InstrumentedDialogFragmen
private static final String KEY_ERROR_CODE = "key_error_code";
private static final String KEY_TWO_FACTOR_AUTHENTICATION = "key_two_factor_authentication";
private static final String KEY_FINISH_ACTIVITY = "key_finish_activity";
private String mActionIdentityCheckSettings = Settings.ACTION_SETTINGS;
@Nullable private BroadcastReceiver mBroadcastReceiver;
private boolean mShouldFinishActivity = false;
@NonNull
@Override
@@ -70,6 +72,9 @@ public class IdentityCheckBiometricErrorDialog extends InstrumentedDialogFragmen
R.string.identity_check_settings_action);
mActionIdentityCheckSettings = identityCheckSettingsAction.isEmpty()
? mActionIdentityCheckSettings : identityCheckSettingsAction;
mShouldFinishActivity = getArguments().getBoolean(
KEY_FINISH_ACTIVITY);
setTitle(customView, isLockoutError);
setBody(customView, isLockoutError, twoFactorAuthentication);
alertDialogBuilder.setView(customView);
@@ -94,31 +99,54 @@ public class IdentityCheckBiometricErrorDialog extends InstrumentedDialogFragmen
}
@Override
public void dismiss() {
super.dismiss();
public void onDestroyView() {
super.onDestroyView();
if (mBroadcastReceiver != null) {
getContext().unregisterReceiver(mBroadcastReceiver);
mBroadcastReceiver = null;
}
if (mShouldFinishActivity && getActivity() != null) {
getActivity().finish();
}
}
/**
* Shows an error dialog to prompt the user to resolve biometric errors for identity check.
* @param fragmentActivity calling activity
* @param errorCode refers to the biometric error
* @param twoFactorAuthentication if the surface requests LSKF before identity check auth
*/
public static void showBiometricErrorDialog(FragmentActivity fragmentActivity,
Utils.BiometricStatus errorCode, boolean twoFactorAuthentication) {
showBiometricErrorDialog(fragmentActivity, errorCode, twoFactorAuthentication,
false /* finishActivityOnDismiss */);
}
/**
* Shows an error dialog to prompt the user to resolve biometric errors for identity check.
* Finishes the activity once the dialog is dismissed.
* @param fragmentActivity calling activity
* @param errorCode refers to the biometric error
*/
public static void showBiometricErrorDialogAndFinishActivityOnDismiss(
FragmentActivity fragmentActivity, Utils.BiometricStatus errorCode) {
showBiometricErrorDialog(fragmentActivity, errorCode, true /* twoFactorAuthentication */,
true /* finishActivityOnDismiss */);
}
private static void showBiometricErrorDialog(FragmentActivity fragmentActivity,
Utils.BiometricStatus errorCode, boolean twoFactorAuthentication,
boolean finishActivityOnDismiss) {
final IdentityCheckBiometricErrorDialog identityCheckBiometricErrorDialog =
new IdentityCheckBiometricErrorDialog();
final Bundle args = new Bundle();
args.putCharSequence(KEY_ERROR_CODE, errorCode.name());
args.putBoolean(KEY_TWO_FACTOR_AUTHENTICATION, twoFactorAuthentication);
args.putBoolean(KEY_FINISH_ACTIVITY, finishActivityOnDismiss);
identityCheckBiometricErrorDialog.setArguments(args);
identityCheckBiometricErrorDialog.show(fragmentActivity.getSupportFragmentManager(),
IdentityCheckBiometricErrorDialog.class.getName());
}
private void setTitle(View view, boolean lockout) {
final TextView titleTextView = view.findViewById(R.id.title);
if (lockout) {

View File

@@ -46,10 +46,12 @@ import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.transition.SettingsTransitionHelper;
@@ -323,7 +325,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
biometricAuthStatus);
return;
}
} else {
@@ -339,10 +343,16 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false;
if (resultCode != RESULT_OK) {
if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
Utils.BiometricStatus.LOCKOUT);
} else {
finish();
}
}
}
}
/**
* Get the preference key of face for passing through credential data to face settings.

View File

@@ -45,9 +45,11 @@ import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -325,7 +327,9 @@ public class FaceSettings extends DashboardFragment {
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
biometricAuthStatus);
}
}
} else if (requestCode == ENROLL_REQUEST) {
@@ -336,10 +340,16 @@ public class FaceSettings extends DashboardFragment {
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false;
if (resultCode != RESULT_OK) {
if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
Utils.BiometricStatus.LOCKOUT);
} else {
finish();
}
}
}
}
@Override
public void onStop() {

View File

@@ -71,12 +71,14 @@ import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.GatekeeperPasswordProvider;
import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtils;
@@ -1010,7 +1012,10 @@ public class FingerprintSettings extends SubSettings {
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(
getActivity(),
biometricAuthStatus);
}
} else {
Log.d(TAG, "Data null or GK PW missing");
@@ -1065,10 +1070,16 @@ public class FingerprintSettings extends SubSettings {
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false;
if (resultCode != RESULT_OK) {
if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
Utils.BiometricStatus.LOCKOUT);
} else {
finish();
}
}
}
}
@Override
public void onDestroy() {

View File

@@ -84,6 +84,7 @@ import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollActivity;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.safetycenter.LockScreenSafetySource;
@@ -500,11 +501,18 @@ public class ChooseLockGeneric extends SettingsActivity {
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
biometricAuthStatus);
}
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
mBiometricsAuthSuccessful = true;
} else if (resultCode
== ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
Utils.BiometricStatus.LOCKOUT);
} else {
finish();
}