Files
packages_apps_Settings/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
Joshua Mccloskey e80c5cddd2 BiometricEnrollIntroduction button update
No longer show the "No thanks" button until the user has
scrolled to the bottom of the introduction text.

This applies for both face and fingerprint enroll introduction screens.

Fixes: 189268868
Test: Manual
Change-Id: I0ccf6ae1d329df06f769f05288706ef22183bc21
2021-06-08 22:25:16 -07:00

245 lines
8.6 KiB
Java

/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.biometrics.face;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollIntroduction;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
import java.util.List;
/**
* Provides introductory info about face unlock and prompts the user to agree before starting face
* enrollment.
*/
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FaceEnrollIntroduction";
private FaceManager mFaceManager;
private FaceFeatureProvider mFaceFeatureProvider;
@Override
protected void onCancelButtonClick(View view) {
if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST)) {
super.onCancelButtonClick(view);
}
}
@Override
protected void onSkipButtonClick(View view) {
if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST)) {
super.onSkipButtonClick(view);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ImageView iconGlasses = findViewById(R.id.icon_glasses);
final ImageView iconLooking = findViewById(R.id.icon_looking);
final ImageView iconSecurity = findViewById(R.id.icon_security);
iconGlasses.getBackground().setColorFilter(getIconColorFilter());
iconLooking.getBackground().setColorFilter(getIconColorFilter());
iconSecurity.getBackground().setColorFilter(getIconColorFilter());
mFaceManager = Utils.getFaceManagerOrNull(this);
mFaceFeatureProvider = FeatureFactory.getFactory(getApplicationContext())
.getFaceFeatureProvider();
// This path is an entry point for SetNewPasswordController, e.g.
// adb shell am start -a android.app.action.SET_NEW_PASSWORD
if (mToken == null && BiometricUtils.containsGatekeeperPasswordHandle(getIntent())) {
mFooterBarMixin.getPrimaryButton().setEnabled(false);
// We either block on generateChallenge, or need to gray out the "next" button until
// the challenge is ready. Let's just do this for now.
mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
mToken = BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId, challenge);
mSensorId = sensorId;
mChallenge = challenge;
mFooterBarMixin.getPrimaryButton().setEnabled(true);
});
}
}
@Override
protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
this, DevicePolicyManager.KEYGUARD_DISABLE_FACE, mUserId) != null;
}
@Override
protected int getLayoutResource() {
return R.layout.face_enroll_introduction;
}
@Override
protected int getHeaderResDisabledByAdmin() {
return R.string.security_settings_face_enroll_introduction_title_unlock_disabled;
}
@Override
protected int getHeaderResDefault() {
return R.string.security_settings_face_enroll_introduction_title;
}
@Override
protected int getDescriptionResDisabledByAdmin() {
return R.string.security_settings_face_enroll_introduction_message_unlock_disabled;
}
@Override
protected FooterButton getCancelButton() {
if (mFooterBarMixin != null) {
return mFooterBarMixin.getSecondaryButton();
}
return null;
}
@Override
protected FooterButton getNextButton() {
if (mFooterBarMixin != null) {
return mFooterBarMixin.getPrimaryButton();
}
return null;
}
@Override
protected TextView getErrorTextView() {
return findViewById(R.id.error_text);
}
private boolean maxFacesEnrolled() {
if (mFaceManager != null) {
final List<FaceSensorPropertiesInternal> props =
mFaceManager.getSensorPropertiesInternal();
// This will need to be updated for devices with multiple face sensors.
final int max = props.get(0).maxEnrollmentsPerUser;
final int numEnrolledFaces = mFaceManager.getEnrolledFaces(mUserId).size();
return numEnrolledFaces >= max;
} else {
return false;
}
}
//TODO: Refactor this to something that conveys it is used for getting a string ID.
@Override
protected int checkMaxEnrolled() {
if (mFaceManager != null) {
if (maxFacesEnrolled()) {
return R.string.face_intro_error_max;
}
} else {
return R.string.face_intro_error_unknown;
}
return 0;
}
@Override
protected void getChallenge(GenerateChallengeCallback callback) {
mFaceManager = Utils.getFaceManagerOrNull(this);
if (mFaceManager == null) {
callback.onChallengeGenerated(0, 0, 0L);
return;
}
mFaceManager.generateChallenge(mUserId, callback::onChallengeGenerated);
}
@Override
protected String getExtraKeyForBiometric() {
return ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
}
@Override
protected Intent getEnrollingIntent() {
Intent intent = new Intent(this, FaceEnrollEducation.class);
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
return intent;
}
@Override
protected int getConfirmLockTitleResId() {
return R.string.security_settings_face_preference_title;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.FACE_ENROLL_INTRO;
}
@Override
public void onClick(LinkSpan span) {
// TODO(b/110906762)
}
@Override
protected FooterButton getPrimaryFooterButton() {
if (mFooterBarMixin == null) {
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
}
if (mFooterBarMixin.getPrimaryButton() == null) {
final FooterButton nextButtonBuilder = new FooterButton.Builder(this)
.setText(R.string.security_settings_face_enroll_introduction_agree)
.setButtonType(FooterButton.ButtonType.OPT_IN)
.setListener(this::onNextButtonClick)
.setTheme(R.style.SudGlifButton_Primary)
.build();
mFooterBarMixin.setPrimaryButton(nextButtonBuilder);
}
return mFooterBarMixin.getPrimaryButton();
}
@Override
protected FooterButton getSecondaryFooterButton() {
if (mFooterBarMixin == null) {
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
}
if (mFooterBarMixin.getSecondaryButton() == null) {
final FooterButton noThanksButton = new FooterButton.Builder(this)
.setText(R.string.security_settings_face_enroll_introduction_no_thanks)
.setListener(this::onSkipButtonClick)
.setButtonType(FooterButton.ButtonType.NEXT)
.setTheme(R.style.SudGlifButton_Primary)
.build();
mFooterBarMixin.setSecondaryButton(noThanksButton, true /* usePrimaryStyle */);
}
return mFooterBarMixin.getSecondaryButton();
}
}