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) {
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;
}
}

View File

@@ -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.
*

View File

@@ -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();
}
}

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.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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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));

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 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());
}

View File

@@ -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);