summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings')
-rw-r--r--src/com/android/settings/EncryptionInterstitial.java8
-rw-r--r--src/com/android/settings/biometrics/BiometricEnrollActivity.java314
-rw-r--r--src/com/android/settings/biometrics/BiometricEnrollBase.java8
-rw-r--r--src/com/android/settings/biometrics/BiometricEnrollCheckbox.java115
-rw-r--r--src/com/android/settings/biometrics/BiometricEnrollIntroduction.java35
-rw-r--r--src/com/android/settings/biometrics/BiometricUtils.java197
-rw-r--r--src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java113
-rw-r--r--src/com/android/settings/biometrics/face/FaceEnrollEducation.java2
-rw-r--r--src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java60
-rw-r--r--src/com/android/settings/biometrics/face/FaceSettings.java2
-rw-r--r--src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java5
-rw-r--r--src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java26
-rw-r--r--src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java2
-rw-r--r--src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java30
-rw-r--r--src/com/android/settings/password/ChooseLockGeneric.java41
-rw-r--r--src/com/android/settings/password/ChooseLockPassword.java47
-rw-r--r--src/com/android/settings/password/ChooseLockPattern.java18
-rw-r--r--src/com/android/settings/password/ChooseLockSettingsHelper.java4
-rw-r--r--src/com/android/settings/password/SetNewPasswordController.java39
-rw-r--r--src/com/android/settings/password/SetupChooseLockGeneric.java7
-rw-r--r--src/com/android/settings/password/SetupChooseLockPassword.java25
-rw-r--r--src/com/android/settings/password/SetupChooseLockPattern.java25
-rw-r--r--src/com/android/settings/password/SetupSkipDialog.java29
23 files changed, 956 insertions, 196 deletions
diff --git a/src/com/android/settings/EncryptionInterstitial.java b/src/com/android/settings/EncryptionInterstitial.java
index 7a11053c57..c65cda7bda 100644
--- a/src/com/android/settings/EncryptionInterstitial.java
+++ b/src/com/android/settings/EncryptionInterstitial.java
@@ -111,6 +111,8 @@ public class EncryptionInterstitial extends SettingsActivity {
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
final boolean forFace = getActivity().getIntent()
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
+ final boolean forBiometrics = getActivity().getIntent()
+ .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
Intent intent = getActivity().getIntent();
mRequestedPasswordQuality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
mUnlockMethodIntent = intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
@@ -121,6 +123,8 @@ public class EncryptionInterstitial extends SettingsActivity {
R.string.encryption_interstitial_message_pattern_for_fingerprint :
forFace ?
R.string.encryption_interstitial_message_pattern_for_face :
+ forBiometrics ?
+ R.string.encryption_interstitial_message_pattern_for_biometrics :
R.string.encryption_interstitial_message_pattern;
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
@@ -129,6 +133,8 @@ public class EncryptionInterstitial extends SettingsActivity {
R.string.encryption_interstitial_message_pin_for_fingerprint :
forFace ?
R.string.encryption_interstitial_message_pin_for_face :
+ forBiometrics ?
+ R.string.encryption_interstitial_message_pin_for_biometrics :
R.string.encryption_interstitial_message_pin;
break;
default:
@@ -136,6 +142,8 @@ public class EncryptionInterstitial extends SettingsActivity {
R.string.encryption_interstitial_message_password_for_fingerprint :
forFace ?
R.string.encryption_interstitial_message_password_for_face :
+ forBiometrics ?
+ R.string.encryption_interstitial_message_password_for_biometrics :
R.string.encryption_interstitial_message_password;
break;
}
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index 35a4546953..f6f44a8386 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -21,23 +21,36 @@ import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricManager.Authenticators;
+import android.hardware.face.FaceManager;
+import android.hardware.face.FaceSensorProperties;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintSensorProperties;
import android.os.Bundle;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
+import android.view.View;
+import androidx.annotation.Nullable;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
-import com.android.settings.biometrics.face.FaceEnrollIntroduction;
-import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor;
-import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
-import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollIntroduction;
import com.android.settings.core.InstrumentedActivity;
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;
/**
* Trampoline activity launched by the {@code android.settings.BIOMETRIC_ENROLL} action which
@@ -49,18 +62,53 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
private static final String TAG = "BiometricEnrollActivity";
+ private static final int REQUEST_CHOOSE_LOCK = 1;
+ private static final int REQUEST_CONFIRM_LOCK = 2;
+
+ public static final int RESULT_SKIP = BiometricEnrollBase.RESULT_SKIP;
+
// Intent extra. If true, biometric enrollment should skip introductory screens. Currently
// this only applies to fingerprint.
public static final String EXTRA_SKIP_INTRO = "skip_intro";
+ private static final String SAVED_STATE_CONFIRMING_CREDENTIALS = "confirming_credentials";
+ private static final String SAVED_STATE_GK_PW_HANDLE = "gk_pw_handle";
+
public static final class InternalActivity extends BiometricEnrollActivity {}
+ private int mUserId = UserHandle.myUserId();
+ private boolean mConfirmingCredentials;
+ @Nullable private Long mGkPwHandle;
+ private BiometricEnrollCheckbox mCheckboxFace;
+ private BiometricEnrollCheckbox mCheckboxFingerprint;
+ @Nullable private MultiBiometricEnrollHelper mMultiBiometricEnrollHelper;
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (this instanceof InternalActivity) {
+ mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
+ }
+
+ if (savedInstanceState != null) {
+ mConfirmingCredentials = savedInstanceState
+ .getBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, false);
+ if (savedInstanceState.containsKey(SAVED_STATE_GK_PW_HANDLE)) {
+ mGkPwHandle = savedInstanceState.getLong(SAVED_STATE_GK_PW_HANDLE);
+ }
+ }
+
+ // Put the theme in the intent so it gets propagated to other activities in the flow
+ final Intent intent = getIntent();
+ if (intent.getStringExtra(WizardManagerHelper.EXTRA_THEME) == null) {
+ intent.putExtra(
+ WizardManagerHelper.EXTRA_THEME,
+ SetupWizardUtils.getThemeString(intent));
+ }
+
// Default behavior is to enroll BIOMETRIC_WEAK or above. See ACTION_BIOMETRIC_ENROLL.
- final int authenticators = getIntent().getIntExtra(
+ final int authenticators = intent.getIntExtra(
Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK);
Log.d(TAG, "Authenticators: " + authenticators);
@@ -73,9 +121,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
if (isSetupWizard) {
if (hasFeatureFace && hasFeatureFingerprint) {
- // TODO(b/162341940, b/152242790) this should show a multi-biometric selection
- // screen
- launchFingerprintOnlyEnroll();
+ setupForMultiBiometricEnroll();
} else if (hasFeatureFace) {
launchFaceOnlyEnroll();
} else if (hasFeatureFingerprint) {
@@ -98,9 +144,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
if (authenticators == BiometricManager.Authenticators.DEVICE_CREDENTIAL) {
launchCredentialOnlyEnroll();
} else if (hasFeatureFace && hasFeatureFingerprint) {
- // TODO(b/162341940, b/152242790) this should show a multi-biometric selection
- // screen
- launchFingerprintOnlyEnroll();
+ setupForMultiBiometricEnroll();
} else if (hasFeatureFingerprint) {
launchFingerprintOnlyEnroll();
} else if (hasFeatureFace) {
@@ -112,30 +156,216 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
}
}
+ @Override
+ protected void onSaveInstanceState(@NonNull Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, mConfirmingCredentials);
+ if (mGkPwHandle != null) {
+ outState.putLong(SAVED_STATE_GK_PW_HANDLE, mGkPwHandle);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (mMultiBiometricEnrollHelper == null) {
+ overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
+
+ switch (requestCode) {
+ case REQUEST_CHOOSE_LOCK:
+ mConfirmingCredentials = false;
+ if (resultCode == ChooseLockPattern.RESULT_FINISHED) {
+ mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data);
+ } else {
+ Log.d(TAG, "Unknown result for chooseLock: " + resultCode);
+ setResult(resultCode);
+ finish();
+ }
+ break;
+ case REQUEST_CONFIRM_LOCK:
+ mConfirmingCredentials = false;
+ if (resultCode == RESULT_OK) {
+ mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data);
+ } else {
+ Log.d(TAG, "Unknown result for confirmLock: " + resultCode);
+ finish();
+ }
+ break;
+ default:
+ Log.d(TAG, "Unknown requestCode: " + requestCode + ", finishing");
+ finish();
+ }
+ } else {
+ mMultiBiometricEnrollHelper.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ @Override
+ protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
+ resid = SetupWizardUtils.getTheme(getIntent());
+ theme.applyStyle(R.style.SetupWizardPartnerResource, true);
+ super.onApplyThemeResource(theme, resid, first);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ if (mConfirmingCredentials || mMultiBiometricEnrollHelper != null) {
+ return;
+ }
+
+ if (!isChangingConfigurations()) {
+ Log.d(TAG, "Finishing in onStop");
+ finish();
+ }
+ }
+
+ 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<FingerprintSensorProperties> fpProperties =
+ fingerprintManager.getSensorProperties();
+ final List<FaceSensorProperties> faceProperties = faceManager.getSensorProperties();
+
+ // 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).maxTemplatesAllowed;
+ final boolean maxFingerprintsEnrolled = fingerprintManager.getEnrolledFingerprints(mUserId)
+ .size() >= fpProperties.get(0).maxTemplatesAllowed;
+
+ 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);
+
+ if (!mConfirmingCredentials && mGkPwHandle == null) {
+ mConfirmingCredentials = true;
+ if (!userHasPassword(mUserId)) {
+ launchChooseLock();
+ } else {
+ launchConfirmLock();
+ }
+ }
+ }
+
+ 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
+ mMultiBiometricEnrollHelper = new MultiBiometricEnrollHelper(this, mUserId,
+ canEnrollFace(), canEnrollFingerprint(), 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)
+ .getActivePasswordQuality(userManager.getCredentialOwnerProfile(userId));
+ return passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ }
+
+ private void launchChooseLock() {
+ Log.d(TAG, "launchChooseLock");
+ Intent intent = BiometricUtils.getChooseLockIntent(this, getIntent());
+ intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
+
+ if (mUserId != UserHandle.USER_NULL) {
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ }
+ startActivityForResult(intent, REQUEST_CHOOSE_LOCK);
+ }
+
+ private void launchConfirmLock() {
+ Log.d(TAG, "launchConfirmLock");
+ final ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(this);
+ builder.setRequestCode(REQUEST_CONFIRM_LOCK)
+ .setRequestGatekeeperPasswordHandle(true)
+ .setForegroundOnly(true)
+ .setReturnCredentials(true);
+ if (mUserId != UserHandle.USER_NULL) {
+ builder.setUserId(mUserId);
+ }
+ final boolean launched = builder.show();
+ if (!launched) {
+ // This shouldn't happen, as we should only end up at this step if a lock thingy is
+ // already set.
+ finish();
+ }
+ }
+
/**
+ * This should only be used to launch enrollment for single-sensor devices, which use
+ * FLAG_ACTIVITY_FORWARD_RESULT path.
+ *
* @param intent Enrollment activity that should be started (e.g. FaceEnrollIntroduction.class,
* etc).
*/
private void launchEnrollActivity(@NonNull Intent intent) {
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ byte[] hardwareAuthToken = null;
if (this instanceof InternalActivity) {
- // Propagate challenge and user Id from ChooseLockGeneric.
- final byte[] token = getIntent()
- .getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
- final int userId = getIntent()
- .getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
- final long gkPwHandle = getIntent().getLongExtra(
- ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 0L);
-
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
- intent.putExtra(Intent.EXTRA_USER_ID, userId);
- if (gkPwHandle != 0L) {
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
- }
+ hardwareAuthToken = getIntent().getByteArrayExtra(
+ ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
}
-
- startActivity(intent);
- finish();
+ BiometricUtils.launchEnrollForResult(this, intent, 0 /* requestCode */, hardwareAuthToken,
+ null /* gkPwHandle */, mUserId);
}
private void launchCredentialOnlyEnroll() {
@@ -152,40 +382,18 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
// ChooseLockGeneric can request to start fingerprint enroll bypassing the intro screen.
if (getIntent().getBooleanExtra(EXTRA_SKIP_INTRO, false)
&& this instanceof InternalActivity) {
- intent = getFingerprintFindSensorIntent();
+ intent = BiometricUtils.getFingerprintFindSensorIntent(this, getIntent());
} else {
- intent = getFingerprintIntroIntent();
+ intent = BiometricUtils.getFingerprintIntroIntent(this, getIntent());
}
launchEnrollActivity(intent);
}
private void launchFaceOnlyEnroll() {
- final Intent intent = getFaceIntroIntent();
+ final Intent intent = BiometricUtils.getFaceIntroIntent(this, getIntent());
launchEnrollActivity(intent);
}
- private Intent getFingerprintFindSensorIntent() {
- Intent intent = new Intent(this, FingerprintEnrollFindSensor.class);
- SetupWizardUtils.copySetupExtras(getIntent(), intent);
- return intent;
- }
-
- private Intent getFingerprintIntroIntent() {
- if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
- Intent intent = new Intent(this, SetupFingerprintEnrollIntroduction.class);
- WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
- return intent;
- } else {
- return new Intent(this, FingerprintEnrollIntroduction.class);
- }
- }
-
- private Intent getFaceIntroIntent() {
- Intent intent = new Intent(this, FaceEnrollIntroduction.class);
- WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
- return intent;
- }
-
@Override
public int getMetricsCategory() {
return SettingsEnums.BIOMETRIC_ENROLL_ACTIVITY;
diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java
index ecb2192572..1d9d07bf1d 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollBase.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java
@@ -57,6 +57,9 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
* starting the next activity. However, this leads to broken 'Back'
* behavior. So, now an activity does not finish itself until it gets this
* result.
+ *
+ * This must be the same as
+ * {@link com.android.settings.password.ChooseLockPattern#RESULT_FINISHED}
*/
public static final int RESULT_FINISHED = RESULT_FIRST_USER;
@@ -78,6 +81,11 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
public static final int LEARN_MORE_REQUEST = 3;
public static final int CONFIRM_REQUEST = 4;
public static final int ENROLL_REQUEST = 5;
+ /**
+ * Request code when starting another biometric enrollment from within a biometric flow. For
+ * example, when starting fingerprint enroll after face enroll.
+ */
+ public static final int ENROLL_NEXT_BIOMETRIC_REQUEST = 6;
protected boolean mLaunchedConfirmLock;
protected byte[] mToken;
diff --git a/src/com/android/settings/biometrics/BiometricEnrollCheckbox.java b/src/com/android/settings/biometrics/BiometricEnrollCheckbox.java
new file mode 100644
index 0000000000..d2ff634942
--- /dev/null
+++ b/src/com/android/settings/biometrics/BiometricEnrollCheckbox.java
@@ -0,0 +1,115 @@
+/*
+ * 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/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 8cd5a70704..26df474aa5 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -21,7 +21,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.storage.StorageManager;
+import android.util.Log;
import android.view.View;
import android.widget.TextView;
@@ -29,9 +29,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.settings.password.ChooseLockGeneric;
-import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
-import com.android.settings.password.SetupChooseLockGeneric;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -43,6 +41,8 @@ import com.google.android.setupdesign.span.LinkSpan;
public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
implements LinkSpan.OnClickListener {
+ private static final String TAG = "BiometricEnrollIntroduction";
+
private static final String KEY_CONFIRMING_CREDENTIALS = "confirming_credentials";
private UserManager mUserManager;
@@ -164,7 +164,8 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
// No password registered, launch into enrollment wizard.
mConfirmingCredentials = true;
launchChooseLock();
- } else if (!BiometricUtils.containsGatekeeperPassword(getIntent()) && mToken == null) {
+ } else if (!BiometricUtils.containsGatekeeperPasswordHandle(getIntent())
+ && mToken == null) {
// It's possible to have a token but mLaunchedConfirmLock == false, since
// ChooseLockGeneric can pass us a token.
mConfirmingCredentials = true;
@@ -220,7 +221,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
}
private void launchChooseLock() {
- Intent intent = getChooseLockIntent();
+ Intent intent = BiometricUtils.getChooseLockIntent(this, getIntent());
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
@@ -240,27 +241,11 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
if (mUserId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
}
+ BiometricUtils.copyMultiBiometricExtras(getIntent(), intent);
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
}
- protected Intent getChooseLockIntent() {
- if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
- // Default to PIN lock in setup wizard
- Intent intent = new Intent(this, SetupChooseLockGeneric.class);
- if (StorageManager.isFileEncryptedNativeOrEmulated()) {
- intent.putExtra(
- LockPatternUtils.PASSWORD_TYPE_KEY,
- DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
- intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
- }
- WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
- return intent;
- } else {
- return new Intent(this, ChooseLockGeneric.class);
- }
- }
-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
@@ -301,6 +286,12 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
}
} else if (requestCode == LEARN_MORE_REQUEST) {
overridePendingTransition(R.anim.sud_slide_back_in, R.anim.sud_slide_back_out);
+ } else if (requestCode == ENROLL_NEXT_BIOMETRIC_REQUEST) {
+ Log.d(TAG, "ENROLL_NEXT_BIOMETRIC_REQUEST, result: " + resultCode);
+ if (resultCode != RESULT_CANCELED) {
+ setResult(resultCode, data);
+ finish();
+ }
}
super.onActivityResult(requestCode, resultCode, data);
}
diff --git a/src/com/android/settings/biometrics/BiometricUtils.java b/src/com/android/settings/biometrics/BiometricUtils.java
index e458f03b94..d93a321cac 100644
--- a/src/com/android/settings/biometrics/BiometricUtils.java
+++ b/src/com/android/settings/biometrics/BiometricUtils.java
@@ -16,16 +16,35 @@
package com.android.settings.biometrics;
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
+import android.os.storage.StorageManager;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.SetupWizardUtils;
+import com.android.settings.biometrics.face.FaceEnrollIntroduction;
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor;
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
+import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollIntroduction;
+import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.SetupChooseLockGeneric;
+
+import com.google.android.setupcompat.util.WizardManagerHelper;
/**
* Common biometric utilities.
*/
public class BiometricUtils {
+ private static final String TAG = "BiometricUtils";
/**
* Given the result from confirming or choosing a credential, request Gatekeeper to generate
* a HardwareAuthToken with the Gatekeeper Password together with a biometric challenge.
@@ -36,24 +55,29 @@ public class BiometricUtils {
* @param challenge Unique biometric challenge from FingerprintManager/FaceManager
* @return
*/
- public static byte[] requestGatekeeperHat(Context context, Intent result, int userId,
- long challenge) {
- final long gatekeeperPasswordHandle = result.getLongExtra(
- ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 0L);
- if (gatekeeperPasswordHandle == 0L) {
+ public static byte[] requestGatekeeperHat(@NonNull Context context, @NonNull Intent result,
+ int userId, long challenge) {
+ if (!containsGatekeeperPasswordHandle(result)) {
throw new IllegalStateException("Gatekeeper Password is missing!!");
}
+ final long gatekeeperPasswordHandle = result.getLongExtra(
+ ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 0L);
+ return requestGatekeeperHat(context, gatekeeperPasswordHandle, userId, challenge);
+ }
+ public static byte[] requestGatekeeperHat(@NonNull Context context, long gkPwHandle, int userId,
+ long challenge) {
final LockPatternUtils utils = new LockPatternUtils(context);
- return utils.verifyGatekeeperPasswordHandle(gatekeeperPasswordHandle, challenge, userId)
+ return utils.verifyGatekeeperPasswordHandle(gkPwHandle, challenge, userId)
.getGatekeeperHAT();
}
- public static boolean containsGatekeeperPassword(Intent data) {
- if (data == null) {
- return false;
- }
- return data.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 0L) != 0L;
+ public static boolean containsGatekeeperPasswordHandle(@Nullable Intent data) {
+ return data != null && data.hasExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE);
+ }
+
+ public static long getGatekeeperPasswordHandle(@NonNull Intent data) {
+ return data.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 0L);
}
/**
@@ -64,16 +88,157 @@ public class BiometricUtils {
* @param context Caller's context
* @param data The onActivityResult intent from ChooseLock* or ConfirmLock*
*/
- public static void removeGatekeeperPasswordHandle(Context context, Intent data) {
+ public static void removeGatekeeperPasswordHandle(@NonNull Context context,
+ @Nullable Intent data) {
if (data == null) {
return;
}
- final long gatekeeperPasswordsHandle = data.getLongExtra(
- ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 0L);
- if (gatekeeperPasswordsHandle == 0L) {
+ if (!containsGatekeeperPasswordHandle(data)) {
return;
}
+ removeGatekeeperPasswordHandle(context, getGatekeeperPasswordHandle(data));
+ }
+
+ public static void removeGatekeeperPasswordHandle(@NonNull Context context, long handle) {
final LockPatternUtils utils = new LockPatternUtils(context);
- utils.removeGatekeeperPasswordHandle(gatekeeperPasswordsHandle);
+ utils.removeGatekeeperPasswordHandle(handle);
+ Log.d(TAG, "Removed handle");
+ }
+
+ /**
+ * @param context caller's context
+ * @param activityIntent The intent that started the caller's activity
+ * @return Intent for starting ChooseLock*
+ */
+ public static Intent getChooseLockIntent(@NonNull Context context,
+ @NonNull Intent activityIntent) {
+ if (WizardManagerHelper.isAnySetupWizard(activityIntent)) {
+ // Default to PIN lock in setup wizard
+ Intent intent = new Intent(context, SetupChooseLockGeneric.class);
+ if (StorageManager.isFileEncryptedNativeOrEmulated()) {
+ intent.putExtra(
+ LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+ intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment
+ .EXTRA_SHOW_OPTIONS_BUTTON, true);
+ }
+ WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
+ return intent;
+ } else {
+ return new Intent(context, ChooseLockGeneric.class);
+ }
+ }
+
+ /**
+ * @param context caller's context
+ * @param activityIntent The intent that started the caller's activity
+ * @return Intent for starting FingerprintEnrollFindSensor
+ */
+ public static Intent getFingerprintFindSensorIntent(@NonNull Context context,
+ @NonNull Intent activityIntent) {
+ Intent intent = new Intent(context, FingerprintEnrollFindSensor.class);
+ SetupWizardUtils.copySetupExtras(activityIntent, intent);
+ return intent;
+ }
+
+ /**
+ * @param context caller's context
+ * @param activityIntent The intent that started the caller's activity
+ * @return Intent for starting FingerprintEnrollIntroduction
+ */
+ public static Intent getFingerprintIntroIntent(@NonNull Context context,
+ @NonNull Intent activityIntent) {
+ if (WizardManagerHelper.isAnySetupWizard(activityIntent)) {
+ Intent intent = new Intent(context, SetupFingerprintEnrollIntroduction.class);
+ WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
+ return intent;
+ } else {
+ return new Intent(context, FingerprintEnrollIntroduction.class);
+ }
+ }
+
+ /**
+ * @param context caller's context
+ * @param activityIntent The intent that started the caller's activity
+ * @return Intent for starting FaceEnrollIntroduction
+ */
+ public static Intent getFaceIntroIntent(@NonNull Context context,
+ @NonNull Intent activityIntent) {
+ Intent intent = new Intent(context, FaceEnrollIntroduction.class);
+ WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
+ return intent;
+ }
+
+ /**
+ * @param activity Reference to the calling activity, used to startActivity
+ * @param intent Intent pointing to the enrollment activity
+ * @param requestCode If non-zero, will invoke startActivityForResult instead of startActivity
+ * @param hardwareAuthToken HardwareAuthToken from Gatekeeper
+ * @param userId User to request enrollment for
+ */
+ public static void launchEnrollForResult(@NonNull BiometricEnrollActivity activity,
+ @NonNull Intent intent, int requestCode,
+ @Nullable byte[] hardwareAuthToken, @Nullable Long gkPwHandle, int userId) {
+ if (hardwareAuthToken != null) {
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
+ hardwareAuthToken);
+ }
+ if (gkPwHandle != null) {
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
+ }
+
+ if (activity instanceof BiometricEnrollActivity.InternalActivity) {
+ intent.putExtra(Intent.EXTRA_USER_ID, userId);
+ }
+
+ if (requestCode != 0) {
+ activity.startActivityForResult(intent, requestCode);
+ } else {
+ activity.startActivity(intent);
+ activity.finish();
+ }
+ }
+
+ /**
+ * @param activity Activity that we want to check
+ * @return True if the activity is going through a multi-biometric enrollment flow.
+ */
+ public static boolean isMultiBiometricEnrollmentFlow(@NonNull Activity activity) {
+ return activity.getIntent().hasExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE);
+ }
+
+ public static void copyMultiBiometricExtras(@NonNull Intent fromIntent,
+ @NonNull Intent toIntent) {
+ final PendingIntent pendingIntent = (PendingIntent) fromIntent.getExtra(
+ MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE, null);
+ if (pendingIntent != null) {
+ toIntent.putExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE, pendingIntent);
+ }
+ }
+
+ /**
+ * If the current biometric enrollment (e.g. face) should be followed by another one (e.g.
+ * fingerprint) (see {@link #isMultiBiometricEnrollmentFlow(Activity)}), retrieves the
+ * PendingIntent pointing to the next enrollment and starts it. The caller will receive the
+ * result in onActivityResult.
+ * @return true if the next enrollment was started
+ */
+ public static boolean tryStartingNextBiometricEnroll(@NonNull Activity activity,
+ int requestCode) {
+ final PendingIntent pendingIntent = (PendingIntent) activity.getIntent()
+ .getExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE);
+ if (pendingIntent != null) {
+ try {
+ Log.d(TAG, "Starting pendingIntent: " + pendingIntent);
+ IntentSender intentSender = pendingIntent.getIntentSender();
+ activity.startIntentSenderForResult(intentSender, requestCode,
+ null /* fillInIntent */, 0 /* flagMask */, 0 /* flagValues */,
+ 0 /* extraFlags */);
+ return true;
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(TAG, "Pending intent canceled: " + e);
+ }
+ }
+ return false;
}
}
diff --git a/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java b/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java
new file mode 100644
index 0000000000..c1e906a8d4
--- /dev/null
+++ b/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java
@@ -0,0 +1,113 @@
+/*
+ * 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.app.Activity;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.settings.password.ChooseLockSettingsHelper;
+
+/**
+ * Helper for {@link BiometricEnrollActivity} when multiple sensors exist on a device.
+ */
+public class MultiBiometricEnrollHelper {
+
+ private static final String TAG = "MultiBiometricEnrollHelper";
+
+ private static final int REQUEST_FACE_ENROLL = 3000;
+ private static final int REQUEST_FINGERPRINT_ENROLL = 3001;
+
+ public static final String EXTRA_ENROLL_AFTER_FACE = "enroll_after_face";
+
+ @NonNull private final BiometricEnrollActivity mActivity;
+ private final long mGkPwHandle;
+ private final int mUserId;
+ private final boolean mRequestEnrollFace;
+ private final boolean mRequestEnrollFingerprint;
+
+ MultiBiometricEnrollHelper(@NonNull BiometricEnrollActivity activity, int userId,
+ boolean enrollFace, boolean enrollFingerprint, long gkPwHandle) {
+ mActivity = activity;
+ mUserId = userId;
+ mGkPwHandle = gkPwHandle;
+ mRequestEnrollFace = enrollFace;
+ mRequestEnrollFingerprint = enrollFingerprint;
+ }
+
+ void startNextStep() {
+ if (mRequestEnrollFace) {
+ launchFaceEnroll();
+ } else if (mRequestEnrollFingerprint) {
+ launchFingerprintEnroll();
+ } else {
+ mActivity.setResult(BiometricEnrollIntroduction.RESULT_SKIP);
+ mActivity.finish();
+ }
+ }
+
+ private void launchFaceEnroll() {
+ final FaceManager faceManager = mActivity.getSystemService(FaceManager.class);
+ faceManager.generateChallenge((sensorId, challenge) -> {
+ final byte[] hardwareAuthToken = BiometricUtils.requestGatekeeperHat(mActivity,
+ mGkPwHandle, mUserId, challenge);
+ final Intent faceIntent = BiometricUtils.getFaceIntroIntent(mActivity,
+ mActivity.getIntent());
+
+ if (mRequestEnrollFingerprint) {
+ // Give FaceEnroll a pendingIntent pointing to fingerprint enrollment, so that it
+ // can be started when user skips or finishes face enrollment.
+ final Intent fpIntent = BiometricUtils.getFingerprintIntroIntent(mActivity,
+ mActivity.getIntent());
+ fpIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, mGkPwHandle);
+ final PendingIntent fpAfterFaceIntent = PendingIntent.getActivity(mActivity,
+ 0 /* requestCode */, fpIntent, 0 /* flags */);
+ faceIntent.putExtra(EXTRA_ENROLL_AFTER_FACE, fpAfterFaceIntent);
+ }
+
+ BiometricUtils.launchEnrollForResult(mActivity, faceIntent, REQUEST_FACE_ENROLL,
+ hardwareAuthToken, mGkPwHandle, mUserId);
+ });
+ }
+
+ private void launchFingerprintEnroll() {
+ final FingerprintManager fingerprintManager = mActivity
+ .getSystemService(FingerprintManager.class);
+ fingerprintManager.generateChallenge(((sensorId, challenge) -> {
+ final byte[] hardwareAuthToken = BiometricUtils.requestGatekeeperHat(mActivity,
+ mGkPwHandle, mUserId, challenge);
+ final Intent intent = BiometricUtils.getFingerprintIntroIntent(mActivity,
+ mActivity.getIntent());
+ BiometricUtils.launchEnrollForResult(mActivity, intent, REQUEST_FINGERPRINT_ENROLL,
+ hardwareAuthToken, mGkPwHandle, mUserId);
+ }));
+ }
+
+ 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();
+ }
+ }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
index 4c4fa1174f..3e9fba281a 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
@@ -33,6 +33,7 @@ import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
+import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.google.android.setupcompat.template.FooterBarMixin;
@@ -183,6 +184,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
}
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
+ BiometricUtils.copyMultiBiometricExtras(getIntent(), intent);
final String flattenedString = getString(R.string.config_face_enroll);
if (!TextUtils.isEmpty(flattenedString)) {
ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 59d1a604e8..55a56ed6a7 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -16,17 +16,23 @@
package com.android.settings.biometrics.face;
+import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.Intent;
+import android.content.IntentSender;
import android.hardware.face.FaceManager;
+import android.hardware.face.FaceSensorProperties;
import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
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.biometrics.MultiBiometricEnrollHelper;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -37,6 +43,8 @@ import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
import com.google.android.setupdesign.template.RequireScrollMixin;
+import java.util.List;
+
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FaceEnrollIntroduction";
@@ -45,6 +53,20 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
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);
@@ -53,25 +75,14 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
.getFaceFeatureProvider();
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
- if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
- mFooterBarMixin.setSecondaryButton(
- new FooterButton.Builder(this)
- .setText(R.string.security_settings_face_enroll_introduction_no_thanks)
- .setListener(this::onSkipButtonClick)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(R.style.SudGlifButton_Secondary)
- .build()
- );
- } else {
- mFooterBarMixin.setSecondaryButton(
- new FooterButton.Builder(this)
- .setText(R.string.security_settings_face_enroll_introduction_no_thanks)
- .setListener(this::onCancelButtonClick)
- .setButtonType(FooterButton.ButtonType.CANCEL)
- .setTheme(R.style.SudGlifButton_Secondary)
- .build()
- );
- }
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.security_settings_face_enroll_introduction_no_thanks)
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.SKIP)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
FooterButton.Builder nextButtonBuilder = new FooterButton.Builder(this)
.setText(R.string.security_settings_face_enroll_introduction_agree)
@@ -99,13 +110,15 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
// 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.containsGatekeeperPassword(getIntent())) {
+ 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((sensorId, challenge) -> {
mToken = BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId, challenge);
- BiometricUtils.removeGatekeeperPasswordHandle(this, getIntent());
+ if (BiometricUtils.isMultiBiometricEnrollmentFlow(this)) {
+ BiometricUtils.removeGatekeeperPasswordHandle(this, getIntent());
+ }
mFooterBarMixin.getPrimaryButton().setEnabled(true);
});
}
@@ -160,8 +173,9 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private boolean maxFacesEnrolled() {
if (mFaceManager != null) {
- final int max = getResources().getInteger(
- com.android.internal.R.integer.config_faceMaxTemplatesPerUser);
+ final List<FaceSensorProperties> props = mFaceManager.getSensorProperties();
+ // This will need to be updated for devices with multiple face sensors.
+ final int max = props.get(0).maxTemplatesAllowed;
final int numEnrolledFaces = mFaceManager.getEnrolledFaces(mUserId).size();
return numEnrolledFaces >= max;
} else {
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index 725123048e..5c8447fd74 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -236,7 +236,7 @@ public class FaceSettings extends DashboardFragment {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- if (mToken == null && !BiometricUtils.containsGatekeeperPassword(data)) {
+ if (mToken == null && !BiometricUtils.containsGatekeeperPasswordHandle(data)) {
Log.e(TAG, "No credential");
finish();
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
index 8029c7dfcc..c320ef5a8d 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
@@ -63,7 +63,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
// This is an entry point for SetNewPasswordController, e.g.
// adb shell am start -a android.app.action.SET_NEW_PASSWORD
- if (mToken == null && BiometricUtils.containsGatekeeperPassword(getIntent())) {
+ if (mToken == null && BiometricUtils.containsGatekeeperPasswordHandle(getIntent())) {
final FingerprintManager fpm = getSystemService(FingerprintManager.class);
fpm.generateChallenge((sensorId, challenge) -> {
mToken = BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId, challenge);
@@ -79,6 +79,9 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
} else if (mToken != null) {
// HAT passed in from somewhere else, such as FingerprintEnrollIntroduction
startLookingForFingerprint();
+ } else {
+ // There's something wrong with the enrollment flow, this should never happen.
+ throw new IllegalStateException("HAT and GkPwHandle both missing...");
}
View animationView = findViewById(R.id.fingerprint_sensor_location_animation);
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 78bb9788b9..dbbcef1156 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -21,6 +21,7 @@ import android.app.settings.SettingsEnums;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintSensorProperties;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
@@ -28,6 +29,7 @@ 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.password.ChooseLockSettingsHelper;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -36,6 +38,8 @@ import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.span.LinkSpan;
+import java.util.List;
+
public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FingerprintIntro";
@@ -45,13 +49,14 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
mFingerprintManager = Utils.getFingerprintManagerOrNull(this);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
mFooterBarMixin.setSecondaryButton(
new FooterButton.Builder(this)
- .setText(R.string.security_settings_face_enroll_introduction_cancel)
- .setListener(this::onCancelButtonClick)
+ .setText(getNegativeButtonTextId())
+ .setListener(this::onSkipButtonClick)
.setButtonType(FooterButton.ButtonType.SKIP)
.setTheme(R.style.SudGlifButton_Secondary)
.build()
@@ -67,6 +72,10 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
);
}
+ int getNegativeButtonTextId() {
+ return R.string.security_settings_fingerprint_enroll_introduction_no_thanks;
+ }
+
@Override
protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
@@ -117,8 +126,10 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
@Override
protected int checkMaxEnrolled() {
if (mFingerprintManager != null) {
- final int max = getResources().getInteger(
- com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
+ final List<FingerprintSensorProperties> props =
+ mFingerprintManager.getSensorProperties();
+ // This will need to be updated for devices with multiple fingerprint sensors
+ final int max = props.get(0).maxTemplatesAllowed;
final int numEnrolledFingerprints =
mFingerprintManager.getEnrolledFingerprints(mUserId).size();
if (numEnrolledFingerprints >= max) {
@@ -147,7 +158,12 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
@Override
protected Intent getEnrollingIntent() {
- return new Intent(this, FingerprintEnrollFindSensor.class);
+ final Intent intent = new Intent(this, FingerprintEnrollFindSensor.class);
+ if (BiometricUtils.containsGatekeeperPasswordHandle(getIntent())) {
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
+ BiometricUtils.getGatekeeperPasswordHandle(getIntent()));
+ }
+ return intent;
}
@Override
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index a65316940c..052b3f0057 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -570,7 +570,7 @@ public class FingerprintSettings extends SubSettings {
if (requestCode == CONFIRM_REQUEST || requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
mLaunchedConfirm = false;
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
- if (data != null && BiometricUtils.containsGatekeeperPassword(data)) {
+ if (data != null && BiometricUtils.containsGatekeeperPasswordHandle(data)) {
mFingerprintManager.generateChallenge((sensorId, challenge) -> {
mToken = BiometricUtils.requestGatekeeperHat(getActivity(), data,
mUserId, challenge);
diff --git a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java
index 7df66b789f..c8a4c05a93 100644
--- a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -32,7 +32,9 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
+import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
+import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.SetupChooseLockGeneric;
import com.android.settings.password.SetupSkipDialog;
@@ -59,28 +61,23 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu
}
@Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putBoolean(KEY_LOCK_SCREEN_PRESENT, mAlreadyHadLockScreenSetup);
+ int getNegativeButtonTextId() {
+ return R.string.security_settings_face_enroll_introduction_cancel;
}
@Override
- protected Intent getChooseLockIntent() {
- Intent intent = new Intent(this, SetupChooseLockGeneric.class);
-
- if (StorageManager.isFileEncryptedNativeOrEmulated()) {
- intent.putExtra(
- LockPatternUtils.PASSWORD_TYPE_KEY,
- DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
- intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
- }
- SetupWizardUtils.copySetupExtras(getIntent(), intent);
- return intent;
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_LOCK_SCREEN_PRESENT, mAlreadyHadLockScreenSetup);
}
@Override
protected Intent getEnrollingIntent() {
final Intent intent = new Intent(this, SetupFingerprintEnrollFindSensor.class);
+ if (BiometricUtils.containsGatekeeperPasswordHandle(getIntent())) {
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
+ BiometricUtils.getGatekeeperPasswordHandle(getIntent()));
+ }
SetupWizardUtils.copySetupExtras(getIntent(), intent);
return intent;
}
@@ -157,6 +154,11 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu
}
}
+ @Override
+ protected void onSkipButtonClick(View view) {
+ onCancelButtonClick(view);
+ }
+
/**
* Propagate lock screen metrics if the user goes back from the fingerprint setup screen
* after having added lock screen to his device.
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 5b3013da21..35e369e942 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -103,6 +103,7 @@ public class ChooseLockGeneric extends SettingsActivity {
private static final String TAG = "ChooseLockGenericFragment";
private static final String KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint";
private static final String KEY_SKIP_FACE = "unlock_skip_face";
+ private static final String KEY_SKIP_BIOMETRICS = "unlock_skip_biometrics";
private static final String PASSWORD_CONFIRMED = "password_confirmed";
private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
public static final String MINIMUM_QUALITY_KEY = "minimum_quality";
@@ -175,6 +176,7 @@ public class ChooseLockGeneric extends SettingsActivity {
protected boolean mForFingerprint = false;
protected boolean mForFace = false;
+ protected boolean mForBiometrics = false;
@Override
public int getMetricsCategory() {
@@ -216,6 +218,9 @@ public class ChooseLockGeneric extends SettingsActivity {
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
mForFace = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
+ mForBiometrics = intent.getBooleanExtra(
+ ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
+
mRequestedMinComplexity = intent
.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE);
mCallerAppName =
@@ -303,17 +308,20 @@ public class ChooseLockGeneric extends SettingsActivity {
}
protected void addHeaderView() {
+ setHeaderView(R.layout.choose_lock_generic_biometric_header);
+ TextView textView = getHeaderView().findViewById(R.id.biometric_header_description);
+
if (mForFingerprint) {
- setHeaderView(R.layout.choose_lock_generic_fingerprint_header);
if (mIsSetNewPassword) {
- ((TextView) getHeaderView().findViewById(R.id.fingerprint_header_description))
- .setText(R.string.fingerprint_unlock_title);
+ textView.setText(R.string.fingerprint_unlock_title);
}
} else if (mForFace) {
- setHeaderView(R.layout.choose_lock_generic_face_header);
if (mIsSetNewPassword) {
- ((TextView) getHeaderView().findViewById(R.id.face_header_description))
- .setText(R.string.face_unlock_title);
+ textView.setText(R.string.face_unlock_title);
+ }
+ } else if (mForBiometrics) {
+ if (mIsSetNewPassword) {
+ textView.setText(R.string.biometrics_unlock_title);
}
}
}
@@ -328,7 +336,8 @@ public class ChooseLockGeneric extends SettingsActivity {
// unlock method to an insecure one
showFactoryResetProtectionWarningDialog(key);
return true;
- } else if (KEY_SKIP_FINGERPRINT.equals(key) || KEY_SKIP_FACE.equals(key)) {
+ } else if (KEY_SKIP_FINGERPRINT.equals(key) || KEY_SKIP_FACE.equals(key)
+ || KEY_SKIP_BIOMETRICS.equals(key)) {
Intent chooseLockGenericIntent = new Intent(getActivity(),
getInternalActivityClass());
chooseLockGenericIntent.setAction(getIntent().getAction());
@@ -357,7 +366,7 @@ public class ChooseLockGeneric extends SettingsActivity {
* @param disabled
*/
// TODO: why does this take disabled, its always called with a quality higher than
- // what makes sense with disabled == true
+ // what makes sense with disabled == true
private void maybeEnableEncryption(int quality, boolean disabled) {
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
if (UserManager.get(getActivity()).isAdminUser()
@@ -381,8 +390,8 @@ public class ChooseLockGeneric extends SettingsActivity {
unlockMethodIntent);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
mForFingerprint);
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE,
- mForFace);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, mForFace);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, mForBiometrics);
// If the caller requested Gatekeeper Password to be returned, we assume it came
// from biometric enrollment. This should be cleaned up, since requesting
// Gatekeeper Password should not imply it came from biometric setup/settings.
@@ -531,6 +540,7 @@ public class ChooseLockGeneric extends SettingsActivity {
findPreference(ScreenLockType.NONE.preferenceKey).setViewId(R.id.lock_none);
findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
findPreference(KEY_SKIP_FACE).setViewId(R.id.lock_none);
+ findPreference(KEY_SKIP_BIOMETRICS).setViewId(R.id.lock_none);
findPreference(ScreenLockType.PIN.preferenceKey).setViewId(R.id.lock_pin);
findPreference(ScreenLockType.PASSWORD.preferenceKey).setViewId(R.id.lock_password);
}
@@ -569,6 +579,12 @@ public class ChooseLockGeneric extends SettingsActivity {
setPreferenceTitle(ScreenLockType.PIN, R.string.face_unlock_set_unlock_pin);
setPreferenceTitle(ScreenLockType.PASSWORD,
R.string.face_unlock_set_unlock_password);
+ } else if (mForBiometrics) {
+ setPreferenceTitle(ScreenLockType.PATTERN,
+ R.string.biometrics_unlock_set_unlock_pattern);
+ setPreferenceTitle(ScreenLockType.PIN, R.string.biometrics_unlock_set_unlock_pin);
+ setPreferenceTitle(ScreenLockType.PASSWORD,
+ R.string.biometrics_unlock_set_unlock_password);
}
if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
@@ -584,6 +600,9 @@ public class ChooseLockGeneric extends SettingsActivity {
if (!(mForFace && mIsSetNewPassword)) {
removePreference(KEY_SKIP_FACE);
}
+ if (!(mForBiometrics && mIsSetNewPassword)) {
+ removePreference(KEY_SKIP_BIOMETRICS);
+ }
}
private void setPreferenceTitle(ScreenLockType lock, @StringRes int title) {
@@ -727,6 +746,7 @@ public class ChooseLockGeneric extends SettingsActivity {
.setRequestedMinComplexity(mRequestedMinComplexity)
.setForFingerprint(mForFingerprint)
.setForFace(mForFace)
+ .setForBiometrics(mForBiometrics)
.setUserId(mUserId)
.setRequestGatekeeperPasswordHandle(mRequestGatekeeperPasswordHandle);
if (mUserPassword != null) {
@@ -743,6 +763,7 @@ public class ChooseLockGeneric extends SettingsActivity {
new ChooseLockPattern.IntentBuilder(getContext())
.setForFingerprint(mForFingerprint)
.setForFace(mForFace)
+ .setForBiometrics(mForBiometrics)
.setUserId(mUserId)
.setRequestGatekeeperPasswordHandle(mRequestGatekeeperPasswordHandle);
if (mUserPassword != null) {
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index 6cfb1efb51..e393af5951 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -151,6 +151,11 @@ public class ChooseLockPassword extends SettingsActivity {
return this;
}
+ public IntentBuilder setForBiometrics(boolean forBiometrics) {
+ mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, forBiometrics);
+ return this;
+ }
+
public IntentBuilder setRequestedMinComplexity(@PasswordComplexity int level) {
mIntent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, level);
return this;
@@ -190,12 +195,16 @@ public class ChooseLockPassword extends SettingsActivity {
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
final boolean forFace = getIntent()
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
+ final boolean forBiometrics = getIntent()
+ .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
CharSequence msg = getText(R.string.lockpassword_choose_your_screen_lock_header);
if (forFingerprint) {
msg = getText(R.string.lockpassword_choose_your_password_header_for_fingerprint);
} else if (forFace) {
msg = getText(R.string.lockpassword_choose_your_password_header_for_face);
+ } else if (forBiometrics) {
+ msg = getText(R.string.lockpassword_choose_your_password_header_for_biometrics);
}
setTitle(msg);
@@ -232,6 +241,7 @@ public class ChooseLockPassword extends SettingsActivity {
private GlifLayout mLayout;
protected boolean mForFingerprint;
protected boolean mForFace;
+ protected boolean mForBiometrics;
private LockscreenCredential mFirstPassword;
private RecyclerView mPasswordRestrictionView;
@@ -254,9 +264,11 @@ public class ChooseLockPassword extends SettingsActivity {
R.string.lockpassword_choose_your_screen_lock_header, // password
R.string.lockpassword_choose_your_password_header_for_fingerprint,
R.string.lockpassword_choose_your_password_header_for_face,
+ R.string.lockpassword_choose_your_password_header_for_biometrics,
R.string.lockpassword_choose_your_screen_lock_header, // pin
R.string.lockpassword_choose_your_pin_header_for_fingerprint,
R.string.lockpassword_choose_your_pin_header_for_face,
+ R.string.lockpassword_choose_your_pin_header_for_biometrics,
R.string.lockpassword_choose_your_password_message, // added security message
R.string.lock_settings_picker_biometrics_added_security_message,
R.string.lockpassword_choose_your_pin_message,
@@ -267,6 +279,8 @@ public class ChooseLockPassword extends SettingsActivity {
R.string.lockpassword_confirm_your_password_header,
R.string.lockpassword_confirm_your_password_header,
R.string.lockpassword_confirm_your_password_header,
+ R.string.lockpassword_confirm_your_password_header,
+ R.string.lockpassword_confirm_your_pin_header,
R.string.lockpassword_confirm_your_pin_header,
R.string.lockpassword_confirm_your_pin_header,
R.string.lockpassword_confirm_your_pin_header,
@@ -280,6 +294,8 @@ public class ChooseLockPassword extends SettingsActivity {
R.string.lockpassword_confirm_passwords_dont_match,
R.string.lockpassword_confirm_passwords_dont_match,
R.string.lockpassword_confirm_passwords_dont_match,
+ R.string.lockpassword_confirm_passwords_dont_match,
+ R.string.lockpassword_confirm_pins_dont_match,
R.string.lockpassword_confirm_pins_dont_match,
R.string.lockpassword_confirm_pins_dont_match,
R.string.lockpassword_confirm_pins_dont_match,
@@ -289,18 +305,22 @@ public class ChooseLockPassword extends SettingsActivity {
0,
R.string.lockpassword_confirm_label);
- Stage(int hintInAlpha, int hintInAlphaForFingerprint, int hintInAlphaForFace,
- int hintInNumeric, int hintInNumericForFingerprint, int hintInNumericForFace,
+ Stage(int hintInAlpha,
+ int hintInAlphaForFingerprint, int hintInAlphaForFace, int hintInAlphaForBiometrics,
+ int hintInNumeric,
+ int hintInNumericForFingerprint, int hintInNumericForFace, int hintInNumericForBiometrics,
int messageInAlpha, int messageInAlphaForBiometrics,
int messageInNumeric, int messageInNumericForBiometrics,
int nextButtonText) {
this.alphaHint = hintInAlpha;
this.alphaHintForFingerprint = hintInAlphaForFingerprint;
this.alphaHintForFace = hintInAlphaForFace;
+ this.alphaHintForBiometrics = hintInAlphaForBiometrics;
this.numericHint = hintInNumeric;
this.numericHintForFingerprint = hintInNumericForFingerprint;
this.numericHintForFace = hintInNumericForFace;
+ this.numericHintForBiometrics = hintInNumericForBiometrics;
this.alphaMessage = messageInAlpha;
this.alphaMessageForBiometrics = messageInAlphaForBiometrics;
@@ -312,16 +332,19 @@ public class ChooseLockPassword extends SettingsActivity {
public static final int TYPE_NONE = 0;
public static final int TYPE_FINGERPRINT = 1;
public static final int TYPE_FACE = 2;
+ public static final int TYPE_BIOMETRIC = 3;
// Password
public final int alphaHint;
public final int alphaHintForFingerprint;
public final int alphaHintForFace;
+ public final int alphaHintForBiometrics;
// PIN
public final int numericHint;
public final int numericHintForFingerprint;
public final int numericHintForFace;
+ public final int numericHintForBiometrics;
public final int alphaMessage;
public final int alphaMessageForBiometrics;
@@ -335,6 +358,8 @@ public class ChooseLockPassword extends SettingsActivity {
return alphaHintForFingerprint;
} else if (type == TYPE_FACE) {
return alphaHintForFace;
+ } else if (type == TYPE_BIOMETRIC) {
+ return alphaHintForBiometrics;
} else {
return alphaHint;
}
@@ -343,6 +368,8 @@ public class ChooseLockPassword extends SettingsActivity {
return numericHintForFingerprint;
} else if (type == TYPE_FACE) {
return numericHintForFace;
+ } else if (type == TYPE_BIOMETRIC) {
+ return numericHintForBiometrics;
} else {
return numericHint;
}
@@ -376,6 +403,8 @@ public class ChooseLockPassword extends SettingsActivity {
mForFingerprint = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
mForFace = intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
+ mForBiometrics = intent.getBooleanExtra(
+ ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
mMinComplexity = intent.getIntExtra(
EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE);
@@ -454,6 +483,8 @@ public class ChooseLockPassword extends SettingsActivity {
mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_fingerprint_header));
} else if (mForFace) {
mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_face_header));
+ } else if (mForBiometrics) {
+ mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_lock));
}
mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
@@ -546,9 +577,15 @@ public class ChooseLockPassword extends SettingsActivity {
}
protected int getStageType() {
- return mForFingerprint ? Stage.TYPE_FINGERPRINT :
- mForFace ? Stage.TYPE_FACE :
- Stage.TYPE_NONE;
+ if (mForFingerprint) {
+ return Stage.TYPE_FINGERPRINT;
+ } else if (mForFace) {
+ return Stage.TYPE_FACE;
+ } else if (mForBiometrics) {
+ return Stage.TYPE_BIOMETRIC;
+ } else {
+ return Stage.TYPE_NONE;
+ }
}
private void setupPasswordRequirementsView(View view) {
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index 7ed9e6bcbe..ff9bf1a6aa 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -81,7 +81,7 @@ public class ChooseLockPattern extends SettingsActivity {
* behavior. So, now an activity does not finish itself until it gets this
* result.
*/
- static final int RESULT_FINISHED = RESULT_FIRST_USER;
+ public static final int RESULT_FINISHED = RESULT_FIRST_USER;
private static final String TAG = "ChooseLockPattern";
@@ -134,6 +134,11 @@ public class ChooseLockPattern extends SettingsActivity {
return this;
}
+ public IntentBuilder setForBiometrics(boolean forBiometrics) {
+ mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, forBiometrics);
+ return this;
+ }
+
/**
* Configures the launch such that at the end of the pattern enrollment, one of its
* managed profile (specified by {@code profileId}) will have its lockscreen unified
@@ -455,6 +460,7 @@ public class ChooseLockPattern extends SettingsActivity {
protected int mUserId;
protected boolean mForFingerprint;
protected boolean mForFace;
+ protected boolean mForBiometrics;
private static final String KEY_UI_STAGE = "uiStage";
private static final String KEY_PATTERN_CHOICE = "chosenPattern";
@@ -488,6 +494,8 @@ public class ChooseLockPattern extends SettingsActivity {
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
mForFace = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
+ mForBiometrics = intent.getBooleanExtra(
+ ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
}
@Override
@@ -506,6 +514,8 @@ public class ChooseLockPattern extends SettingsActivity {
layout.setIcon(getActivity().getDrawable(R.drawable.ic_fingerprint_header));
} else if (mForFace) {
layout.setIcon(getActivity().getDrawable(R.drawable.ic_face_header));
+ } else if (mForBiometrics) {
+ layout.setIcon(getActivity().getDrawable(R.drawable.ic_lock));
}
}
@@ -732,8 +742,8 @@ public class ChooseLockPattern extends SettingsActivity {
} else {
mHeaderText.setText(stage.headerMessage);
}
- final boolean forBiometrics = mForFingerprint || mForFace;
- int message = forBiometrics ? stage.messageForBiometrics : stage.message;
+ final boolean forAnyBiometric = mForFingerprint || mForFace || mForBiometrics;
+ int message = forAnyBiometric ? stage.messageForBiometrics : stage.message;
if (message == ID_EMPTY_MESSAGE) {
mMessageText.setText("");
} else {
@@ -756,7 +766,7 @@ public class ChooseLockPattern extends SettingsActivity {
mHeaderText.setTextColor(mDefaultHeaderColorList);
}
- if (stage == Stage.NeedToConfirm && forBiometrics) {
+ if (stage == Stage.NeedToConfirm && forAnyBiometric) {
mHeaderText.setText("");
mTitleText.setText(R.string.lockpassword_draw_your_pattern_again_header);
}
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index 1d10408e4f..1e1f59fddf 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -50,8 +50,12 @@ public final class ChooseLockSettingsHelper {
public static final String EXTRA_KEY_FORCE_VERIFY = "force_verify";
// Gatekeeper HardwareAuthToken
public static final String EXTRA_KEY_CHALLENGE_TOKEN = "hw_auth_token";
+ // For the fingerprint-only path
public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
+ // For the face-only path
public static final String EXTRA_KEY_FOR_FACE = "for_face";
+ // For the paths where multiple biometric sensors exist
+ public static final String EXTRA_KEY_FOR_BIOMETRICS = "for_biometrics";
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only";
public static final String EXTRA_KEY_REQUEST_GK_PW_HANDLE = "request_gk_pw_handle";
diff --git a/src/com/android/settings/password/SetNewPasswordController.java b/src/com/android/settings/password/SetNewPasswordController.java
index 393e8c76bc..03efa605d5 100644
--- a/src/com/android/settings/password/SetNewPasswordController.java
+++ b/src/com/android/settings/password/SetNewPasswordController.java
@@ -111,28 +111,49 @@ final class SetNewPasswordController {
*/
public void dispatchSetNewPasswordIntent() {
final Bundle extras;
- // TODO: handle the case with multiple biometrics, perhaps take an arg for biometric type?
- if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)
- && mFaceManager != null
+
+ final boolean hasFeatureFingerprint = mPackageManager
+ .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
+ final boolean hasFeatureFace = mPackageManager
+ .hasSystemFeature(PackageManager.FEATURE_FACE);
+
+ final boolean shouldShowFingerprintEnroll = mFingerprintManager != null
+ && mFingerprintManager.isHardwareDetected()
+ && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
+ && !isFingerprintDisabledByAdmin();
+ final boolean shouldShowFaceEnroll = mFaceManager != null
&& mFaceManager.isHardwareDetected()
&& !mFaceManager.hasEnrolledTemplates(mTargetUserId)
- && !isFaceDisabledByAdmin()) {
+ && !isFaceDisabledByAdmin();
+
+ if (hasFeatureFace && shouldShowFaceEnroll
+ && hasFeatureFingerprint && shouldShowFingerprintEnroll) {
+ extras = getBiometricChooseLockExtras();
+ } else if (hasFeatureFace && shouldShowFaceEnroll) {
extras = getFaceChooseLockExtras();
- } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
- && mFingerprintManager != null
- && mFingerprintManager.isHardwareDetected()
- && !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
- && !isFingerprintDisabledByAdmin()) {
+ } else if (hasFeatureFingerprint && shouldShowFingerprintEnroll) {
extras = getFingerprintChooseLockExtras();
} else {
extras = new Bundle();
}
+
// No matter we show fingerprint options or not, we should tell the next activity which
// user is setting new password.
extras.putInt(Intent.EXTRA_USER_ID, mTargetUserId);
mUi.launchChooseLock(extras);
}
+ private Bundle getBiometricChooseLockExtras() {
+ Bundle chooseLockExtras = new Bundle();
+ chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
+ PASSWORD_QUALITY_SOMETHING);
+ chooseLockExtras.putBoolean(
+ ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
+ chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
+ chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
+ return chooseLockExtras;
+ }
+
private Bundle getFingerprintChooseLockExtras() {
Bundle chooseLockExtras = new Bundle();
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index aa17f8e987..5a0a2a6e5b 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -200,8 +200,9 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
.getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false),
/* isPatternMode= */ false,
/* isAlphaMode= */ false,
- /* isFingerprintSupported= */ false,
- /* isFaceSupported= */ false
+ /* forFingerprint= */ false,
+ /* forFace= */ false,
+ /* forBiometrics= */ false
);
dialog.show(getFragmentManager());
return true;
@@ -242,7 +243,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
}
private boolean isForBiometric() {
- return mForFingerprint || mForFace;
+ return mForFingerprint || mForFace || mForBiometrics;
}
}
diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java
index 60bb0cdc30..e82dc94e12 100644
--- a/src/com/android/settings/password/SetupChooseLockPassword.java
+++ b/src/com/android/settings/password/SetupChooseLockPassword.java
@@ -104,18 +104,23 @@ public class SetupChooseLockPassword extends ChooseLockPassword {
@Override
protected void onSkipOrClearButtonClick(View view) {
if (mLeftButtonIsSkip) {
- SetupSkipDialog dialog = SetupSkipDialog.newInstance(
- getActivity().getIntent()
- .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false),
+ final Intent intent = getActivity().getIntent();
+ final boolean frpSupported = intent
+ .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false);
+ final boolean forFingerprint = intent
+ .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
+ final boolean forFace = intent
+ .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
+ final boolean forBiometrics = intent
+ .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
+
+ final SetupSkipDialog dialog = SetupSkipDialog.newInstance(
+ frpSupported,
/* isPatternMode= */ false,
mIsAlphaMode,
- getActivity().getIntent()
- .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
- false),
- getActivity().getIntent()
- .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false)
-
- );
+ forFingerprint,
+ forFace,
+ forBiometrics);
dialog.show(getFragmentManager());
return;
}
diff --git a/src/com/android/settings/password/SetupChooseLockPattern.java b/src/com/android/settings/password/SetupChooseLockPattern.java
index 8e59d8c582..e80599f3fa 100644
--- a/src/com/android/settings/password/SetupChooseLockPattern.java
+++ b/src/com/android/settings/password/SetupChooseLockPattern.java
@@ -90,18 +90,23 @@ public class SetupChooseLockPattern extends ChooseLockPattern {
@Override
protected void onSkipOrClearButtonClick(View view) {
if (mLeftButtonIsSkip) {
- SetupSkipDialog dialog = SetupSkipDialog.newInstance(
- getActivity().getIntent()
- .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false),
+ final Intent intent = getActivity().getIntent();
+ final boolean frpSupported = intent
+ .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false);
+ final boolean forFingerprint = intent
+ .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
+ final boolean forFace = intent
+ .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
+ final boolean forBiometrics = intent
+ .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
+
+ final SetupSkipDialog dialog = SetupSkipDialog.newInstance(
+ frpSupported,
/* isPatternMode= */ true,
/* isAlphaMode= */ false,
- getActivity().getIntent()
- .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
- false),
- getActivity().getIntent()
- .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false)
-
- );
+ forFingerprint,
+ forFace,
+ forBiometrics);
dialog.show(getFragmentManager());
return;
}
diff --git a/src/com/android/settings/password/SetupSkipDialog.java b/src/com/android/settings/password/SetupSkipDialog.java
index 68f8dd4888..ef00357ae8 100644
--- a/src/com/android/settings/password/SetupSkipDialog.java
+++ b/src/com/android/settings/password/SetupSkipDialog.java
@@ -43,14 +43,16 @@ public class SetupSkipDialog extends InstrumentedDialogFragment
public static final int RESULT_SKIP = Activity.RESULT_FIRST_USER + 10;
public static SetupSkipDialog newInstance(boolean isFrpSupported, boolean isPatternMode,
- boolean isAlphanumericMode, boolean isFingerprintSupported, boolean isFaceSupported) {
+ boolean isAlphanumericMode, boolean forFingerprint, boolean forFace,
+ boolean forBiometrics) {
SetupSkipDialog dialog = new SetupSkipDialog();
Bundle args = new Bundle();
args.putBoolean(ARG_FRP_SUPPORTED, isFrpSupported);
args.putBoolean(ARG_LOCK_TYPE_PATTERN, isPatternMode);
args.putBoolean(ARG_LOCK_TYPE_ALPHANUMERIC, isAlphanumericMode);
- args.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, isFingerprintSupported);
- args.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, isFaceSupported);
+ args.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, forFingerprint);
+ args.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, forFace);
+ args.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, forBiometrics);
dialog.setArguments(args);
return dialog;
}
@@ -68,11 +70,13 @@ public class SetupSkipDialog extends InstrumentedDialogFragment
@NonNull
public AlertDialog.Builder onCreateDialogBuilder() {
Bundle args = getArguments();
- final boolean isFaceSupported =
+ final boolean forFace =
args.getBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE);
- final boolean isFingerprintSupported =
+ final boolean forFingerprint =
args.getBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT);
- if (isFaceSupported || isFingerprintSupported) {
+ final boolean forBiometrics =
+ args.getBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS);
+ if (forFace || forFingerprint || forBiometrics) {
final int titleId;
if (args.getBoolean(ARG_LOCK_TYPE_PATTERN)) {
@@ -82,13 +86,20 @@ public class SetupSkipDialog extends InstrumentedDialogFragment
R.string.lock_screen_password_skip_title : R.string.lock_screen_pin_skip_title;
}
+ final int msgResId;
+ if (forBiometrics) {
+ msgResId = R.string.biometrics_lock_screen_setup_skip_dialog_text;
+ } else if (forFace) {
+ msgResId = R.string.face_lock_screen_setup_skip_dialog_text;
+ } else {
+ msgResId = R.string.fingerprint_lock_screen_setup_skip_dialog_text;
+ }
+
return new AlertDialog.Builder(getContext())
.setPositiveButton(R.string.skip_lock_screen_dialog_button_label, this)
.setNegativeButton(R.string.cancel_lock_screen_dialog_button_label, this)
.setTitle(titleId)
- .setMessage(isFaceSupported ?
- R.string.face_lock_screen_setup_skip_dialog_text :
- R.string.fingerprint_lock_screen_setup_skip_dialog_text);
+ .setMessage(msgResId);
} else {
return new AlertDialog.Builder(getContext())
.setPositiveButton(R.string.skip_anyway_button_label, this)