Add mandatory biometric prompt to platform surfaces (5/N)

1. For biometric settings, request biometric prompt only after
   successful credential verification and no auth request after
   enrollment

2. Differentiate between mandatory biometrics ineffective error and
   other biometric errors

Flag: android.hardware.biometrics.flags.mandatory_biometrics
Bug: 358176202
Bug: 358179610
Test: atest UtilsTest DevelopmentSettingsDashboardFragmentTest MainClearTest BuildNumberPreferenceControllerTest CombinedBiometricProfileSettingsTest
Change-Id: I778dd5403dd5ab64d8cc39bd88b22c4d39182e94
This commit is contained in:
Diya Bera
2024-08-12 02:40:37 +00:00
parent 3a71993386
commit 92ea474b86
13 changed files with 205 additions and 136 deletions

View File

@@ -183,13 +183,16 @@ public class MainClear extends InstrumentedFragment implements OnGlobalLayoutLis
if (requestCode == KEYGUARD_REQUEST) { if (requestCode == KEYGUARD_REQUEST) {
final int userId = getActivity().getUserId(); final int userId = getActivity().getUserId();
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(), final Utils.BiometricStatus biometricAuthStatus =
false /* biometricsSuccessfullyAuthenticated */, Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
false /* biometricsAuthenticationRequested */, false /* biometricsAuthenticationRequested */,
userId)) { userId);
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRICS_REQUEST, Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRICS_REQUEST,
userId, false /* hideBackground */); userId, false /* hideBackground */);
return; return;
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
return;
} }
} }

View File

@@ -199,6 +199,15 @@ public final class Utils extends com.android.settingslib.Utils {
return ActivityManager.isUserAMonkey(); return ActivityManager.isUserAMonkey();
} }
/**
* Enum for returning biometric status.
* {@link OK} no error detected when requesting mandatory biometrics authentication
* {@link NOT_ACTIVE} mandatory biometrics is not active
* {@link LOCKOUT} biometric sensors are in lockout mode
* {@link ERROR} corresponds to other errors
*/
public enum BiometricStatus {OK, NOT_ACTIVE, LOCKOUT, ERROR}
/** /**
* Returns whether the device is voice-capable (meaning, it is also a phone). * Returns whether the device is voice-capable (meaning, it is also a phone).
*/ */
@@ -1490,33 +1499,40 @@ public final class Utils extends com.android.settingslib.Utils {
* Request biometric authentication if all requirements for mandatory biometrics is satisfied. * Request biometric authentication if all requirements for mandatory biometrics is satisfied.
* *
* @param context of the corresponding activity/fragment * @param context of the corresponding activity/fragment
* @param biometricsSuccessfullyAuthenticated if the user has already authenticated using
* biometrics
* @param biometricsAuthenticationRequested if the activity/fragment has already requested for * @param biometricsAuthenticationRequested if the activity/fragment has already requested for
* biometric prompt * biometric prompt
* @param userId user id for the authentication request * @param userId user id for the authentication request
* @return true if all requirements for mandatory biometrics is satisfied * @return biometric status when mandatory biometrics authentication is requested
*/ */
public static boolean requestBiometricAuthenticationForMandatoryBiometrics( public static BiometricStatus requestBiometricAuthenticationForMandatoryBiometrics(
@NonNull Context context, @NonNull Context context,
boolean biometricsSuccessfullyAuthenticated,
boolean biometricsAuthenticationRequested, int userId) { boolean biometricsAuthenticationRequested, int userId) {
final BiometricManager biometricManager = context.getSystemService(BiometricManager.class); final BiometricManager biometricManager = context.getSystemService(BiometricManager.class);
if (biometricManager == null) { if (biometricManager == null) {
Log.e(TAG, "Biometric Manager is null."); Log.e(TAG, "Biometric Manager is null.");
return false; return BiometricStatus.NOT_ACTIVE;
} }
final int status = biometricManager.canAuthenticate(userId, final int status = biometricManager.canAuthenticate(userId,
BiometricManager.Authenticators.MANDATORY_BIOMETRICS); BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
return android.hardware.biometrics.Flags.mandatoryBiometrics() if (android.hardware.biometrics.Flags.mandatoryBiometrics()
&& status == BiometricManager.BIOMETRIC_SUCCESS && !biometricsAuthenticationRequested) {
&& !biometricsSuccessfullyAuthenticated switch(status) {
&& !biometricsAuthenticationRequested; case BiometricManager.BIOMETRIC_SUCCESS:
return BiometricStatus.OK;
case BiometricManager.BIOMETRIC_ERROR_LOCKOUT:
return BiometricStatus.LOCKOUT;
case BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE:
return BiometricStatus.NOT_ACTIVE;
default:
return BiometricStatus.ERROR;
}
}
return BiometricStatus.NOT_ACTIVE;
} }
/** /**
* Launch biometric prompt for mandatory biometrics. Call * Launch biometric prompt for mandatory biometrics. Call
* {@link #requestBiometricAuthenticationForMandatoryBiometrics(Context, boolean, boolean, int)} * {@link #requestBiometricAuthenticationForMandatoryBiometrics(Context, boolean, int)}
* to check if all requirements for mandatory biometrics is satisfied * to check if all requirements for mandatory biometrics is satisfied
* before launching biometric prompt. * before launching biometric prompt.
* *

View File

@@ -75,14 +75,11 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
@VisibleForTesting @VisibleForTesting
static final String RETRY_PREFERENCE_BUNDLE = "retry_preference_bundle"; static final String RETRY_PREFERENCE_BUNDLE = "retry_preference_bundle";
private static final String BIOMETRICS_AUTH_REQUESTED = "biometrics_auth_requested"; private static final String BIOMETRICS_AUTH_REQUESTED = "biometrics_auth_requested";
private static final String BIOMETRICS_AUTHENTICATED_SUCCESSFULLY =
"biometrics_authenticated_successfully";
protected int mUserId; protected int mUserId;
protected long mGkPwHandle; protected long mGkPwHandle;
private boolean mConfirmCredential; private boolean mConfirmCredential;
private boolean mBiometricsAuthenticationRequested; private boolean mBiometricsAuthenticationRequested;
private boolean mBiometricsSuccessfullyAuthenticated;
@Nullable private FaceManager mFaceManager; @Nullable private FaceManager mFaceManager;
@Nullable private FingerprintManager mFingerprintManager; @Nullable private FingerprintManager mFingerprintManager;
// Do not finish() if choosing/confirming credential, showing fp/face settings, or launching // Do not finish() if choosing/confirming credential, showing fp/face settings, or launching
@@ -120,9 +117,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(getIntent()); mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(getIntent());
} }
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
if (savedInstanceState != null) { if (savedInstanceState != null) {
mConfirmCredential = savedInstanceState.getBoolean(SAVE_STATE_CONFIRM_CREDETIAL); mConfirmCredential = savedInstanceState.getBoolean(SAVE_STATE_CONFIRM_CREDETIAL);
mDoNotFinishActivity = savedInstanceState.getBoolean(DO_NOT_FINISH_ACTIVITY); mDoNotFinishActivity = savedInstanceState.getBoolean(DO_NOT_FINISH_ACTIVITY);
@@ -135,21 +129,12 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
} }
mBiometricsAuthenticationRequested = savedInstanceState.getBoolean( mBiometricsAuthenticationRequested = savedInstanceState.getBoolean(
BIOMETRICS_AUTH_REQUESTED); BIOMETRICS_AUTH_REQUESTED);
mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
BIOMETRICS_AUTHENTICATED_SUCCESSFULLY);
} }
if (mGkPwHandle == 0L && !mConfirmCredential) { if (mGkPwHandle == 0L && !mConfirmCredential) {
mConfirmCredential = true; mConfirmCredential = true;
launchChooseOrConfirmLock(); launchChooseOrConfirmLock();
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(
getActivity(), mBiometricsSuccessfullyAuthenticated,
mBiometricsAuthenticationRequested, mUserId)) {
mBiometricsAuthenticationRequested = true;
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} }
updateUnlockPhonePreferenceSummary(); updateUnlockPhonePreferenceSummary();
final Preference useInAppsPreference = findPreference(getUseInAppsPreferenceKey()); final Preference useInAppsPreference = findPreference(getUseInAppsPreferenceKey());
@@ -161,13 +146,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested, mUserId)
&& mGkPwHandle != 0L) {
mBiometricsAuthenticationRequested = true;
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
}
if (!mConfirmCredential) { if (!mConfirmCredential) {
mDoNotFinishActivity = false; mDoNotFinishActivity = false;
} }
@@ -204,9 +182,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId); extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge); extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
extras.putBoolean(
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
mBiometricsSuccessfullyAuthenticated);
onFaceOrFingerprintPreferenceTreeClick(preference); onFaceOrFingerprintPreferenceTreeClick(preference);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
if (retry) { if (retry) {
@@ -236,9 +211,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
final Bundle extras = preference.getExtras(); final Bundle extras = preference.getExtras();
extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge); extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
extras.putBoolean(
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
mBiometricsSuccessfullyAuthenticated);
onFaceOrFingerprintPreferenceTreeClick(preference); onFaceOrFingerprintPreferenceTreeClick(preference);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
if (retry) { if (retry) {
@@ -323,8 +295,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
} }
outState.putBoolean(BIOMETRICS_AUTH_REQUESTED, outState.putBoolean(BIOMETRICS_AUTH_REQUESTED,
mBiometricsAuthenticationRequested); mBiometricsAuthenticationRequested);
outState.putBoolean(BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
mBiometricsSuccessfullyAuthenticated);
} }
@Override @Override
@@ -342,6 +312,20 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
com.google.android.setupdesign.R.anim.sud_slide_next_out); com.google.android.setupdesign.R.anim.sud_slide_next_out);
retryPreferenceKey(mRetryPreferenceKey, mRetryPreferenceExtra); retryPreferenceKey(mRetryPreferenceKey, mRetryPreferenceExtra);
} }
final Utils.BiometricStatus biometricAuthStatus =
Utils.requestBiometricAuthenticationForMandatoryBiometrics(
getActivity(),
mBiometricsAuthenticationRequested,
mUserId);
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
mBiometricsAuthenticationRequested = true;
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
return;
}
} else { } else {
Log.d(getLogTag(), "Data null or GK PW missing."); Log.d(getLogTag(), "Data null or GK PW missing.");
finish(); finish();
@@ -354,9 +338,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
mRetryPreferenceExtra = null; mRetryPreferenceExtra = null;
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) { } else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false; mBiometricsAuthenticationRequested = false;
if (resultCode == RESULT_OK) { if (resultCode != RESULT_OK) {
mBiometricsSuccessfullyAuthenticated = true;
} else {
finish(); finish();
} }
} }

View File

@@ -23,7 +23,6 @@ import static com.android.settings.Utils.isPrivateProfile;
import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST; import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST; import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.ENROLL_REQUEST; import static com.android.settings.biometrics.BiometricEnrollBase.ENROLL_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED; import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT; import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT;
@@ -98,7 +97,6 @@ public class FaceSettings extends DashboardFragment {
private boolean mConfirmingPassword; private boolean mConfirmingPassword;
private boolean mBiometricsAuthenticationRequested; private boolean mBiometricsAuthenticationRequested;
private boolean mBiometricsSuccessfullyAuthenticated;
private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> { private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
@@ -150,8 +148,6 @@ public class FaceSettings extends DashboardFragment {
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putByteArray(KEY_TOKEN, mToken); outState.putByteArray(KEY_TOKEN, mToken);
outState.putBoolean(KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED,
mBiometricsSuccessfullyAuthenticated);
} }
@Override @Override
@@ -171,8 +167,6 @@ public class FaceSettings extends DashboardFragment {
mToken = getIntent().getByteArrayExtra(KEY_TOKEN); mToken = getIntent().getByteArrayExtra(KEY_TOKEN);
mSensorId = getIntent().getIntExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, -1); mSensorId = getIntent().getIntExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, -1);
mChallenge = getIntent().getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 0L); mChallenge = getIntent().getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 0L);
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
mUserId = getActivity().getIntent().getIntExtra( mUserId = getActivity().getIntent().getIntExtra(
Intent.EXTRA_USER_ID, UserHandle.myUserId()); Intent.EXTRA_USER_ID, UserHandle.myUserId());
@@ -241,8 +235,6 @@ public class FaceSettings extends DashboardFragment {
if (savedInstanceState != null) { if (savedInstanceState != null) {
mToken = savedInstanceState.getByteArray(KEY_TOKEN); mToken = savedInstanceState.getByteArray(KEY_TOKEN);
mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED);
} }
} }
@@ -288,12 +280,6 @@ public class FaceSettings extends DashboardFragment {
Log.e(TAG, "Password not set"); Log.e(TAG, "Password not set");
finish(); finish();
} }
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested,
mUserId)) {
mBiometricsAuthenticationRequested = true;
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else { } else {
mAttentionController.setToken(mToken); mAttentionController.setToken(mToken);
mEnrollController.setToken(mToken); mEnrollController.setToken(mToken);
@@ -330,6 +316,17 @@ public class FaceSettings extends DashboardFragment {
final boolean hasEnrolled = mFaceManager.hasEnrolledTemplates(mUserId); final boolean hasEnrolled = mFaceManager.hasEnrolledTemplates(mUserId);
mEnrollButton.setVisible(!hasEnrolled); mEnrollButton.setVisible(!hasEnrolled);
mRemoveButton.setVisible(hasEnrolled); mRemoveButton.setVisible(hasEnrolled);
final Utils.BiometricStatus biometricAuthStatus =
Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
mBiometricsAuthenticationRequested,
mUserId);
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
}
} }
} else if (requestCode == ENROLL_REQUEST) { } else if (requestCode == ENROLL_REQUEST) {
if (resultCode == RESULT_TIMEOUT) { if (resultCode == RESULT_TIMEOUT) {
@@ -338,9 +335,7 @@ public class FaceSettings extends DashboardFragment {
} }
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) { } else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false; mBiometricsAuthenticationRequested = false;
if (resultCode == RESULT_OK) { if (resultCode != RESULT_OK) {
mBiometricsSuccessfullyAuthenticated = true;
} else {
finish(); finish();
} }
} }

View File

@@ -239,8 +239,6 @@ public class FingerprintSettings extends SubSettings {
"security_settings_fingerprint_footer"; "security_settings_fingerprint_footer";
private static final String KEY_BIOMETRICS_AUTHENTICATION_REQUESTED = private static final String KEY_BIOMETRICS_AUTHENTICATION_REQUESTED =
"biometrics_authentication_requested"; "biometrics_authentication_requested";
private static final String KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED =
"biometrics_successfully_authenticated";
private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000; private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
private static final int MSG_FINGER_AUTH_SUCCESS = 1001; private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
@@ -276,7 +274,6 @@ public class FingerprintSettings extends SubSettings {
private byte[] mToken; private byte[] mToken;
private boolean mLaunchedConfirm; private boolean mLaunchedConfirm;
private boolean mBiometricsAuthenticationRequested; private boolean mBiometricsAuthenticationRequested;
private boolean mBiometricsSuccessfullyAuthenticated;
private boolean mHasFirstEnrolled = true; private boolean mHasFirstEnrolled = true;
private Drawable mHighlightDrawable; private Drawable mHighlightDrawable;
private int mUserId; private int mUserId;
@@ -451,8 +448,6 @@ public class FingerprintSettings extends SubSettings {
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
mChallenge = activity.getIntent() mChallenge = activity.getIntent()
.getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, -1L); .getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, -1L);
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
mAuthenticateSidecar = (FingerprintAuthenticateSidecar) mAuthenticateSidecar = (FingerprintAuthenticateSidecar)
getFragmentManager().findFragmentByTag(TAG_AUTHENTICATE_SIDECAR); getFragmentManager().findFragmentByTag(TAG_AUTHENTICATE_SIDECAR);
@@ -494,8 +489,6 @@ public class FingerprintSettings extends SubSettings {
mIsEnrolling = savedInstanceState.getBoolean(KEY_IS_ENROLLING, mIsEnrolling); mIsEnrolling = savedInstanceState.getBoolean(KEY_IS_ENROLLING, mIsEnrolling);
mHasFirstEnrolled = savedInstanceState.getBoolean(KEY_HAS_FIRST_ENROLLED, mHasFirstEnrolled = savedInstanceState.getBoolean(KEY_HAS_FIRST_ENROLLED,
mHasFirstEnrolled); mHasFirstEnrolled);
mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED);
mBiometricsAuthenticationRequested = savedInstanceState.getBoolean( mBiometricsAuthenticationRequested = savedInstanceState.getBoolean(
KEY_BIOMETRICS_AUTHENTICATION_REQUESTED); KEY_BIOMETRICS_AUTHENTICATION_REQUESTED);
} }
@@ -506,12 +499,6 @@ public class FingerprintSettings extends SubSettings {
if (mToken == null) { if (mToken == null) {
mLaunchedConfirm = true; mLaunchedConfirm = true;
launchChooseOrConfirmLock(); launchChooseOrConfirmLock();
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested,
mUserId)) {
mBiometricsAuthenticationRequested = true;
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (!mHasFirstEnrolled) { } else if (!mHasFirstEnrolled) {
mIsEnrolling = true; mIsEnrolling = true;
addFirstFingerprint(null); addFirstFingerprint(null);
@@ -801,14 +788,6 @@ public class FingerprintSettings extends SubSettings {
mCalibrator = FeatureFactory.getFeatureFactory().getFingerprintFeatureProvider() mCalibrator = FeatureFactory.getFeatureFactory().getFingerprintFeatureProvider()
.getUdfpsEnrollCalibrator(getActivity().getApplicationContext(), null, null); .getUdfpsEnrollCalibrator(getActivity().getApplicationContext(), null, null);
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested,
mUserId)) {
mBiometricsAuthenticationRequested = true;
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST, mUserId, true /* hideBackground */);
}
} }
private void updatePreferences() { private void updatePreferences() {
@@ -858,8 +837,6 @@ public class FingerprintSettings extends SubSettings {
outState.putBoolean(KEY_HAS_FIRST_ENROLLED, mHasFirstEnrolled); outState.putBoolean(KEY_HAS_FIRST_ENROLLED, mHasFirstEnrolled);
outState.putBoolean(KEY_BIOMETRICS_AUTHENTICATION_REQUESTED, outState.putBoolean(KEY_BIOMETRICS_AUTHENTICATION_REQUESTED,
mBiometricsAuthenticationRequested); mBiometricsAuthenticationRequested);
outState.putBoolean(KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED,
mBiometricsSuccessfullyAuthenticated);
} }
@Override @Override
@@ -1023,6 +1000,18 @@ public class FingerprintSettings extends SubSettings {
updateAddPreference(); updateAddPreference();
}); });
} }
final Utils.BiometricStatus biometricAuthStatus =
Utils.requestBiometricAuthenticationForMandatoryBiometrics(
getActivity(),
mBiometricsAuthenticationRequested,
mUserId);
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
}
} else { } else {
Log.d(TAG, "Data null or GK PW missing"); Log.d(TAG, "Data null or GK PW missing");
finish(); finish();
@@ -1075,9 +1064,7 @@ 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) {
mBiometricsSuccessfullyAuthenticated = true;
} else {
finish(); finish();
} }
} }

View File

@@ -365,12 +365,19 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
if (isChecked != developmentEnabledState) { if (isChecked != developmentEnabledState) {
if (isChecked) { if (isChecked) {
final int userId = getContext().getUserId(); final int userId = getContext().getUserId();
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getContext(),
final Utils.BiometricStatus biometricAuthStatus =
Utils.requestBiometricAuthenticationForMandatoryBiometrics(
getContext(),
mIsBiometricsAuthenticated, mIsBiometricsAuthenticated,
false /* biometricsAuthenticationRequested */, userId)) { userId);
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
mSwitchBar.setChecked(false); mSwitchBar.setChecked(false);
Utils.launchBiometricPromptForMandatoryBiometrics(this, Utils.launchBiometricPromptForMandatoryBiometrics(this,
REQUEST_BIOMETRIC_PROMPT, userId, false /* hideBackground */); REQUEST_BIOMETRIC_PROMPT,
userId, false /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
mSwitchBar.setChecked(false);
} else { } else {
//Reset biometrics once enable dialog is shown //Reset biometrics once enable dialog is shown
mIsBiometricsAuthenticated = false; mIsBiometricsAuthenticated = false;

View File

@@ -225,13 +225,15 @@ public class BuildNumberPreferenceController extends BasePreferenceController im
if (requestCode == REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF if (requestCode == REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF
&& resultCode == Activity.RESULT_OK) { && resultCode == Activity.RESULT_OK) {
final int userId = mContext.getUserId(); final int userId = mContext.getUserId();
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext, final Utils.BiometricStatus biometricAuthStatus =
false /* biometricsSuccessfullyAuthenticated */, Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
false /* biometricsAuthenticationRequested */, false /* biometricsAuthenticationRequested */,
userId)) { userId);
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
Utils.launchBiometricPromptForMandatoryBiometrics(mFragment, Utils.launchBiometricPromptForMandatoryBiometrics(mFragment,
REQUEST_IDENTITY_CHECK_FOR_DEV_PREF, userId, false /* hideBackground */); REQUEST_IDENTITY_CHECK_FOR_DEV_PREF,
} else { userId, false /* hideBackground */);
} else if (biometricAuthStatus == Utils.BiometricStatus.NOT_ACTIVE) {
enableDevelopmentSettings(); enableDevelopmentSettings();
} }
} else if (requestCode == REQUEST_IDENTITY_CHECK_FOR_DEV_PREF } else if (requestCode == REQUEST_IDENTITY_CHECK_FOR_DEV_PREF

View File

@@ -491,11 +491,16 @@ public class ChooseLockGeneric extends SettingsActivity {
? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD) ? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
: null; : null;
updatePreferencesOrFinish(false /* isRecreatingActivity */); updatePreferencesOrFinish(false /* isRecreatingActivity */);
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getContext(), final Utils.BiometricStatus biometricAuthStatus =
mBiometricsAuthSuccessful, mWaitingForConfirmation, mUserId)) { Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
mWaitingForConfirmation = true; false /* biometricsAuthenticationRequested */,
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST, mUserId);
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */); mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
finish();
} }
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) { } else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {

View File

@@ -142,7 +142,7 @@ public class MainClearTest {
when(mMockActivity.getSystemService(BiometricManager.class)).thenReturn(mBiometricManager); when(mMockActivity.getSystemService(BiometricManager.class)).thenReturn(mBiometricManager);
when(mBiometricManager.canAuthenticate(anyInt(), when(mBiometricManager.canAuthenticate(anyInt(),
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS))) eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE); .thenReturn(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE);
} }
@After @After
@@ -388,6 +388,30 @@ public class MainClearTest {
verify(mMainClear, times(0)).showFinalConfirmation(); verify(mMainClear, times(0)).showFinalConfirmation();
} }
@Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testOnActivityResultInternal_keyguardRequestNotTriggeringBiometricPrompt_lockoutError() {
when(mContext.getResources()).thenReturn(mResources);
when(mMockActivity.getSystemService(BiometricManager.class)).thenReturn(mBiometricManager);
when(mResources.getString(anyInt())).thenReturn(TEST_ACCOUNT_NAME);
when(mBiometricManager.canAuthenticate(anyInt(),
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_LOCKOUT);
doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
doNothing().when(mMainClear).startActivityForResult(any(), anyInt());
doReturn(mMockActivity).when(mMainClear).getActivity();
doReturn(mContext).when(mMainClear).getContext();
mMainClear
.onActivityResultInternal(MainClear.KEYGUARD_REQUEST, Activity.RESULT_OK, null);
verify(mMainClear).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
verify(mMainClear, never()).startActivityForResult(any(), eq(MainClear.BIOMETRICS_REQUEST));
verify(mMainClear, never()).establishInitialState();
verify(mMainClear, never()).getAccountConfirmationIntent();
verify(mMainClear, never()).showFinalConfirmation();
}
@Test @Test
public void testOnActivityResultInternal_biometricRequestTriggeringFinalConfirmation() { public void testOnActivityResultInternal_biometricRequestTriggeringFinalConfirmation() {
doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST)); doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST));
@@ -397,10 +421,10 @@ public class MainClearTest {
mMainClear mMainClear
.onActivityResultInternal(MainClear.BIOMETRICS_REQUEST, Activity.RESULT_OK, null); .onActivityResultInternal(MainClear.BIOMETRICS_REQUEST, Activity.RESULT_OK, null);
verify(mMainClear, times(1)).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST)); verify(mMainClear).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST));
verify(mMainClear, times(0)).establishInitialState(); verify(mMainClear, never()).establishInitialState();
verify(mMainClear, times(1)).getAccountConfirmationIntent(); verify(mMainClear).getAccountConfirmationIntent();
verify(mMainClear, times(1)).showFinalConfirmation(); verify(mMainClear).showFinalConfirmation();
} }
@Test @Test

View File

@@ -530,40 +530,40 @@ public class UtilsTest {
@Test @Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS) @EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testRequestBiometricAuthentication_biometricManagerNull_shouldReturnFalse() { public void testRequestBiometricAuthentication_biometricManagerNull_shouldReturnNotActive() {
when(mContext.getSystemService(BiometricManager.class)).thenReturn(null); when(mContext.getSystemService(BiometricManager.class)).thenReturn(null);
assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext, assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
false /* biometricsSuccessfullyAuthenticated */, false /* biometricsAuthenticationRequested */, USER_ID)).isEqualTo(
false /* biometricsAuthenticationRequested */, USER_ID)).isFalse(); Utils.BiometricStatus.NOT_ACTIVE);
} }
@Test @Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS) @EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testRequestBiometricAuthentication_biometricManagerReturnsSuccess_shouldReturnTrue() { public void testRequestBiometricAuthentication_biometricManagerReturnsSuccess_shouldReturnOk() {
when(mBiometricManager.canAuthenticate(USER_ID, when(mBiometricManager.canAuthenticate(USER_ID,
BiometricManager.Authenticators.MANDATORY_BIOMETRICS)) BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS); .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
final boolean requestBiometricAuthenticationForMandatoryBiometrics = final Utils.BiometricStatus requestBiometricAuthenticationForMandatoryBiometrics =
Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext, Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
false /* biometricsSuccessfullyAuthenticated */,
false /* biometricsAuthenticationRequested */, USER_ID); false /* biometricsAuthenticationRequested */, USER_ID);
assertThat(requestBiometricAuthenticationForMandatoryBiometrics).isTrue(); assertThat(requestBiometricAuthenticationForMandatoryBiometrics).isEqualTo(
Utils.BiometricStatus.OK);
} }
@Test @Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS) @EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testRequestBiometricAuthentication_biometricManagerReturnsError_shouldReturnFalse() { public void testRequestBiometricAuthentication_biometricManagerReturnsError_shouldReturnError() {
when(mBiometricManager.canAuthenticate(anyInt(), when(mBiometricManager.canAuthenticate(anyInt(),
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS))) eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE); .thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext, assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
false /* biometricsSuccessfullyAuthenticated */, false /* biometricsAuthenticationRequested */, USER_ID)).isEqualTo(
false /* biometricsAuthenticationRequested */, USER_ID)).isFalse(); Utils.BiometricStatus.ERROR);
} }
@Test @Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS) @EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testRequestBiometricAuthentication_biometricManagerReturnsSuccessForDifferentUser_shouldReturnFalse() { public void testRequestBiometricAuthentication_biometricManagerReturnsSuccessForDifferentUser_shouldReturnError() {
when(mBiometricManager.canAuthenticate(anyInt(), when(mBiometricManager.canAuthenticate(anyInt(),
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS))) eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE); .thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
@@ -571,8 +571,8 @@ public class UtilsTest {
BiometricManager.Authenticators.MANDATORY_BIOMETRICS)) BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS); .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext, assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
false /* biometricsSuccessfullyAuthenticated */, false /* biometricsAuthenticationRequested */, USER_ID)).isEqualTo(
false /* biometricsAuthenticationRequested */, USER_ID)).isFalse(); Utils.BiometricStatus.ERROR);
} }
@Test @Test

View File

@@ -129,7 +129,7 @@ public class CombinedBiometricProfileSettingsTest {
doReturn(mBiometricManager).when(mActivity).getSystemService(BiometricManager.class); doReturn(mBiometricManager).when(mActivity).getSystemService(BiometricManager.class);
when(mBiometricManager.canAuthenticate(anyInt(), when(mBiometricManager.canAuthenticate(anyInt(),
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS))) eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE); .thenReturn(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE);
ReflectionHelpers.setField(mFragment, "mDashboardFeatureProvider", ReflectionHelpers.setField(mFragment, "mDashboardFeatureProvider",
FakeFeatureFactory.setupForTest().dashboardFeatureProvider); FakeFeatureFactory.setupForTest().dashboardFeatureProvider);
@@ -187,6 +187,8 @@ public class CombinedBiometricProfileSettingsTest {
mFragment.onAttach(mContext); mFragment.onAttach(mContext);
mFragment.onCreate(null); mFragment.onCreate(null);
mFragment.onActivityResult(CONFIRM_REQUEST, RESULT_FINISHED,
new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L));
verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(), verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(),
eq(BiometricsSettingsBase.BIOMETRIC_AUTH_REQUEST)); eq(BiometricsSettingsBase.BIOMETRIC_AUTH_REQUEST));

View File

@@ -20,6 +20,8 @@ import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWE
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST; import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment; import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment;
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.CHOOSE_LOCK_GENERIC_REQUEST; import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.CHOOSE_LOCK_GENERIC_REQUEST;
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.KEY_REQUIRE_SCREEN_ON_TO_AUTH; import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.KEY_REQUIRE_SCREEN_ON_TO_AUTH;
@@ -146,7 +148,7 @@ public class FingerprintSettingsFragmentTest {
doReturn(mBiometricManager).when(mContext).getSystemService(BiometricManager.class); doReturn(mBiometricManager).when(mContext).getSystemService(BiometricManager.class);
doReturn(true).when(mFingerprintManager).isHardwareDetected(); doReturn(true).when(mFingerprintManager).isHardwareDetected();
doReturn(mVibrator).when(mContext).getSystemService(Vibrator.class); doReturn(mVibrator).when(mContext).getSystemService(Vibrator.class);
when(mBiometricManager.canAuthenticate( when(mBiometricManager.canAuthenticate(PRIMARY_USER_ID,
BiometricManager.Authenticators.MANDATORY_BIOMETRICS)) BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE); .thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
} }
@@ -170,20 +172,23 @@ public class FingerprintSettingsFragmentTest {
} }
@Test @Test
@Ignore("b/353706169")
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS) @EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testLaunchBiometricPromptForFingerprint() { public void testLaunchBiometricPromptForFingerprint() {
when(mBiometricManager.canAuthenticate( when(mBiometricManager.canAuthenticate(PRIMARY_USER_ID,
BiometricManager.Authenticators.MANDATORY_BIOMETRICS)) BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS); .thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
doNothing().when(mFingerprintManager).generateChallenge(anyInt(), any());
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
setUpFragment(false); setUpFragment(false);
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass( ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
Intent.class); mFragment.onActivityResult(CONFIRM_REQUEST, RESULT_FINISHED,
new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L));
verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(), verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(),
eq(BIOMETRIC_AUTH_REQUEST)); eq(BIOMETRIC_AUTH_REQUEST));
Intent intent = intentArgumentCaptor.getValue(); final Intent intent = intentArgumentCaptor.getValue();
assertThat(intent.getComponent().getClassName()).isEqualTo( assertThat(intent.getComponent().getClassName()).isEqualTo(
ConfirmDeviceCredentialActivity.InternalActivity.class.getName()); ConfirmDeviceCredentialActivity.InternalActivity.class.getName());
} }

View File

@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -32,6 +33,7 @@ import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.Flags; import android.hardware.biometrics.Flags;
import android.os.Looper; import android.os.Looper;
import android.os.UserManager; import android.os.UserManager;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -193,6 +195,7 @@ public class BuildNumberPreferenceControllerTest {
@Test @Test
@UiThreadTest @UiThreadTest
@RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS)
public void onActivityResult_confirmPasswordRequestCompleted_enableDevPref() { public void onActivityResult_confirmPasswordRequestCompleted_enableDevPref() {
when(mUserManager.isAdminUser()).thenReturn(true); when(mUserManager.isAdminUser()).thenReturn(true);
@@ -206,7 +209,6 @@ public class BuildNumberPreferenceControllerTest {
} }
@Test @Test
@UiThreadTest
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
public void onActivityResult_confirmPasswordRequestCompleted_launchBiometricPrompt() { public void onActivityResult_confirmPasswordRequestCompleted_launchBiometricPrompt() {
when(mUserManager.isAdminUser()).thenReturn(true); when(mUserManager.isAdminUser()).thenReturn(true);
@@ -225,6 +227,45 @@ public class BuildNumberPreferenceControllerTest {
eq(BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF)); eq(BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF));
} }
@Test
@UiThreadTest
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
public void onActivityResult_confirmPasswordRequestCompleted_mandatoryBiometricsError() {
when(mUserManager.isAdminUser()).thenReturn(true);
when(mBiometricManager.canAuthenticate(mContext.getUserId(),
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE);
final boolean activityResultHandled = mController.onActivityResult(
BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,
Activity.RESULT_OK,
null);
assertThat(activityResultHandled).isTrue();
verify(mFragment, never()).startActivityForResult(any(),
eq(BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF));
}
@Test
@UiThreadTest
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
public void onActivityResult_confirmPasswordRequestCompleted_lockoutError() {
when(mUserManager.isAdminUser()).thenReturn(true);
when(mBiometricManager.canAuthenticate(mContext.getUserId(),
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_LOCKOUT);
final boolean activityResultHandled = mController.onActivityResult(
BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,
Activity.RESULT_OK,
null);
assertThat(activityResultHandled).isTrue();
verify(mFragment, never()).startActivityForResult(any(),
eq(BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF));
assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse();
}
@Test @Test
public void onActivityResult_confirmBiometricAuthentication_enableDevPref() { public void onActivityResult_confirmBiometricAuthentication_enableDevPref() {
when(mUserManager.isAdminUser()).thenReturn(true); when(mUserManager.isAdminUser()).thenReturn(true);