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:
@@ -183,13 +183,16 @@ public class MainClear extends InstrumentedFragment implements OnGlobalLayoutLis
|
||||
|
||||
if (requestCode == KEYGUARD_REQUEST) {
|
||||
final int userId = getActivity().getUserId();
|
||||
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||
false /* biometricsSuccessfullyAuthenticated */,
|
||||
false /* biometricsAuthenticationRequested */,
|
||||
userId)) {
|
||||
final Utils.BiometricStatus biometricAuthStatus =
|
||||
Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||
false /* biometricsAuthenticationRequested */,
|
||||
userId);
|
||||
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
|
||||
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRICS_REQUEST,
|
||||
userId, false /* hideBackground */);
|
||||
return;
|
||||
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -199,6 +199,15 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
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).
|
||||
*/
|
||||
@@ -1489,34 +1498,41 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
/**
|
||||
* Request biometric authentication if all requirements for mandatory biometrics is satisfied.
|
||||
*
|
||||
* @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
|
||||
* biometric prompt
|
||||
* @param userId user id for the authentication request
|
||||
* @return true if all requirements for mandatory biometrics is satisfied
|
||||
* @param context of the corresponding activity/fragment
|
||||
* @param biometricsAuthenticationRequested if the activity/fragment has already requested for
|
||||
* biometric prompt
|
||||
* @param userId user id for the authentication request
|
||||
* @return biometric status when mandatory biometrics authentication is requested
|
||||
*/
|
||||
public static boolean requestBiometricAuthenticationForMandatoryBiometrics(
|
||||
public static BiometricStatus requestBiometricAuthenticationForMandatoryBiometrics(
|
||||
@NonNull Context context,
|
||||
boolean biometricsSuccessfullyAuthenticated,
|
||||
boolean biometricsAuthenticationRequested, int userId) {
|
||||
final BiometricManager biometricManager = context.getSystemService(BiometricManager.class);
|
||||
if (biometricManager == null) {
|
||||
Log.e(TAG, "Biometric Manager is null.");
|
||||
return false;
|
||||
return BiometricStatus.NOT_ACTIVE;
|
||||
}
|
||||
final int status = biometricManager.canAuthenticate(userId,
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
|
||||
return android.hardware.biometrics.Flags.mandatoryBiometrics()
|
||||
&& status == BiometricManager.BIOMETRIC_SUCCESS
|
||||
&& !biometricsSuccessfullyAuthenticated
|
||||
&& !biometricsAuthenticationRequested;
|
||||
if (android.hardware.biometrics.Flags.mandatoryBiometrics()
|
||||
&& !biometricsAuthenticationRequested) {
|
||||
switch(status) {
|
||||
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
|
||||
* {@link #requestBiometricAuthenticationForMandatoryBiometrics(Context, boolean, boolean, int)}
|
||||
* {@link #requestBiometricAuthenticationForMandatoryBiometrics(Context, boolean, int)}
|
||||
* to check if all requirements for mandatory biometrics is satisfied
|
||||
* before launching biometric prompt.
|
||||
*
|
||||
|
@@ -75,14 +75,11 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
@VisibleForTesting
|
||||
static final String RETRY_PREFERENCE_BUNDLE = "retry_preference_bundle";
|
||||
private static final String BIOMETRICS_AUTH_REQUESTED = "biometrics_auth_requested";
|
||||
private static final String BIOMETRICS_AUTHENTICATED_SUCCESSFULLY =
|
||||
"biometrics_authenticated_successfully";
|
||||
|
||||
protected int mUserId;
|
||||
protected long mGkPwHandle;
|
||||
private boolean mConfirmCredential;
|
||||
private boolean mBiometricsAuthenticationRequested;
|
||||
private boolean mBiometricsSuccessfullyAuthenticated;
|
||||
@Nullable private FaceManager mFaceManager;
|
||||
@Nullable private FingerprintManager mFingerprintManager;
|
||||
// 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());
|
||||
}
|
||||
|
||||
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
|
||||
BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mConfirmCredential = savedInstanceState.getBoolean(SAVE_STATE_CONFIRM_CREDETIAL);
|
||||
mDoNotFinishActivity = savedInstanceState.getBoolean(DO_NOT_FINISH_ACTIVITY);
|
||||
@@ -135,21 +129,12 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
}
|
||||
mBiometricsAuthenticationRequested = savedInstanceState.getBoolean(
|
||||
BIOMETRICS_AUTH_REQUESTED);
|
||||
mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
|
||||
BIOMETRICS_AUTHENTICATED_SUCCESSFULLY);
|
||||
}
|
||||
|
||||
if (mGkPwHandle == 0L && !mConfirmCredential) {
|
||||
mConfirmCredential = true;
|
||||
launchChooseOrConfirmLock();
|
||||
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(
|
||||
getActivity(), mBiometricsSuccessfullyAuthenticated,
|
||||
mBiometricsAuthenticationRequested, mUserId)) {
|
||||
mBiometricsAuthenticationRequested = true;
|
||||
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST,
|
||||
mUserId, true /* hideBackground */);
|
||||
}
|
||||
|
||||
updateUnlockPhonePreferenceSummary();
|
||||
|
||||
final Preference useInAppsPreference = findPreference(getUseInAppsPreferenceKey());
|
||||
@@ -161,13 +146,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
@Override
|
||||
public void 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) {
|
||||
mDoNotFinishActivity = false;
|
||||
}
|
||||
@@ -204,9 +182,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
|
||||
extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
||||
extras.putBoolean(
|
||||
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
|
||||
mBiometricsSuccessfullyAuthenticated);
|
||||
onFaceOrFingerprintPreferenceTreeClick(preference);
|
||||
} catch (IllegalStateException e) {
|
||||
if (retry) {
|
||||
@@ -236,9 +211,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
final Bundle extras = preference.getExtras();
|
||||
extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
||||
extras.putBoolean(
|
||||
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
|
||||
mBiometricsSuccessfullyAuthenticated);
|
||||
onFaceOrFingerprintPreferenceTreeClick(preference);
|
||||
} catch (IllegalStateException e) {
|
||||
if (retry) {
|
||||
@@ -323,8 +295,6 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
}
|
||||
outState.putBoolean(BIOMETRICS_AUTH_REQUESTED,
|
||||
mBiometricsAuthenticationRequested);
|
||||
outState.putBoolean(BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
|
||||
mBiometricsSuccessfullyAuthenticated);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -342,6 +312,20 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
com.google.android.setupdesign.R.anim.sud_slide_next_out);
|
||||
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 {
|
||||
Log.d(getLogTag(), "Data null or GK PW missing.");
|
||||
finish();
|
||||
@@ -354,9 +338,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
mRetryPreferenceExtra = null;
|
||||
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
||||
mBiometricsAuthenticationRequested = false;
|
||||
if (resultCode == RESULT_OK) {
|
||||
mBiometricsSuccessfullyAuthenticated = true;
|
||||
} else {
|
||||
if (resultCode != RESULT_OK) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@@ -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.CONFIRM_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_TIMEOUT;
|
||||
|
||||
@@ -98,7 +97,6 @@ public class FaceSettings extends DashboardFragment {
|
||||
|
||||
private boolean mConfirmingPassword;
|
||||
private boolean mBiometricsAuthenticationRequested;
|
||||
private boolean mBiometricsSuccessfullyAuthenticated;
|
||||
|
||||
private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
|
||||
|
||||
@@ -150,8 +148,6 @@ public class FaceSettings extends DashboardFragment {
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putByteArray(KEY_TOKEN, mToken);
|
||||
outState.putBoolean(KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED,
|
||||
mBiometricsSuccessfullyAuthenticated);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -171,8 +167,6 @@ public class FaceSettings extends DashboardFragment {
|
||||
mToken = getIntent().getByteArrayExtra(KEY_TOKEN);
|
||||
mSensorId = getIntent().getIntExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, -1);
|
||||
mChallenge = getIntent().getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 0L);
|
||||
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
|
||||
EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
|
||||
|
||||
mUserId = getActivity().getIntent().getIntExtra(
|
||||
Intent.EXTRA_USER_ID, UserHandle.myUserId());
|
||||
@@ -241,8 +235,6 @@ public class FaceSettings extends DashboardFragment {
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
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");
|
||||
finish();
|
||||
}
|
||||
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested,
|
||||
mUserId)) {
|
||||
mBiometricsAuthenticationRequested = true;
|
||||
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST,
|
||||
mUserId, true /* hideBackground */);
|
||||
} else {
|
||||
mAttentionController.setToken(mToken);
|
||||
mEnrollController.setToken(mToken);
|
||||
@@ -330,6 +316,17 @@ public class FaceSettings extends DashboardFragment {
|
||||
final boolean hasEnrolled = mFaceManager.hasEnrolledTemplates(mUserId);
|
||||
mEnrollButton.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) {
|
||||
if (resultCode == RESULT_TIMEOUT) {
|
||||
@@ -338,9 +335,7 @@ public class FaceSettings extends DashboardFragment {
|
||||
}
|
||||
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
||||
mBiometricsAuthenticationRequested = false;
|
||||
if (resultCode == RESULT_OK) {
|
||||
mBiometricsSuccessfullyAuthenticated = true;
|
||||
} else {
|
||||
if (resultCode != RESULT_OK) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@@ -239,8 +239,6 @@ public class FingerprintSettings extends SubSettings {
|
||||
"security_settings_fingerprint_footer";
|
||||
private static final String KEY_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_FINGER_AUTH_SUCCESS = 1001;
|
||||
@@ -276,7 +274,6 @@ public class FingerprintSettings extends SubSettings {
|
||||
private byte[] mToken;
|
||||
private boolean mLaunchedConfirm;
|
||||
private boolean mBiometricsAuthenticationRequested;
|
||||
private boolean mBiometricsSuccessfullyAuthenticated;
|
||||
private boolean mHasFirstEnrolled = true;
|
||||
private Drawable mHighlightDrawable;
|
||||
private int mUserId;
|
||||
@@ -451,8 +448,6 @@ public class FingerprintSettings extends SubSettings {
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
mChallenge = activity.getIntent()
|
||||
.getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, -1L);
|
||||
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
|
||||
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
|
||||
|
||||
mAuthenticateSidecar = (FingerprintAuthenticateSidecar)
|
||||
getFragmentManager().findFragmentByTag(TAG_AUTHENTICATE_SIDECAR);
|
||||
@@ -494,8 +489,6 @@ public class FingerprintSettings extends SubSettings {
|
||||
mIsEnrolling = savedInstanceState.getBoolean(KEY_IS_ENROLLING, mIsEnrolling);
|
||||
mHasFirstEnrolled = savedInstanceState.getBoolean(KEY_HAS_FIRST_ENROLLED,
|
||||
mHasFirstEnrolled);
|
||||
mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
|
||||
KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED);
|
||||
mBiometricsAuthenticationRequested = savedInstanceState.getBoolean(
|
||||
KEY_BIOMETRICS_AUTHENTICATION_REQUESTED);
|
||||
}
|
||||
@@ -506,12 +499,6 @@ public class FingerprintSettings extends SubSettings {
|
||||
if (mToken == null) {
|
||||
mLaunchedConfirm = true;
|
||||
launchChooseOrConfirmLock();
|
||||
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested,
|
||||
mUserId)) {
|
||||
mBiometricsAuthenticationRequested = true;
|
||||
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST,
|
||||
mUserId, true /* hideBackground */);
|
||||
} else if (!mHasFirstEnrolled) {
|
||||
mIsEnrolling = true;
|
||||
addFirstFingerprint(null);
|
||||
@@ -801,14 +788,6 @@ public class FingerprintSettings extends SubSettings {
|
||||
|
||||
mCalibrator = FeatureFactory.getFeatureFactory().getFingerprintFeatureProvider()
|
||||
.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() {
|
||||
@@ -858,8 +837,6 @@ public class FingerprintSettings extends SubSettings {
|
||||
outState.putBoolean(KEY_HAS_FIRST_ENROLLED, mHasFirstEnrolled);
|
||||
outState.putBoolean(KEY_BIOMETRICS_AUTHENTICATION_REQUESTED,
|
||||
mBiometricsAuthenticationRequested);
|
||||
outState.putBoolean(KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED,
|
||||
mBiometricsSuccessfullyAuthenticated);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1023,6 +1000,18 @@ public class FingerprintSettings extends SubSettings {
|
||||
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 {
|
||||
Log.d(TAG, "Data null or GK PW missing");
|
||||
finish();
|
||||
@@ -1075,9 +1064,7 @@ public class FingerprintSettings extends SubSettings {
|
||||
updateAddPreference();
|
||||
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
||||
mBiometricsAuthenticationRequested = false;
|
||||
if (resultCode == RESULT_OK) {
|
||||
mBiometricsSuccessfullyAuthenticated = true;
|
||||
} else {
|
||||
if (resultCode != RESULT_OK) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@@ -365,12 +365,19 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
if (isChecked != developmentEnabledState) {
|
||||
if (isChecked) {
|
||||
final int userId = getContext().getUserId();
|
||||
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getContext(),
|
||||
mIsBiometricsAuthenticated,
|
||||
false /* biometricsAuthenticationRequested */, userId)) {
|
||||
|
||||
final Utils.BiometricStatus biometricAuthStatus =
|
||||
Utils.requestBiometricAuthenticationForMandatoryBiometrics(
|
||||
getContext(),
|
||||
mIsBiometricsAuthenticated,
|
||||
userId);
|
||||
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
|
||||
mSwitchBar.setChecked(false);
|
||||
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 {
|
||||
//Reset biometrics once enable dialog is shown
|
||||
mIsBiometricsAuthenticated = false;
|
||||
|
@@ -225,13 +225,15 @@ public class BuildNumberPreferenceController extends BasePreferenceController im
|
||||
if (requestCode == REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF
|
||||
&& resultCode == Activity.RESULT_OK) {
|
||||
final int userId = mContext.getUserId();
|
||||
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||
false /* biometricsSuccessfullyAuthenticated */,
|
||||
false /* biometricsAuthenticationRequested */,
|
||||
userId)) {
|
||||
final Utils.BiometricStatus biometricAuthStatus =
|
||||
Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||
false /* biometricsAuthenticationRequested */,
|
||||
userId);
|
||||
if (biometricAuthStatus == Utils.BiometricStatus.OK) {
|
||||
Utils.launchBiometricPromptForMandatoryBiometrics(mFragment,
|
||||
REQUEST_IDENTITY_CHECK_FOR_DEV_PREF, userId, false /* hideBackground */);
|
||||
} else {
|
||||
REQUEST_IDENTITY_CHECK_FOR_DEV_PREF,
|
||||
userId, false /* hideBackground */);
|
||||
} else if (biometricAuthStatus == Utils.BiometricStatus.NOT_ACTIVE) {
|
||||
enableDevelopmentSettings();
|
||||
}
|
||||
} else if (requestCode == REQUEST_IDENTITY_CHECK_FOR_DEV_PREF
|
||||
|
@@ -491,11 +491,16 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
|
||||
: null;
|
||||
updatePreferencesOrFinish(false /* isRecreatingActivity */);
|
||||
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getContext(),
|
||||
mBiometricsAuthSuccessful, mWaitingForConfirmation, mUserId)) {
|
||||
mWaitingForConfirmation = true;
|
||||
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST,
|
||||
final Utils.BiometricStatus biometricAuthStatus =
|
||||
Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||
false /* biometricsAuthenticationRequested */,
|
||||
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 == BIOMETRIC_AUTH_REQUEST) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
|
@@ -142,7 +142,7 @@ public class MainClearTest {
|
||||
when(mMockActivity.getSystemService(BiometricManager.class)).thenReturn(mBiometricManager);
|
||||
when(mBiometricManager.canAuthenticate(anyInt(),
|
||||
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -388,6 +388,30 @@ public class MainClearTest {
|
||||
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
|
||||
public void testOnActivityResultInternal_biometricRequestTriggeringFinalConfirmation() {
|
||||
doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST));
|
||||
@@ -397,10 +421,10 @@ public class MainClearTest {
|
||||
mMainClear
|
||||
.onActivityResultInternal(MainClear.BIOMETRICS_REQUEST, Activity.RESULT_OK, null);
|
||||
|
||||
verify(mMainClear, times(1)).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST));
|
||||
verify(mMainClear, times(0)).establishInitialState();
|
||||
verify(mMainClear, times(1)).getAccountConfirmationIntent();
|
||||
verify(mMainClear, times(1)).showFinalConfirmation();
|
||||
verify(mMainClear).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST));
|
||||
verify(mMainClear, never()).establishInitialState();
|
||||
verify(mMainClear).getAccountConfirmationIntent();
|
||||
verify(mMainClear).showFinalConfirmation();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -530,40 +530,40 @@ public class UtilsTest {
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void testRequestBiometricAuthentication_biometricManagerNull_shouldReturnFalse() {
|
||||
public void testRequestBiometricAuthentication_biometricManagerNull_shouldReturnNotActive() {
|
||||
when(mContext.getSystemService(BiometricManager.class)).thenReturn(null);
|
||||
assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||
false /* biometricsSuccessfullyAuthenticated */,
|
||||
false /* biometricsAuthenticationRequested */, USER_ID)).isFalse();
|
||||
false /* biometricsAuthenticationRequested */, USER_ID)).isEqualTo(
|
||||
Utils.BiometricStatus.NOT_ACTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void testRequestBiometricAuthentication_biometricManagerReturnsSuccess_shouldReturnTrue() {
|
||||
public void testRequestBiometricAuthentication_biometricManagerReturnsSuccess_shouldReturnOk() {
|
||||
when(mBiometricManager.canAuthenticate(USER_ID,
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
|
||||
final boolean requestBiometricAuthenticationForMandatoryBiometrics =
|
||||
final Utils.BiometricStatus requestBiometricAuthenticationForMandatoryBiometrics =
|
||||
Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||
false /* biometricsSuccessfullyAuthenticated */,
|
||||
false /* biometricsAuthenticationRequested */, USER_ID);
|
||||
assertThat(requestBiometricAuthenticationForMandatoryBiometrics).isTrue();
|
||||
false /* biometricsAuthenticationRequested */, USER_ID);
|
||||
assertThat(requestBiometricAuthenticationForMandatoryBiometrics).isEqualTo(
|
||||
Utils.BiometricStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void testRequestBiometricAuthentication_biometricManagerReturnsError_shouldReturnFalse() {
|
||||
public void testRequestBiometricAuthentication_biometricManagerReturnsError_shouldReturnError() {
|
||||
when(mBiometricManager.canAuthenticate(anyInt(),
|
||||
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||
false /* biometricsSuccessfullyAuthenticated */,
|
||||
false /* biometricsAuthenticationRequested */, USER_ID)).isFalse();
|
||||
false /* biometricsAuthenticationRequested */, USER_ID)).isEqualTo(
|
||||
Utils.BiometricStatus.ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void testRequestBiometricAuthentication_biometricManagerReturnsSuccessForDifferentUser_shouldReturnFalse() {
|
||||
public void testRequestBiometricAuthentication_biometricManagerReturnsSuccessForDifferentUser_shouldReturnError() {
|
||||
when(mBiometricManager.canAuthenticate(anyInt(),
|
||||
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
@@ -571,8 +571,8 @@ public class UtilsTest {
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
|
||||
assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||
false /* biometricsSuccessfullyAuthenticated */,
|
||||
false /* biometricsAuthenticationRequested */, USER_ID)).isFalse();
|
||||
false /* biometricsAuthenticationRequested */, USER_ID)).isEqualTo(
|
||||
Utils.BiometricStatus.ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -129,7 +129,7 @@ public class CombinedBiometricProfileSettingsTest {
|
||||
doReturn(mBiometricManager).when(mActivity).getSystemService(BiometricManager.class);
|
||||
when(mBiometricManager.canAuthenticate(anyInt(),
|
||||
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE);
|
||||
|
||||
ReflectionHelpers.setField(mFragment, "mDashboardFeatureProvider",
|
||||
FakeFeatureFactory.setupForTest().dashboardFeatureProvider);
|
||||
@@ -187,6 +187,8 @@ public class CombinedBiometricProfileSettingsTest {
|
||||
|
||||
mFragment.onAttach(mContext);
|
||||
mFragment.onCreate(null);
|
||||
mFragment.onActivityResult(CONFIRM_REQUEST, RESULT_FINISHED,
|
||||
new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L));
|
||||
|
||||
verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(),
|
||||
eq(BiometricsSettingsBase.BIOMETRIC_AUTH_REQUEST));
|
||||
|
@@ -20,6 +20,8 @@ import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWE
|
||||
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.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.CHOOSE_LOCK_GENERIC_REQUEST;
|
||||
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(true).when(mFingerprintManager).isHardwareDetected();
|
||||
doReturn(mVibrator).when(mContext).getSystemService(Vibrator.class);
|
||||
when(mBiometricManager.canAuthenticate(
|
||||
when(mBiometricManager.canAuthenticate(PRIMARY_USER_ID,
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
}
|
||||
@@ -170,20 +172,23 @@ public class FingerprintSettingsFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/353706169")
|
||||
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void testLaunchBiometricPromptForFingerprint() {
|
||||
when(mBiometricManager.canAuthenticate(
|
||||
when(mBiometricManager.canAuthenticate(PRIMARY_USER_ID,
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
|
||||
|
||||
doNothing().when(mFingerprintManager).generateChallenge(anyInt(), any());
|
||||
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
|
||||
setUpFragment(false);
|
||||
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(
|
||||
Intent.class);
|
||||
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
mFragment.onActivityResult(CONFIRM_REQUEST, RESULT_FINISHED,
|
||||
new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L));
|
||||
|
||||
verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(),
|
||||
eq(BIOMETRIC_AUTH_REQUEST));
|
||||
|
||||
Intent intent = intentArgumentCaptor.getValue();
|
||||
final Intent intent = intentArgumentCaptor.getValue();
|
||||
assertThat(intent.getComponent().getClassName()).isEqualTo(
|
||||
ConfirmDeviceCredentialActivity.InternalActivity.class.getName());
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -32,6 +33,7 @@ import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.Flags;
|
||||
import android.os.Looper;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
@@ -193,6 +195,7 @@ public class BuildNumberPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
@RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void onActivityResult_confirmPasswordRequestCompleted_enableDevPref() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
|
||||
@@ -206,7 +209,6 @@ public class BuildNumberPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||
public void onActivityResult_confirmPasswordRequestCompleted_launchBiometricPrompt() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
@@ -225,6 +227,45 @@ public class BuildNumberPreferenceControllerTest {
|
||||
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
|
||||
public void onActivityResult_confirmBiometricAuthentication_enableDevPref() {
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
|
Reference in New Issue
Block a user