From 5f1d13e3b01b2dce7bb07141cfe31242e7b1f147 Mon Sep 17 00:00:00 2001 From: Curtis Belmonte Date: Fri, 16 Apr 2021 15:09:03 -0700 Subject: [PATCH] Remove multi-biometric interstitial screen in SUW On devices with multiple biometric sensors, this removes the interstitial screen in Setup Wizard that let the user choose whether to enroll face, fingerprint, or both. Instead, such devices will always show face enrollment followed by fingerprint, with the option to skip either or both. Test: Manually tested all enroll/skip combinations in SUW Fixes: 183720580 Change-Id: I7f045579f732196bde28dd96e9443e4bb4c906ae --- res/layout/biometric_enroll_checkbox.xml | 64 ---------- res/layout/biometric_enroll_layout.xml | 79 ------------ res/values/strings.xml | 20 --- .../biometrics/BiometricEnrollActivity.java | 81 ++---------- .../biometrics/BiometricEnrollCheckbox.java | 115 ------------------ .../settings/biometrics/BiometricUtils.java | 3 +- .../MultiBiometricEnrollHelper.java | 14 +-- 7 files changed, 18 insertions(+), 358 deletions(-) delete mode 100644 res/layout/biometric_enroll_checkbox.xml delete mode 100644 res/layout/biometric_enroll_layout.xml delete mode 100644 src/com/android/settings/biometrics/BiometricEnrollCheckbox.java diff --git a/res/layout/biometric_enroll_checkbox.xml b/res/layout/biometric_enroll_checkbox.xml deleted file mode 100644 index 028b511ff25..00000000000 --- a/res/layout/biometric_enroll_checkbox.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/layout/biometric_enroll_layout.xml b/res/layout/biometric_enroll_layout.xml deleted file mode 100644 index 2f3b34c7a25..00000000000 --- a/res/layout/biometric_enroll_layout.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/values/strings.xml b/res/values/strings.xml index 16c7e188a21..6bf44546f47 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -740,26 +740,6 @@ Screen lock - - - Unlock your phone securely with your face and fingerprint - - You can also sign in to apps and confirm payments - - Set up unlock with: - - Face unlock - - Make unlocking your phone a breeze - - Fingerprint - - Save time unlocking phone in your pocket - - Skip - - Next - Face added diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java index 2985a9d2101..cede6a02351 100644 --- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java +++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java @@ -33,7 +33,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.util.Log; -import android.view.View; import androidx.annotation.Nullable; @@ -45,10 +44,7 @@ import com.android.settings.password.ChooseLockGeneric; import com.android.settings.password.ChooseLockPattern; import com.android.settings.password.ChooseLockSettingsHelper; -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.GlifLayout; import java.util.List; @@ -78,9 +74,9 @@ public class BiometricEnrollActivity extends InstrumentedActivity { private int mUserId = UserHandle.myUserId(); private boolean mConfirmingCredentials; + private boolean mIsFaceEnrollable; + private boolean mIsFingerprintEnrollable; @Nullable private Long mGkPwHandle; - private BiometricEnrollCheckbox mCheckboxFace; - private BiometricEnrollCheckbox mCheckboxFingerprint; @Nullable private MultiBiometricEnrollHelper mMultiBiometricEnrollHelper; @Override @@ -180,6 +176,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity { mConfirmingCredentials = false; if (resultCode == ChooseLockPattern.RESULT_FINISHED) { mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data); + startMultiBiometricEnroll(); } else { Log.d(TAG, "Unknown result for chooseLock: " + resultCode); setResult(resultCode); @@ -190,6 +187,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity { mConfirmingCredentials = false; if (resultCode == RESULT_OK) { mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data); + startMultiBiometricEnroll(); } else { Log.d(TAG, "Unknown result for confirmLock: " + resultCode); finish(); @@ -226,14 +224,6 @@ public class BiometricEnrollActivity extends InstrumentedActivity { } private void setupForMultiBiometricEnroll() { - setContentView(R.layout.biometric_enroll_layout); - - mCheckboxFace = findViewById(R.id.checkbox_face); - mCheckboxFingerprint = findViewById(R.id.checkbox_fingerprint); - - mCheckboxFace.setListener(this::updateNextButton); - mCheckboxFingerprint.setListener(this::updateNextButton); - final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class); final FaceManager faceManager = getSystemService(FaceManager.class); final List fpProperties = @@ -242,39 +232,10 @@ public class BiometricEnrollActivity extends InstrumentedActivity { faceManager.getSensorPropertiesInternal(); // This would need to be updated for devices with multiple sensors of the same modality - final boolean maxFacesEnrolled = faceManager.getEnrolledFaces(mUserId).size() - >= faceProperties.get(0).maxEnrollmentsPerUser; - final boolean maxFingerprintsEnrolled = fingerprintManager.getEnrolledFingerprints(mUserId) - .size() >= fpProperties.get(0).maxEnrollmentsPerUser; - - if (maxFacesEnrolled) { - mCheckboxFace.setEnabled(false); - mCheckboxFace.setDescription(R.string.face_intro_error_max); - } - - if (maxFingerprintsEnrolled) { - mCheckboxFingerprint.setEnabled(false); - mCheckboxFingerprint.setDescription(R.string.fingerprint_intro_error_max); - } - - final FooterBarMixin footerBarMixin = ((GlifLayout) findViewById(R.id.setup_wizard_layout)) - .getMixin(FooterBarMixin.class); - footerBarMixin.setSecondaryButton(new FooterButton.Builder(this) - .setText(R.string.multi_biometric_enroll_skip) - .setListener(this::onButtonNegative) - .setButtonType(FooterButton.ButtonType.SKIP) - .setTheme(R.style.SudGlifButton_Secondary) - .build()); - - footerBarMixin.setPrimaryButton(new FooterButton.Builder(this) - .setText(R.string.multi_biometric_enroll_next) - .setListener(this::onButtonPositive) - .setButtonType(FooterButton.ButtonType.NEXT) - .setTheme(R.style.SudGlifButton_Primary) - .build()); - - footerBarMixin.getSecondaryButton().setVisibility(View.VISIBLE); - footerBarMixin.getPrimaryButton().setVisibility(View.VISIBLE); + mIsFaceEnrollable = faceManager.getEnrolledFaces(mUserId).size() + < faceProperties.get(0).maxEnrollmentsPerUser; + mIsFingerprintEnrollable = fingerprintManager.getEnrolledFingerprints(mUserId).size() + < fpProperties.get(0).maxEnrollmentsPerUser; if (!mConfirmingCredentials && mGkPwHandle == null) { mConfirmingCredentials = true; @@ -286,34 +247,12 @@ public class BiometricEnrollActivity extends InstrumentedActivity { } } - private void updateNextButton(View view) { - final boolean canEnrollAny = canEnrollFace() || canEnrollFingerprint(); - - final FooterBarMixin footerBarMixin = ((GlifLayout) findViewById(R.id.setup_wizard_layout)) - .getMixin(FooterBarMixin.class); - footerBarMixin.getPrimaryButton().setEnabled(canEnrollAny); - } - - private void onButtonPositive(View view) { - // Start the state machine according to checkboxes, taking max enrolled into account + private void startMultiBiometricEnroll() { mMultiBiometricEnrollHelper = new MultiBiometricEnrollHelper(this, mUserId, - canEnrollFace(), canEnrollFingerprint(), mGkPwHandle); + mIsFaceEnrollable, mIsFingerprintEnrollable, mGkPwHandle); mMultiBiometricEnrollHelper.startNextStep(); } - private void onButtonNegative(View view) { - setResult(RESULT_SKIP); - finish(); - } - - private boolean canEnrollFace() { - return mCheckboxFace.isEnabled() && mCheckboxFace.isChecked(); - } - - private boolean canEnrollFingerprint() { - return mCheckboxFingerprint.isEnabled() && mCheckboxFingerprint.isChecked(); - } - private boolean userHasPassword(int userId) { final UserManager userManager = getSystemService(UserManager.class); final int passwordQuality = new LockPatternUtils(this) diff --git a/src/com/android/settings/biometrics/BiometricEnrollCheckbox.java b/src/com/android/settings/biometrics/BiometricEnrollCheckbox.java deleted file mode 100644 index d2ff6349427..00000000000 --- a/src/com/android/settings/biometrics/BiometricEnrollCheckbox.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; - -import com.android.settings.R; - -/** - * Widget contain space for an icon, title, description, and checkbox. On devices with multiple - * biometric sensors, allows users to choose sensors during {@link BiometricEnrollActivity}. - */ -public class BiometricEnrollCheckbox extends LinearLayout { - - @NonNull private final CheckBox mCheckBox; - @NonNull private final TextView mDescriptionView; - @Nullable private View.OnClickListener mListener; - - public BiometricEnrollCheckbox(Context context) { - this(context, null /* attrs */); - } - - public BiometricEnrollCheckbox(Context context, - @Nullable AttributeSet attrs) { - this(context, attrs, 0 /* defStyleAttr */); - } - - public BiometricEnrollCheckbox(Context context, @Nullable AttributeSet attrs, - int defStyleAttr) { - this(context, attrs, defStyleAttr, 0 /* defStyleRes */); - } - - public BiometricEnrollCheckbox(Context context, AttributeSet attrs, int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - - LayoutInflater.from(context).inflate(R.layout.biometric_enroll_checkbox, - this, true /* attachToRoot */); - - mCheckBox = findViewById(R.id.checkbox); - final ImageView iconView = findViewById(R.id.icon); - final TextView titleView = findViewById(R.id.title); - mDescriptionView = findViewById(R.id.description); - - setOnClickListener(view -> { - if (isEnabled()) { - mCheckBox.toggle(); - } - if (mListener != null) { - mListener.onClick(view); - } - }); - - final TypedArray a = context - .obtainStyledAttributes(attrs, R.styleable.BiometricEnrollCheckbox); - try { - final Drawable icon = - a.getDrawable(R.styleable.BiometricEnrollCheckbox_icon); - final CharSequence title = - a.getText(R.styleable.BiometricEnrollCheckbox_title); - final CharSequence description = - a.getText(R.styleable.BiometricEnrollCheckbox_description); - iconView.setImageDrawable(icon); - titleView.setText(title); - mDescriptionView.setText(description); - } finally { - a.recycle(); - } - } - - public void setListener(View.OnClickListener listener) { - mListener = listener; - } - - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - mCheckBox.setEnabled(enabled); - } - - public boolean isChecked() { - return mCheckBox.isChecked(); - } - - public void setDescription(@StringRes int resId) { - mDescriptionView.setText(resId); - } -} diff --git a/src/com/android/settings/biometrics/BiometricUtils.java b/src/com/android/settings/biometrics/BiometricUtils.java index 4f13d0cc484..e12badfd860 100644 --- a/src/com/android/settings/biometrics/BiometricUtils.java +++ b/src/com/android/settings/biometrics/BiometricUtils.java @@ -30,6 +30,7 @@ import android.view.Surface; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; @@ -181,7 +182,7 @@ public class BiometricUtils { * @param hardwareAuthToken HardwareAuthToken from Gatekeeper * @param userId User to request enrollment for */ - public static void launchEnrollForResult(@NonNull BiometricEnrollActivity activity, + public static void launchEnrollForResult(@NonNull FragmentActivity activity, @NonNull Intent intent, int requestCode, @Nullable byte[] hardwareAuthToken, @Nullable Long gkPwHandle, int userId) { if (hardwareAuthToken != null) { diff --git a/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java b/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java index 84128e23e7b..7d3be878e83 100644 --- a/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java +++ b/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java @@ -16,7 +16,6 @@ package com.android.settings.biometrics; -import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.hardware.face.FaceManager; @@ -24,6 +23,7 @@ import android.hardware.fingerprint.FingerprintManager; import android.util.Log; import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentActivity; import com.android.settings.password.ChooseLockSettingsHelper; @@ -39,13 +39,13 @@ public class MultiBiometricEnrollHelper { public static final String EXTRA_ENROLL_AFTER_FACE = "enroll_after_face"; - @NonNull private final BiometricEnrollActivity mActivity; + @NonNull private final FragmentActivity mActivity; private final long mGkPwHandle; private final int mUserId; private final boolean mRequestEnrollFace; private final boolean mRequestEnrollFingerprint; - MultiBiometricEnrollHelper(@NonNull BiometricEnrollActivity activity, int userId, + MultiBiometricEnrollHelper(@NonNull FragmentActivity activity, int userId, boolean enrollFace, boolean enrollFingerprint, long gkPwHandle) { mActivity = activity; mUserId = userId; @@ -108,10 +108,8 @@ public class MultiBiometricEnrollHelper { void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d(TAG, "RequestCode: " + requestCode + " resultCode: " + resultCode); - if (resultCode != Activity.RESULT_CANCELED) { - BiometricUtils.removeGatekeeperPasswordHandle(mActivity, mGkPwHandle); - mActivity.setResult(resultCode); - mActivity.finish(); - } + BiometricUtils.removeGatekeeperPasswordHandle(mActivity, mGkPwHandle); + mActivity.setResult(resultCode); + mActivity.finish(); } }