Merge "Update Identity Check for Fingerprint Settings" into main

This commit is contained in:
Diya Bera
2025-03-07 09:49:13 -08:00
committed by Android (Google) Code Review
3 changed files with 76 additions and 42 deletions

View File

@@ -27,6 +27,7 @@ import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_AUTHENTICATORS; import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_AUTHENTICATORS;
import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_HIDE_BACKGROUND; import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_HIDE_BACKGROUND;
import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT; import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT;
import static com.android.settings.password.ConfirmDeviceCredentialActivity.EXTRA_DATA;
import android.app.ActionBar; import android.app.ActionBar;
import android.app.Activity; import android.app.Activity;
@@ -1549,7 +1550,29 @@ public final class Utils extends com.android.settingslib.Utils {
final UserManager userManager = (UserManager) fragment.getContext().getSystemService( final UserManager userManager = (UserManager) fragment.getContext().getSystemService(
UserManager.class); UserManager.class);
fragment.startActivityForResult(getIntentForBiometricAuthentication(fragment.getResources(), fragment.startActivityForResult(getIntentForBiometricAuthentication(fragment.getResources(),
getEffectiveUserId(userManager, userId), hideBackground), requestCode); getEffectiveUserId(userManager, userId), hideBackground, null /* data */),
requestCode);
}
/**
* Launch biometric prompt for mandatory biometrics. Call
* {@link #requestBiometricAuthenticationForMandatoryBiometrics(Context, boolean, int)}
* to check if all requirements for mandatory biometrics is satisfied
* before launching biometric prompt.
*
* @param fragment corresponding fragment of the surface
* @param requestCode for starting the new activity
* @param userId user id for the authentication request
* @param hideBackground if the background activity screen needs to be hidden
* @param data additional info to returned to the activity after authentication
* has ended
*/
public static void launchBiometricPromptForMandatoryBiometrics(@NonNull Fragment fragment,
int requestCode, int userId, boolean hideBackground, @Nullable Intent data) {
final UserManager userManager = (UserManager) fragment.getContext().getSystemService(
UserManager.class);
fragment.startActivityForResult(getIntentForBiometricAuthentication(fragment.getResources(),
getEffectiveUserId(userManager, userId), hideBackground, data), requestCode);
} }
/** /**
@@ -1568,7 +1591,7 @@ public final class Utils extends com.android.settingslib.Utils {
final UserManager userManager = activity.getSystemService(UserManager.class); final UserManager userManager = activity.getSystemService(UserManager.class);
activity.startActivityForResult(getIntentForBiometricAuthentication( activity.startActivityForResult(getIntentForBiometricAuthentication(
activity.getResources(), getEffectiveUserId(userManager, userId), activity.getResources(), getEffectiveUserId(userManager, userId),
hideBackground), requestCode); hideBackground, null /* data */), requestCode);
} }
private static int getEffectiveUserId(UserManager userManager, int userId) { private static int getEffectiveUserId(UserManager userManager, int userId) {
@@ -1579,7 +1602,7 @@ public final class Utils extends com.android.settingslib.Utils {
} }
private static Intent getIntentForBiometricAuthentication(Resources resources, private static Intent getIntentForBiometricAuthentication(Resources resources,
int effectiveUserId, boolean hideBackground) { int effectiveUserId, boolean hideBackground, @Nullable Intent data) {
final Intent intent = new Intent(); final Intent intent = new Intent();
if (android.hardware.biometrics.Flags.mandatoryBiometrics()) { if (android.hardware.biometrics.Flags.mandatoryBiometrics()) {
intent.putExtra(BIOMETRIC_PROMPT_AUTHENTICATORS, intent.putExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
@@ -1592,6 +1615,7 @@ public final class Utils extends com.android.settingslib.Utils {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, true); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, true);
intent.putExtra(EXTRA_USER_ID, effectiveUserId); intent.putExtra(EXTRA_USER_ID, effectiveUserId);
intent.putExtra(BIOMETRIC_PROMPT_HIDE_BACKGROUND, hideBackground); intent.putExtra(BIOMETRIC_PROMPT_HIDE_BACKGROUND, hideBackground);
intent.putExtra(EXTRA_DATA, data);
intent.setClassName(SETTINGS_PACKAGE_NAME, intent.setClassName(SETTINGS_PACKAGE_NAME,
ConfirmDeviceCredentialActivity.InternalActivity.class.getName()); ConfirmDeviceCredentialActivity.InternalActivity.class.getName());
return intent; return intent;

View File

@@ -1277,42 +1277,6 @@ public class FingerprintSettings extends SubSettings {
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) { if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
runChallengeGeneratedInvokers(); runChallengeGeneratedInvokers();
if (BiometricUtils.containsGatekeeperPasswordHandle(data)) { if (BiometricUtils.containsGatekeeperPasswordHandle(data)) {
if (!mHasFirstEnrolled && !mIsEnrolling) {
final Activity activity = getActivity();
if (activity != null) {
// Apply pending transition for auto adding first fingerprint case
activity.overridePendingTransition(
com.google.android.setupdesign.R.anim.sud_slide_next_in,
com.google.android.setupdesign.R.anim.sud_slide_next_out);
}
// To have smoother animation, change flow to let next visible activity
// to generateChallenge, then pass it back through activity result.
// Token and challenge will be updated later through the activity result
// of AUTO_ADD_FIRST_FINGERPRINT_REQUEST.
mIsEnrolling = true;
addFirstFingerprint(
BiometricUtils.getGatekeeperPasswordHandle(data));
} else {
mFingerprintManager.generateChallenge(mUserId,
(sensorId, userId, challenge) -> {
final Activity activity = getActivity();
if (activity == null || activity.isFinishing()) {
// Stop everything
Log.w(TAG, "activity detach or finishing");
return;
}
final GatekeeperPasswordProvider provider =
new GatekeeperPasswordProvider(
new LockPatternUtils(activity));
mToken = provider.requestGatekeeperHat(data, challenge,
mUserId);
mChallenge = challenge;
provider.removeGatekeeperPasswordHandle(data, false);
updateAddPreference();
});
}
final Utils.BiometricStatus biometricAuthStatus = final Utils.BiometricStatus biometricAuthStatus =
Utils.requestBiometricAuthenticationForMandatoryBiometrics( Utils.requestBiometricAuthenticationForMandatoryBiometrics(
getActivity(), getActivity(),
@@ -1321,12 +1285,14 @@ public class FingerprintSettings extends SubSettings {
if (biometricAuthStatus == Utils.BiometricStatus.OK) { if (biometricAuthStatus == Utils.BiometricStatus.OK) {
Utils.launchBiometricPromptForMandatoryBiometrics(this, Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST, BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */); mUserId, true /* hideBackground */, data);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) { } else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
IdentityCheckBiometricErrorDialog IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss( .showBiometricErrorDialogAndFinishActivityOnDismiss(
getActivity(), getActivity(),
biometricAuthStatus); biometricAuthStatus);
} else {
handleAuthenticationSuccessful(data);
} }
} else { } else {
Log.d(TAG, "Data null or GK PW missing"); Log.d(TAG, "Data null or GK PW missing");
@@ -1380,7 +1346,9 @@ public class FingerprintSettings extends SubSettings {
updateAddPreference(); updateAddPreference();
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) { } else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false; mBiometricsAuthenticationRequested = false;
if (resultCode != RESULT_OK) { if (resultCode == RESULT_OK) {
handleAuthenticationSuccessful(data);
} else {
if (resultCode if (resultCode
== ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) { == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
IdentityCheckBiometricErrorDialog IdentityCheckBiometricErrorDialog
@@ -1435,6 +1403,45 @@ public class FingerprintSettings extends SubSettings {
} }
} }
private void handleAuthenticationSuccessful(Intent data) {
if (!mHasFirstEnrolled && !mIsEnrolling) {
final Activity activity = getActivity();
if (activity != null) {
// Apply pending transition for auto adding first fingerprint case
activity.overridePendingTransition(
com.google.android.setupdesign.R.anim.sud_slide_next_in,
com.google.android.setupdesign.R.anim.sud_slide_next_out);
}
// To have smoother animation, change flow to let next visible activity
// to generateChallenge, then pass it back through activity result.
// Token and challenge will be updated later through the activity result
// of AUTO_ADD_FIRST_FINGERPRINT_REQUEST.
mIsEnrolling = true;
addFirstFingerprint(
BiometricUtils.getGatekeeperPasswordHandle(data));
} else {
mFingerprintManager.generateChallenge(mUserId,
(sensorId, userId, challenge) -> {
final Activity activity = getActivity();
if (activity == null || activity.isFinishing()) {
// Stop everything
Log.w(TAG, "activity detach or finishing");
return;
}
final GatekeeperPasswordProvider provider =
new GatekeeperPasswordProvider(
new LockPatternUtils(activity));
mToken = provider.requestGatekeeperHat(data, challenge,
mUserId);
mChallenge = challenge;
provider.removeGatekeeperPasswordHandle(data, false);
updateAddPreference();
});
}
}
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();

View File

@@ -84,6 +84,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
"biometric_prompt_negative_button_text"; "biometric_prompt_negative_button_text";
public static final String BIOMETRIC_PROMPT_HIDE_BACKGROUND = public static final String BIOMETRIC_PROMPT_HIDE_BACKGROUND =
"biometric_prompt_hide_background"; "biometric_prompt_hide_background";
public static final String EXTRA_DATA = "extra_data";
public static final int BIOMETRIC_LOCKOUT_ERROR_RESULT = 100; public static final int BIOMETRIC_LOCKOUT_ERROR_RESULT = 100;
public static class InternalActivity extends ConfirmDeviceCredentialActivity { public static class InternalActivity extends ConfirmDeviceCredentialActivity {
@@ -108,6 +109,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
private boolean mGoingToBackground; private boolean mGoingToBackground;
private boolean mWaitingForBiometricCallback; private boolean mWaitingForBiometricCallback;
private int mBiometricsAuthenticators; private int mBiometricsAuthenticators;
private Intent mIntentData;
private Executor mExecutor = (runnable -> { private Executor mExecutor = (runnable -> {
mHandler.post(runnable); mHandler.post(runnable);
@@ -158,7 +160,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
ConfirmDeviceCredentialActivity.this); ConfirmDeviceCredentialActivity.this);
} }
setResult(Activity.RESULT_OK); setResult(Activity.RESULT_OK, mIntentData);
finish(); finish();
} }
@@ -207,6 +209,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
mBiometricsAuthenticators = intent.getIntExtra(BIOMETRIC_PROMPT_AUTHENTICATORS, mBiometricsAuthenticators = intent.getIntExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
BiometricManager.Authenticators.DEVICE_CREDENTIAL BiometricManager.Authenticators.DEVICE_CREDENTIAL
| BiometricManager.Authenticators.BIOMETRIC_WEAK); | BiometricManager.Authenticators.BIOMETRIC_WEAK);
mIntentData = intent.getParcelableExtra(EXTRA_DATA, Intent.class);
final String negativeButtonText = intent.getStringExtra( final String negativeButtonText = intent.getStringExtra(
BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT); BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT);
final boolean frp = final boolean frp =