Merge "Disable combined controller only if all modalities require consent" into sc-v2-dev am: b84b7d586a

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/16265888

Change-Id: Idb41f923cdbe1ebc251a1c033d8066404898f768
This commit is contained in:
TreeHugger Robot
2021-11-18 03:41:27 +00:00
committed by Automerger Merge Worker
5 changed files with 81 additions and 22 deletions

View File

@@ -242,12 +242,11 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
}
}
// start enrollment process if we haven't bailed out yet
if (mParentalOptionsRequired && mParentalOptions == null) {
mParentalConsentHelper = new ParentalConsentHelper(
mIsFaceEnrollable, mIsFingerprintEnrollable, mGkPwHandle);
mParentalConsentHelper = new ParentalConsentHelper(mGkPwHandle);
setOrConfirmCredentialsNow();
} else {
// Start enrollment process if we haven't bailed out yet
startEnroll();
}
}
@@ -263,7 +262,10 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
private void startEnrollWith(@Authenticators.Types int authenticators, boolean setupWizard) {
// If the caller is not setup wizard, and the user has something enrolled, finish.
if (!setupWizard) {
// Allow parental consent flow to skip this check, since one modality could be consented
// and another non-consented. This can also happen if the restriction is applied when
// enrollments already exists.
if (!setupWizard && !mParentalOptionsRequired) {
final BiometricManager bm = getSystemService(BiometricManager.class);
final @BiometricError int result = bm.canAuthenticate(authenticators);
if (result != BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
@@ -330,6 +332,25 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
// single enrollment is handled entirely by the launched activity
// this handles multi enroll or if parental consent is required
if (mParentalConsentHelper != null) {
// Lazily retrieve the values from ParentalControlUtils, since the value may not be
// ready in onCreate.
final boolean faceConsentRequired = ParentalControlsUtils
.parentConsentRequired(this, BiometricAuthenticator.TYPE_FACE) != null;
final boolean fpConsentRequired = ParentalControlsUtils
.parentConsentRequired(this, BiometricAuthenticator.TYPE_FINGERPRINT) != null;
final boolean requestFaceConsent = faceConsentRequired && mHasFeatureFace;
final boolean requestFpConsent = fpConsentRequired && mHasFeatureFingerprint;
Log.d(TAG, "faceConsentRequired: " + faceConsentRequired
+ ", fpConsentRequired: " + fpConsentRequired
+ ", hasFeatureFace: " + mHasFeatureFace
+ ", hasFeatureFingerprint: " + mHasFeatureFingerprint
+ ", faceEnrollable: " + mIsFaceEnrollable
+ ", fpEnrollable: " + mIsFingerprintEnrollable);
mParentalConsentHelper.setConsentRequirement(requestFaceConsent, requestFpConsent);
handleOnActivityResultWhileConsenting(requestCode, resultCode, data);
} else {
handleOnActivityResultWhileEnrolling(requestCode, resultCode, data);
@@ -362,10 +383,18 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
final boolean isStillPrompting = mParentalConsentHelper.launchNext(
this, REQUEST_CHOOSE_OPTIONS, resultCode, data);
if (!isStillPrompting) {
Log.d(TAG, "Enrollment consent options set, starting enrollment");
mParentalOptions = mParentalConsentHelper.getConsentResult();
mParentalConsentHelper = null;
startEnroll();
Log.d(TAG, "Enrollment consent options set, starting enrollment: "
+ mParentalOptions);
// Note that we start enrollment with CONVENIENCE instead of the default
// of WEAK in startEnroll(), since we want to allow enrollment for any
// sensor as long as it has been consented for. We should eventually
// clean up this logic and do something like pass in the parental consent
// result, so that we can request enrollment for specific sensors, but
// that's quite a large and risky change to the startEnrollWith() logic.
startEnrollWith(Authenticators.BIOMETRIC_CONVENIENCE,
WizardManagerHelper.isAnySetupWizard(getIntent()));
}
} else {
Log.d(TAG, "Unknown or cancelled parental consent");

View File

@@ -52,8 +52,8 @@ public class ParentalConsentHelper {
private static final String KEY_FINGERPRINT_CONSENT_STRINGS = "fingerprint_strings";
private static final String KEY_IRIS_CONSENT_STRINGS = "iris_strings";
private final boolean mRequireFace;
private final boolean mRequireFingerprint;
private boolean mRequireFace;
private boolean mRequireFingerprint;
private long mGkPwHandle;
@Nullable
@@ -64,15 +64,19 @@ public class ParentalConsentHelper {
/**
* Helper for aggregating user consent.
*
* @param requireFace if face consent should be shown
* @param requireFingerprint if fingerprint consent should be shown
* @param gkPwHandle for launched intents
*/
public ParentalConsentHelper(boolean requireFace, boolean requireFingerprint,
@Nullable Long gkPwHandle) {
public ParentalConsentHelper(@Nullable Long gkPwHandle) {
mGkPwHandle = gkPwHandle != null ? gkPwHandle : 0L;
}
/**
* @param requireFace if face consent should be shown
* @param requireFingerprint if fingerprint consent should be shown
*/
public void setConsentRequirement(boolean requireFace, boolean requireFingerprint) {
mRequireFace = requireFace;
mRequireFingerprint = requireFingerprint;
mGkPwHandle = gkPwHandle != null ? gkPwHandle : 0L;
}
/**

View File

@@ -104,12 +104,34 @@ public class CombinedBiometricStatusPreferenceController extends
private void updateStateInternal() {
// This controller currently is shown if fingerprint&face exist on the device. If this
// changes in the future, the modalities passed into the below will need to be updated.
updateStateInternal(ParentalControlsUtils.parentConsentRequired(mContext,
BiometricAuthenticator.TYPE_FACE | BiometricAuthenticator.TYPE_FINGERPRINT));
final RestrictedLockUtils.EnforcedAdmin faceAdmin = ParentalControlsUtils
.parentConsentRequired(mContext, BiometricAuthenticator.TYPE_FACE);
final RestrictedLockUtils.EnforcedAdmin fpAdmin = ParentalControlsUtils
.parentConsentRequired(mContext, BiometricAuthenticator.TYPE_FINGERPRINT);
// If the admins are non-null, they are actually always the same. Just the helper class
// we create above always return the admin, instead of a boolean.
final boolean faceConsentRequired = faceAdmin != null;
final boolean fpConsentRequired = fpAdmin != null;
final RestrictedLockUtils.EnforcedAdmin admin = faceAdmin != null ? faceAdmin : fpAdmin;
updateStateInternal(admin, faceConsentRequired, fpConsentRequired);
}
@VisibleForTesting
void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin,
boolean faceConsentRequired, boolean fpConsentRequired) {
// Disable the preference (and show the consent flow) only if consent is required for all
// modalities. Otherwise, users will not be able to enter and modify settings for modalities
// which have already been consented. In any case, the controllers for the modalities which
// have not yet been consented will be disabled in the combined page anyway - users can
// go through the consent+enrollment flow from there.
final boolean disablePreference = faceConsentRequired && fpConsentRequired;
if (!disablePreference) {
enforcedAdmin = null;
}
if (mPreference != null) {
mPreference.setDisabledByAdmin(enforcedAdmin);
}

View File

@@ -104,12 +104,16 @@ public class CombinedBiometricStatusPreferenceControllerTest {
RestrictedLockUtils.EnforcedAdmin admin = mock(RestrictedLockUtils.EnforcedAdmin.class);
mController.mPreference = restrictedPreference;
mController.updateStateInternal(admin);
mController.updateStateInternal(admin, true, true);
verify(restrictedPreference).setDisabledByAdmin(eq(admin));
reset(admin);
mController.updateStateInternal(admin, true, false);
verify(restrictedPreference).setDisabledByAdmin(eq(null));
mController.updateStateInternal(null /* enforcedAdmin */);
verify(restrictedPreference, never()).setDisabledByAdmin(any());
mController.updateStateInternal(admin, false, true);
verify(restrictedPreference).setDisabledByAdmin(eq(null));
mController.updateStateInternal(admin, false, false);
verify(restrictedPreference).setDisabledByAdmin(eq(null));
}
}

View File

@@ -167,8 +167,8 @@ public class ParentalConsentHelperTest {
}
// initial consent status
final ParentalConsentHelper helper =
new ParentalConsentHelper(requireFace, requireFingerprint, gkpw);
final ParentalConsentHelper helper = new ParentalConsentHelper(gkpw);
helper.setConsentRequirement(requireFace, requireFingerprint);
assertThat(ParentalConsentHelper.hasFaceConsent(helper.getConsentResult()))
.isFalse();
assertThat(ParentalConsentHelper.hasFingerprintConsent(helper.getConsentResult()))