Merge changes from topic "face-settings"
* changes: 3/n: Remove all faces when Pin/Pattern/Pass is removed 2/n: Add face to ChooseLock* 1/n Start adding Face settings (base, intro)
This commit is contained in:
@@ -110,8 +110,10 @@ public class EncryptionInterstitial extends SettingsActivity {
|
||||
|
||||
mRequirePasswordToDecrypt = view.findViewById(R.id.encrypt_require_password);
|
||||
mDontRequirePasswordToDecrypt = view.findViewById(R.id.encrypt_dont_require_password);
|
||||
boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
|
||||
final boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
|
||||
final boolean forFace = getActivity().getIntent()
|
||||
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
|
||||
Intent intent = getActivity().getIntent();
|
||||
mRequestedPasswordQuality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
|
||||
mUnlockMethodIntent = intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
|
||||
@@ -120,17 +122,23 @@ public class EncryptionInterstitial extends SettingsActivity {
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
||||
msgId = forFingerprint ?
|
||||
R.string.encryption_interstitial_message_pattern_for_fingerprint :
|
||||
forFace ?
|
||||
R.string.encryption_interstitial_message_pattern_for_face :
|
||||
R.string.encryption_interstitial_message_pattern;
|
||||
break;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||
msgId = forFingerprint ?
|
||||
R.string.encryption_interstitial_message_pin_for_fingerprint :
|
||||
forFace ?
|
||||
R.string.encryption_interstitial_message_pin_for_face :
|
||||
R.string.encryption_interstitial_message_pin;
|
||||
break;
|
||||
default:
|
||||
msgId = forFingerprint ?
|
||||
R.string.encryption_interstitial_message_password_for_fingerprint :
|
||||
forFace ?
|
||||
R.string.encryption_interstitial_message_password_for_face :
|
||||
R.string.encryption_interstitial_message_password;
|
||||
break;
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.VectorDrawable;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.LinkProperties;
|
||||
@@ -813,6 +814,19 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
return fingerprintManager != null && fingerprintManager.isHardwareDetected();
|
||||
}
|
||||
|
||||
public static FaceManager getFaceManagerOrNull(Context context) {
|
||||
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
|
||||
return (FaceManager) context.getSystemService(Context.FACE_SERVICE);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasFaceHardware(Context context) {
|
||||
FaceManager faceManager = getFaceManagerOrNull(context);
|
||||
return faceManager != null && faceManager.isHardwareDetected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches an intent which may optionally have a user id defined.
|
||||
* @param fragment Fragment to use to launch the activity.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2018 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint;
|
||||
package com.android.settings.biometrics;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Intent;
|
||||
@@ -29,6 +29,8 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SetupWizardUtils;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintSettings;
|
||||
import com.android.settings.core.InstrumentedActivity;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.setupwizardlib.GlifLayout;
|
||||
@@ -36,11 +38,11 @@ import com.android.setupwizardlib.GlifLayout;
|
||||
/**
|
||||
* Base activity for all fingerprint enrollment steps.
|
||||
*/
|
||||
public abstract class FingerprintEnrollBase extends InstrumentedActivity
|
||||
public abstract class BiometricEnrollBase extends InstrumentedActivity
|
||||
implements View.OnClickListener {
|
||||
public static final int RESULT_FINISHED = FingerprintSettings.RESULT_FINISHED;
|
||||
static final int RESULT_SKIP = FingerprintSettings.RESULT_SKIP;
|
||||
static final int RESULT_TIMEOUT = FingerprintSettings.RESULT_TIMEOUT;
|
||||
public static final int RESULT_FINISHED = BiometricSettings.RESULT_FINISHED;
|
||||
public static final int RESULT_SKIP = BiometricSettings.RESULT_SKIP;
|
||||
public static final int RESULT_TIMEOUT = BiometricSettings.RESULT_TIMEOUT;
|
||||
|
||||
protected byte[] mToken;
|
||||
protected int mUserId;
|
||||
@@ -118,7 +120,7 @@ public abstract class FingerprintEnrollBase extends InstrumentedActivity
|
||||
protected void onNextButtonClick() {
|
||||
}
|
||||
|
||||
protected Intent getEnrollingIntent() {
|
||||
protected Intent getFingerprintEnrollingIntent() {
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings", FingerprintEnrollEnrolling.class.getName());
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
|
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.admin.DevicePolicyManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.password.ChooseLockGeneric;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.setupwizardlib.span.LinkSpan;
|
||||
|
||||
/**
|
||||
* Abstract base class for the intro onboarding activity for biometric enrollment.
|
||||
*/
|
||||
public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
implements LinkSpan.OnClickListener {
|
||||
|
||||
public static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
|
||||
public static final int BIOMETRIC_FIND_SENSOR_REQUEST = 2;
|
||||
public static final int LEARN_MORE_REQUEST = 3;
|
||||
|
||||
private UserManager mUserManager;
|
||||
private boolean mHasPassword;
|
||||
private boolean mBiometricUnlockDisabledByAdmin;
|
||||
private TextView mErrorText;
|
||||
|
||||
/**
|
||||
* @return true if the biometric is disabled by a device administrator
|
||||
*/
|
||||
protected abstract boolean isDisabledByAdmin();
|
||||
|
||||
/**
|
||||
* @return the layout resource
|
||||
*/
|
||||
protected abstract int getLayoutResource();
|
||||
|
||||
/**
|
||||
* @return the header resource for if the biometric has been disabled by a device administrator
|
||||
*/
|
||||
protected abstract int getHeaderResDisabledByAdmin();
|
||||
|
||||
/**
|
||||
* @return the default header resource
|
||||
*/
|
||||
protected abstract int getHeaderResDefault();
|
||||
|
||||
/**
|
||||
* @return the description resource for if the biometric has been disabled by a device admin
|
||||
*/
|
||||
protected abstract int getDescriptionResDisabledByAdmin();
|
||||
|
||||
/**
|
||||
* @return the cancel button
|
||||
*/
|
||||
protected abstract Button getCancelButton();
|
||||
|
||||
/**
|
||||
* @return the next button
|
||||
*/
|
||||
protected abstract Button getNextButton();
|
||||
|
||||
/**
|
||||
* @return the error TextView
|
||||
*/
|
||||
protected abstract TextView getErrorTextView();
|
||||
|
||||
/**
|
||||
* @return 0 if there are no errors, otherwise returns the resource ID for the error string
|
||||
* to be displayed.
|
||||
*/
|
||||
protected abstract int checkMaxEnrolled();
|
||||
|
||||
/**
|
||||
* @return the challenge generated by the biometric hardware
|
||||
*/
|
||||
protected abstract long getChallenge();
|
||||
|
||||
/**
|
||||
* @return one of the ChooseLockSettingsHelper#EXTRA_KEY_FOR_* constants
|
||||
*/
|
||||
protected abstract String getExtraKeyForBiometric();
|
||||
|
||||
/**
|
||||
* @return the intent for proceeding to the next step of enrollment
|
||||
*/
|
||||
protected abstract Intent getFindSensorIntent();
|
||||
|
||||
/**
|
||||
* @param span
|
||||
*/
|
||||
public abstract void onClick(LinkSpan span);
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mBiometricUnlockDisabledByAdmin = isDisabledByAdmin();
|
||||
|
||||
setContentView(getLayoutResource());
|
||||
if (mBiometricUnlockDisabledByAdmin) {
|
||||
setHeaderText(getHeaderResDisabledByAdmin());
|
||||
} else {
|
||||
setHeaderText(getHeaderResDefault());
|
||||
}
|
||||
|
||||
Button cancelButton = getCancelButton();
|
||||
cancelButton.setOnClickListener(v -> onCancelButtonClick());
|
||||
|
||||
mErrorText = getErrorTextView();
|
||||
|
||||
mUserManager = UserManager.get(this);
|
||||
updatePasswordQuality();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
final int errorMsg = checkMaxEnrolled();
|
||||
if (errorMsg == 0) {
|
||||
mErrorText.setText(null);
|
||||
getNextButton().setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mErrorText.setText(errorMsg);
|
||||
getNextButton().setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePasswordQuality() {
|
||||
final int passwordQuality = new ChooseLockSettingsHelper(this).utils()
|
||||
.getActivePasswordQuality(mUserManager.getCredentialOwnerProfile(mUserId));
|
||||
mHasPassword = passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNextButtonClick() {
|
||||
if (!mHasPassword) {
|
||||
// No biometrics registered, launch into enrollment wizard.
|
||||
launchChooseLock();
|
||||
} else {
|
||||
// Lock thingy is already set up, launch directly into find sensor step from wizard.
|
||||
launchFindSensor(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void launchChooseLock() {
|
||||
Intent intent = getChooseLockIntent();
|
||||
long challenge = getChallenge();
|
||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
|
||||
intent.putExtra(getExtraKeyForBiometric(), true);
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
}
|
||||
startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
|
||||
}
|
||||
|
||||
private void launchFindSensor(byte[] token) {
|
||||
Intent intent = getFindSensorIntent();
|
||||
if (token != null) {
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
}
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
}
|
||||
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
|
||||
}
|
||||
|
||||
protected Intent getChooseLockIntent() {
|
||||
return new Intent(this, ChooseLockGeneric.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
final boolean isResultFinished = resultCode == RESULT_FINISHED;
|
||||
if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
|
||||
if (isResultFinished || resultCode == RESULT_SKIP) {
|
||||
final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
|
||||
setResult(result, data);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
} else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
|
||||
if (isResultFinished) {
|
||||
updatePasswordQuality();
|
||||
byte[] token = data.getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
launchFindSensor(token);
|
||||
return;
|
||||
}
|
||||
} else if (requestCode == LEARN_MORE_REQUEST) {
|
||||
overridePendingTransition(R.anim.suw_slide_back_in, R.anim.suw_slide_back_out);
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
protected void onCancelButtonClick() {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
super.initViews();
|
||||
|
||||
TextView description = (TextView) findViewById(R.id.description_text);
|
||||
if (mBiometricUnlockDisabledByAdmin) {
|
||||
description.setText(getDescriptionResDisabledByAdmin());
|
||||
}
|
||||
}
|
||||
}
|
48
src/com/android/settings/biometrics/BiometricSettings.java
Normal file
48
src/com/android/settings/biometrics/BiometricSettings.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 com.android.settings.SubSettings;
|
||||
|
||||
/**
|
||||
* Abstract base class for biometric settings, such as Fingerprint, Face, Iris
|
||||
*/
|
||||
public abstract class BiometricSettings extends SubSettings {
|
||||
/**
|
||||
* Used by the choose fingerprint wizard to indicate the wizard is
|
||||
* finished, and each activity in the wizard should finish.
|
||||
* <p>
|
||||
* Previously, each activity in the wizard would finish itself after
|
||||
* starting the next activity. However, this leads to broken 'Back'
|
||||
* behavior. So, now an activity does not finish itself until it gets this
|
||||
* result.
|
||||
*/
|
||||
protected static final int RESULT_FINISHED = RESULT_FIRST_USER;
|
||||
|
||||
/**
|
||||
* Used by the enrolling screen during setup wizard to skip over setting up fingerprint, which
|
||||
* will be useful if the user accidentally entered this flow.
|
||||
*/
|
||||
protected static final int RESULT_SKIP = RESULT_FIRST_USER + 1;
|
||||
|
||||
/**
|
||||
* Like {@link #RESULT_FINISHED} except this one indicates enrollment failed because the
|
||||
* device was left idle. This is used to clear the credential token to require the user to
|
||||
* re-enter their pin/pattern/password before continuing.
|
||||
*/
|
||||
protected static final int RESULT_TIMEOUT = RESULT_FIRST_USER + 2;
|
||||
}
|
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public abstract class BiometricStatusPreferenceController extends BasePreferenceController {
|
||||
|
||||
protected final UserManager mUm;
|
||||
protected final LockPatternUtils mLockPatternUtils;
|
||||
|
||||
protected final int mUserId = UserHandle.myUserId();
|
||||
protected final int mProfileChallengeUserId;
|
||||
|
||||
/**
|
||||
* @return true if the manager is not null and the hardware is detected.
|
||||
*/
|
||||
protected abstract boolean isDeviceSupported();
|
||||
|
||||
/**
|
||||
* @return true if the user has enrolled biometrics of the subclassed type.
|
||||
*/
|
||||
protected abstract boolean hasEnrolledBiometrics();
|
||||
|
||||
/**
|
||||
* @return the summary text if biometrics are enrolled.
|
||||
*/
|
||||
protected abstract String getSummaryTextEnrolled();
|
||||
|
||||
/**
|
||||
* @return the summary text if no biometrics are enrolled.
|
||||
*/
|
||||
protected abstract String getSummaryTextNoneEnrolled();
|
||||
|
||||
/**
|
||||
* @return the class name for the settings page.
|
||||
*/
|
||||
protected abstract String getSettingsClassName();
|
||||
|
||||
/**
|
||||
* @return the class name for entry to enrollment.
|
||||
*/
|
||||
protected abstract String getEnrollClassName();
|
||||
|
||||
public BiometricStatusPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mLockPatternUtils = FeatureFactory.getFactory(context)
|
||||
.getSecurityFeatureProvider()
|
||||
.getLockPatternUtils(context);
|
||||
mProfileChallengeUserId = Utils.getManagedProfileId(mUm, mUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (!isDeviceSupported()) {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
if (isUserSupported()) {
|
||||
return AVAILABLE;
|
||||
} else {
|
||||
return DISABLED_FOR_USER;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (!isAvailable()) {
|
||||
if (preference != null) {
|
||||
preference.setVisible(false);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
preference.setVisible(true);
|
||||
}
|
||||
final int userId = getUserId();
|
||||
final String clazz;
|
||||
if (hasEnrolledBiometrics()) {
|
||||
preference.setSummary(getSummaryTextEnrolled());
|
||||
clazz = getSettingsClassName();
|
||||
} else {
|
||||
preference.setSummary(getSummaryTextNoneEnrolled());
|
||||
clazz = getEnrollClassName();
|
||||
}
|
||||
preference.setOnPreferenceClickListener(target -> {
|
||||
final Context context = target.getContext();
|
||||
final UserManager userManager = UserManager.get(context);
|
||||
if (Utils.startQuietModeDialogIfNecessary(context, userManager,
|
||||
userId)) {
|
||||
return false;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings", clazz);
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, userId);
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
protected int getUserId() {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
protected boolean isUserSupported() {
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.face;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Intent;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricEnrollIntroduction;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.setupwizardlib.span.LinkSpan;
|
||||
|
||||
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
|
||||
private static final String TAG = "FaceIntro";
|
||||
|
||||
private FaceManager mFaceManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mFaceManager = Utils.getFaceManagerOrNull(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDisabledByAdmin() {
|
||||
return RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
|
||||
this, DevicePolicyManager.KEYGUARD_DISABLE_FACE, mUserId) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutResource() {
|
||||
return R.layout.face_enroll_introduction;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHeaderResDisabledByAdmin() {
|
||||
return R.string.security_settings_face_enroll_introduction_title_unlock_disabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHeaderResDefault() {
|
||||
return R.string.security_settings_face_enroll_introduction_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDescriptionResDisabledByAdmin() {
|
||||
return R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Button getCancelButton() {
|
||||
return findViewById(R.id.face_cancel_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Button getNextButton() {
|
||||
return findViewById(R.id.face_next_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextView getErrorTextView() {
|
||||
return findViewById(R.id.error_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int checkMaxEnrolled() {
|
||||
if (mFaceManager != null) {
|
||||
final int max = getResources().getInteger(
|
||||
com.android.internal.R.integer.config_faceMaxTemplatesPerUser);
|
||||
final int numEnrolledFaces = mFaceManager.getEnrolledFaces(mUserId).size();
|
||||
if (numEnrolledFaces >= max) {
|
||||
return R.string.face_intro_error_max;
|
||||
}
|
||||
} else {
|
||||
return R.string.face_intro_error_unknown;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getChallenge() {
|
||||
if (mFaceManager == null) {
|
||||
return 0;
|
||||
}
|
||||
return mFaceManager.preEnroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getExtraKeyForBiometric() {
|
||||
return ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getFindSensorIntent() {
|
||||
return null; // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.FACE_ENROLL_INTRO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(LinkSpan span) {
|
||||
// TODO(b/110906762)
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.face;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.face.FaceManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricStatusPreferenceController;
|
||||
|
||||
public class FaceStatusPreferenceController extends BiometricStatusPreferenceController {
|
||||
|
||||
private static final String KEY_FACE_SETTINGS = "face_settings";
|
||||
|
||||
protected final FaceManager mFaceManager;
|
||||
|
||||
public FaceStatusPreferenceController(Context context) {
|
||||
this(context, KEY_FACE_SETTINGS);
|
||||
}
|
||||
|
||||
public FaceStatusPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
mFaceManager = Utils.getFaceManagerOrNull(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDeviceSupported() {
|
||||
return mFaceManager != null && mFaceManager.isHardwareDetected();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasEnrolledBiometrics() {
|
||||
return mFaceManager.hasEnrolledFaces(mUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSummaryTextEnrolled() {
|
||||
return mContext.getResources()
|
||||
.getString(R.string.security_settings_face_preference_summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSummaryTextNoneEnrolled() {
|
||||
return mContext.getResources()
|
||||
.getString(R.string.security_settings_face_preference_summary_none);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSettingsClassName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getEnrollClassName() {
|
||||
return FaceEnrollIntroduction.class.getName();
|
||||
}
|
||||
|
||||
}
|
@@ -44,13 +44,14 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
/**
|
||||
* Activity which handles the actual enrolling for fingerprint.
|
||||
*/
|
||||
public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
|
||||
public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
implements FingerprintEnrollSidecar.Listener {
|
||||
|
||||
static final String TAG_SIDECAR = "sidecar";
|
||||
|
@@ -27,6 +27,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollSidecar.Listener;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
@@ -35,7 +36,7 @@ import androidx.annotation.Nullable;
|
||||
/**
|
||||
* Activity explaining the fingerprint sensor location for fingerprint enrollment.
|
||||
*/
|
||||
public class FingerprintEnrollFindSensor extends FingerprintEnrollBase {
|
||||
public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
|
||||
|
||||
@VisibleForTesting
|
||||
static final int CONFIRM_REQUEST = 1;
|
||||
@@ -166,7 +167,7 @@ public class FingerprintEnrollFindSensor extends FingerprintEnrollBase {
|
||||
}
|
||||
getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
|
||||
mSidecar = null;
|
||||
startActivityForResult(getEnrollingIntent(), ENROLLING);
|
||||
startActivityForResult(getFingerprintEnrollingIntent(), ENROLLING);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -25,11 +25,12 @@ import android.widget.Button;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
|
||||
/**
|
||||
* Activity which concludes fingerprint enrollment.
|
||||
*/
|
||||
public class FingerprintEnrollFinish extends FingerprintEnrollBase {
|
||||
public class FingerprintEnrollFinish extends BiometricEnrollBase {
|
||||
|
||||
private static final int REQUEST_ADD_ANOTHER = 1;
|
||||
|
||||
@@ -71,7 +72,7 @@ public class FingerprintEnrollFinish extends FingerprintEnrollBase {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.add_another_button) {
|
||||
startActivityForResult(getEnrollingIntent(), REQUEST_ADD_ANOTHER);
|
||||
startActivityForResult(getFingerprintEnrollingIntent(), REQUEST_ADD_ANOTHER);
|
||||
}
|
||||
super.onClick(v);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2018 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.
|
||||
@@ -21,195 +21,109 @@ import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.password.ChooseLockGeneric;
|
||||
import com.android.settings.biometrics.BiometricEnrollIntroduction;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settingslib.HelpUtils;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.setupwizardlib.span.LinkSpan;
|
||||
|
||||
/**
|
||||
* Onboarding activity for fingerprint enrollment.
|
||||
*/
|
||||
public class FingerprintEnrollIntroduction extends FingerprintEnrollBase
|
||||
implements View.OnClickListener, LinkSpan.OnClickListener {
|
||||
public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
|
||||
private static final String TAG = "FingerprintIntro";
|
||||
|
||||
protected static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
|
||||
protected static final int FINGERPRINT_FIND_SENSOR_REQUEST = 2;
|
||||
protected static final int LEARN_MORE_REQUEST = 3;
|
||||
|
||||
private UserManager mUserManager;
|
||||
private boolean mHasPassword;
|
||||
private boolean mFingerprintUnlockDisabledByAdmin;
|
||||
private TextView mErrorText;
|
||||
private FingerprintManager mFingerprintManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mFingerprintUnlockDisabledByAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
|
||||
this, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId) != null;
|
||||
|
||||
setContentView(R.layout.fingerprint_enroll_introduction);
|
||||
if (mFingerprintUnlockDisabledByAdmin) {
|
||||
setHeaderText(R.string
|
||||
.security_settings_fingerprint_enroll_introduction_title_unlock_disabled);
|
||||
} else {
|
||||
setHeaderText(R.string.security_settings_fingerprint_enroll_introduction_title);
|
||||
}
|
||||
|
||||
Button cancelButton = (Button) findViewById(R.id.fingerprint_cancel_button);
|
||||
cancelButton.setOnClickListener(this);
|
||||
|
||||
mErrorText = (TextView) findViewById(R.id.error_text);
|
||||
|
||||
mUserManager = UserManager.get(this);
|
||||
updatePasswordQuality();
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(this);
|
||||
int errorMsg = 0;
|
||||
if (fingerprintManager != null) {
|
||||
final int max = getResources().getInteger(
|
||||
com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
|
||||
final int numEnrolledFingerprints =
|
||||
fingerprintManager.getEnrolledFingerprints(mUserId).size();
|
||||
if (numEnrolledFingerprints >= max) {
|
||||
errorMsg = R.string.fingerprint_intro_error_max;
|
||||
}
|
||||
} else {
|
||||
errorMsg = R.string.fingerprint_intro_error_unknown;
|
||||
}
|
||||
if (errorMsg == 0) {
|
||||
mErrorText.setText(null);
|
||||
getNextButton().setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mErrorText.setText(errorMsg);
|
||||
getNextButton().setVisibility(View.GONE);
|
||||
}
|
||||
protected boolean isDisabledByAdmin() {
|
||||
return RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
|
||||
this, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId) != null;
|
||||
}
|
||||
|
||||
private void updatePasswordQuality() {
|
||||
final int passwordQuality = new ChooseLockSettingsHelper(this).utils()
|
||||
.getActivePasswordQuality(mUserManager.getCredentialOwnerProfile(mUserId));
|
||||
mHasPassword = passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||
@Override
|
||||
protected int getLayoutResource() {
|
||||
return R.layout.fingerprint_enroll_introduction;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHeaderResDisabledByAdmin() {
|
||||
return R.string.security_settings_fingerprint_enroll_introduction_title_unlock_disabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHeaderResDefault() {
|
||||
return R.string.security_settings_fingerprint_enroll_introduction_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDescriptionResDisabledByAdmin() {
|
||||
return R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Button getCancelButton() {
|
||||
return findViewById(R.id.fingerprint_cancel_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Button getNextButton() {
|
||||
return (Button) findViewById(R.id.fingerprint_next_button);
|
||||
return findViewById(R.id.fingerprint_next_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNextButtonClick() {
|
||||
if (!mHasPassword) {
|
||||
// No fingerprints registered, launch into enrollment wizard.
|
||||
launchChooseLock();
|
||||
protected TextView getErrorTextView() {
|
||||
return findViewById(R.id.error_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int checkMaxEnrolled() {
|
||||
if (mFingerprintManager != null) {
|
||||
final int max = getResources().getInteger(
|
||||
com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
|
||||
final int numEnrolledFingerprints =
|
||||
mFingerprintManager.getEnrolledFingerprints(mUserId).size();
|
||||
if (numEnrolledFingerprints >= max) {
|
||||
return R.string.fingerprint_intro_error_max;
|
||||
}
|
||||
} else {
|
||||
// Lock thingy is already set up, launch directly into find sensor step from wizard.
|
||||
launchFindSensor(null);
|
||||
return R.string.fingerprint_intro_error_unknown;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void launchChooseLock() {
|
||||
Intent intent = getChooseLockIntent();
|
||||
long challenge = Utils.getFingerprintManagerOrNull(this).preEnroll();
|
||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
@Override
|
||||
protected long getChallenge() {
|
||||
if (mFingerprintManager == null) {
|
||||
return 0;
|
||||
}
|
||||
startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
|
||||
return mFingerprintManager.preEnroll();
|
||||
}
|
||||
|
||||
private void launchFindSensor(byte[] token) {
|
||||
Intent intent = getFindSensorIntent();
|
||||
if (token != null) {
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
}
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
}
|
||||
startActivityForResult(intent, FINGERPRINT_FIND_SENSOR_REQUEST);
|
||||
}
|
||||
|
||||
protected Intent getChooseLockIntent() {
|
||||
return new Intent(this, ChooseLockGeneric.class);
|
||||
@Override
|
||||
protected String getExtraKeyForBiometric() {
|
||||
return ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getFindSensorIntent() {
|
||||
return new Intent(this, FingerprintEnrollFindSensor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
final boolean isResultFinished = resultCode == RESULT_FINISHED;
|
||||
if (requestCode == FINGERPRINT_FIND_SENSOR_REQUEST) {
|
||||
if (isResultFinished || resultCode == RESULT_SKIP) {
|
||||
final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
|
||||
setResult(result, data);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
} else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
|
||||
if (isResultFinished) {
|
||||
updatePasswordQuality();
|
||||
byte[] token = data.getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
launchFindSensor(token);
|
||||
return;
|
||||
}
|
||||
} else if (requestCode == LEARN_MORE_REQUEST) {
|
||||
overridePendingTransition(R.anim.suw_slide_back_in, R.anim.suw_slide_back_out);
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.fingerprint_cancel_button) {
|
||||
onCancelButtonClick();
|
||||
} else {
|
||||
super.onClick(v);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.FINGERPRINT_ENROLL_INTRO;
|
||||
}
|
||||
|
||||
protected void onCancelButtonClick() {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
super.initViews();
|
||||
|
||||
TextView description = (TextView) findViewById(R.id.description_text);
|
||||
if (mFingerprintUnlockDisabledByAdmin) {
|
||||
description.setText(R.string
|
||||
.security_settings_fingerprint_enroll_introduction_message_unlock_disabled);
|
||||
}
|
||||
return MetricsProto.MetricsEvent.FINGERPRINT_ENROLL_INTRO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -43,6 +43,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricSettings;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.password.ChooseLockGeneric;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
@@ -66,34 +67,10 @@ import androidx.preference.PreferenceViewHolder;
|
||||
/**
|
||||
* Settings screen for fingerprints
|
||||
*/
|
||||
public class FingerprintSettings extends SubSettings {
|
||||
public class FingerprintSettings extends BiometricSettings {
|
||||
|
||||
private static final String TAG = "FingerprintSettings";
|
||||
|
||||
/**
|
||||
* Used by the choose fingerprint wizard to indicate the wizard is
|
||||
* finished, and each activity in the wizard should finish.
|
||||
* <p>
|
||||
* Previously, each activity in the wizard would finish itself after
|
||||
* starting the next activity. However, this leads to broken 'Back'
|
||||
* behavior. So, now an activity does not finish itself until it gets this
|
||||
* result.
|
||||
*/
|
||||
protected static final int RESULT_FINISHED = RESULT_FIRST_USER;
|
||||
|
||||
/**
|
||||
* Used by the enrolling screen during setup wizard to skip over setting up fingerprint, which
|
||||
* will be useful if the user accidentally entered this flow.
|
||||
*/
|
||||
protected static final int RESULT_SKIP = RESULT_FIRST_USER + 1;
|
||||
|
||||
/**
|
||||
* Like {@link #RESULT_FINISHED} except this one indicates enrollment failed because the
|
||||
* device was left idle. This is used to clear the credential token to require the user to
|
||||
* re-enter their pin/pattern/password before continuing.
|
||||
*/
|
||||
protected static final int RESULT_TIMEOUT = RESULT_FIRST_USER + 2;
|
||||
|
||||
private static final long LOCKOUT_DURATION = 30000; // time we have to wait for fp to reset, ms
|
||||
|
||||
public static final String ANNOTATION_URL = "url";
|
||||
|
@@ -17,32 +17,17 @@
|
||||
package com.android.settings.biometrics.fingerprint;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.biometrics.BiometricStatusPreferenceController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public class FingerprintStatusPreferenceController extends BasePreferenceController {
|
||||
public class FingerprintStatusPreferenceController extends BiometricStatusPreferenceController {
|
||||
|
||||
private static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings";
|
||||
|
||||
protected final FingerprintManager mFingerprintManager;
|
||||
protected final UserManager mUm;
|
||||
protected final LockPatternUtils mLockPatternUtils;
|
||||
|
||||
protected final int mUserId = UserHandle.myUserId();
|
||||
protected final int mProfileChallengeUserId;
|
||||
|
||||
public FingerprintStatusPreferenceController(Context context) {
|
||||
this(context, KEY_FINGERPRINT_SETTINGS);
|
||||
@@ -51,69 +36,39 @@ public class FingerprintStatusPreferenceController extends BasePreferenceControl
|
||||
public FingerprintStatusPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
|
||||
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mLockPatternUtils = FeatureFactory.getFactory(context)
|
||||
.getSecurityFeatureProvider()
|
||||
.getLockPatternUtils(context);
|
||||
mProfileChallengeUserId = Utils.getManagedProfileId(mUm, mUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (mFingerprintManager == null || !mFingerprintManager.isHardwareDetected()) {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
if (isUserSupported()) {
|
||||
return AVAILABLE;
|
||||
} else {
|
||||
return DISABLED_FOR_USER;
|
||||
}
|
||||
protected boolean isDeviceSupported() {
|
||||
return mFingerprintManager != null && mFingerprintManager.isHardwareDetected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (!isAvailable()) {
|
||||
if (preference != null) {
|
||||
preference.setVisible(false);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
preference.setVisible(true);
|
||||
}
|
||||
final int userId = getUserId();
|
||||
final List<Fingerprint> items = mFingerprintManager.getEnrolledFingerprints(userId);
|
||||
final int fingerprintCount = items != null ? items.size() : 0;
|
||||
final String clazz;
|
||||
if (fingerprintCount > 0) {
|
||||
preference.setSummary(mContext.getResources().getQuantityString(
|
||||
R.plurals.security_settings_fingerprint_preference_summary,
|
||||
fingerprintCount, fingerprintCount));
|
||||
clazz = FingerprintSettings.class.getName();
|
||||
} else {
|
||||
preference.setSummary(
|
||||
R.string.security_settings_fingerprint_preference_summary_none);
|
||||
clazz = FingerprintEnrollIntroduction.class.getName();
|
||||
}
|
||||
preference.setOnPreferenceClickListener(target -> {
|
||||
final Context context = target.getContext();
|
||||
final UserManager userManager = UserManager.get(context);
|
||||
if (Utils.startQuietModeDialogIfNecessary(context, userManager,
|
||||
userId)) {
|
||||
return false;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings", clazz);
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, userId);
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
});
|
||||
protected boolean hasEnrolledBiometrics() {
|
||||
return mFingerprintManager.hasEnrolledFingerprints(mUserId);
|
||||
}
|
||||
|
||||
protected int getUserId() {
|
||||
return mUserId;
|
||||
@Override
|
||||
protected String getSummaryTextEnrolled() {
|
||||
final int numEnrolled = mFingerprintManager.getEnrolledFingerprints(mUserId).size();
|
||||
return mContext.getResources().getQuantityString(
|
||||
R.plurals.security_settings_fingerprint_preference_summary,
|
||||
numEnrolled, numEnrolled);
|
||||
}
|
||||
|
||||
protected boolean isUserSupported() {
|
||||
return true;
|
||||
@Override
|
||||
protected String getSummaryTextNoneEnrolled() {
|
||||
return mContext.getString(R.string.security_settings_fingerprint_preference_summary_none);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSettingsClassName() {
|
||||
return FingerprintSettings.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getEnrollClassName() {
|
||||
return FingerprintEnrollIntroduction.class.getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -42,7 +42,7 @@ public class SetupFingerprintEnrollFindSensor extends FingerprintEnrollFindSenso
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getEnrollingIntent() {
|
||||
protected Intent getFingerprintEnrollingIntent() {
|
||||
Intent intent = new Intent(this, SetupFingerprintEnrollEnrolling.class);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
|
@@ -28,7 +28,7 @@ import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
public class SetupFingerprintEnrollFinish extends FingerprintEnrollFinish {
|
||||
|
||||
@Override
|
||||
protected Intent getEnrollingIntent() {
|
||||
protected Intent getFingerprintEnrollingIntent() {
|
||||
Intent intent = new Intent(this, SetupFingerprintEnrollEnrolling.class);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
|
@@ -97,7 +97,7 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
// if lock was already present, do not return intent data since it must have been
|
||||
// reported in previous attempts
|
||||
if (requestCode == FINGERPRINT_FIND_SENSOR_REQUEST && isKeyguardSecure()
|
||||
if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST && isKeyguardSecure()
|
||||
&& !mAlreadyHadLockScreenSetup) {
|
||||
data = getMetricIntent(data);
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ package com.android.settings.password;
|
||||
|
||||
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
|
||||
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
|
||||
|
||||
import static com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment
|
||||
.RESULT_FINISHED;
|
||||
|
||||
@@ -31,6 +32,8 @@ import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.hardware.face.Face;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintManager.RemovalCallback;
|
||||
@@ -52,9 +55,9 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollBase;
|
||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
@@ -99,6 +102,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 PASSWORD_CONFIRMED = "password_confirmed";
|
||||
private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
|
||||
public static final String MINIMUM_QUALITY_KEY = "minimum_quality";
|
||||
@@ -143,6 +147,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
private String mUserPassword;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private FingerprintManager mFingerprintManager;
|
||||
private FaceManager mFaceManager;
|
||||
private int mUserId;
|
||||
private boolean mHideDrawer = false;
|
||||
private ManagedLockPasswordProvider mManagedPasswordProvider;
|
||||
@@ -151,6 +156,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
private ChooseLockGenericController mController;
|
||||
|
||||
protected boolean mForFingerprint = false;
|
||||
protected boolean mForFace = false;
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
@@ -163,6 +169,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
|
||||
String chooseLockAction = getActivity().getIntent().getAction();
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(getActivity());
|
||||
mFaceManager = Utils.getFaceManagerOrNull(getActivity());
|
||||
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity());
|
||||
mLockPatternUtils = new LockPatternUtils(getActivity());
|
||||
@@ -185,6 +192,8 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
|
||||
mForFingerprint = getActivity().getIntent().getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
|
||||
mForFace = getActivity().getIntent().getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
|
||||
mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
|
||||
mUserManager = UserManager.get(getActivity());
|
||||
@@ -248,6 +257,12 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
((TextView) getHeaderView().findViewById(R.id.fingerprint_header_description))
|
||||
.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +275,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
// unlock method to an insecure one
|
||||
showFactoryResetProtectionWarningDialog(key);
|
||||
return true;
|
||||
} else if (KEY_SKIP_FINGERPRINT.equals(key)) {
|
||||
} else if (KEY_SKIP_FINGERPRINT.equals(key) || KEY_SKIP_FACE.equals(key)) {
|
||||
Intent chooseLockGenericIntent = new Intent(getActivity(),
|
||||
ChooseLockGeneric.InternalActivity.class);
|
||||
chooseLockGenericIntent.setAction(getIntent().getAction());
|
||||
@@ -310,6 +325,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(EXTRA_HIDE_DRAWER, mHideDrawer);
|
||||
startActivityForResult(
|
||||
intent,
|
||||
@@ -360,7 +377,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
}
|
||||
}
|
||||
} else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
|
||||
&& resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
|
||||
&& resultCode == BiometricEnrollBase.RESULT_FINISHED) {
|
||||
Intent intent = getFindSensorIntent(getActivity());
|
||||
if (data != null) {
|
||||
intent.putExtras(data.getExtras());
|
||||
@@ -430,6 +447,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
// Used for testing purposes
|
||||
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(ScreenLockType.PIN.preferenceKey).setViewId(R.id.lock_pin);
|
||||
findPreference(ScreenLockType.PASSWORD.preferenceKey).setViewId(R.id.lock_password);
|
||||
}
|
||||
@@ -441,6 +459,12 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
setPreferenceTitle(ScreenLockType.PIN, R.string.fingerprint_unlock_set_unlock_pin);
|
||||
setPreferenceTitle(ScreenLockType.PASSWORD,
|
||||
R.string.fingerprint_unlock_set_unlock_password);
|
||||
} else if (mForFace) {
|
||||
setPreferenceTitle(ScreenLockType.PATTERN,
|
||||
R.string.face_unlock_set_unlock_pattern);
|
||||
setPreferenceTitle(ScreenLockType.PIN, R.string.face_unlock_set_unlock_pin);
|
||||
setPreferenceTitle(ScreenLockType.PASSWORD,
|
||||
R.string.face_unlock_set_unlock_password);
|
||||
}
|
||||
|
||||
if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
|
||||
@@ -453,6 +477,9 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
if (!(mForFingerprint && mIsSetNewPassword)) {
|
||||
removePreference(KEY_SKIP_FINGERPRINT);
|
||||
}
|
||||
if (!(mForFace && mIsSetNewPassword)) {
|
||||
removePreference(KEY_SKIP_FACE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreferenceTitle(ScreenLockType lock, @StringRes int title) {
|
||||
@@ -581,6 +608,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
new ChooseLockPassword.IntentBuilder(getContext())
|
||||
.setPasswordQuality(quality)
|
||||
.setForFingerprint(mForFingerprint)
|
||||
.setForFace(mForFace)
|
||||
.setUserId(mUserId);
|
||||
if (mHasChallenge) {
|
||||
builder.setChallenge(mChallenge);
|
||||
@@ -595,6 +623,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
ChooseLockPattern.IntentBuilder builder =
|
||||
new ChooseLockPattern.IntentBuilder(getContext())
|
||||
.setForFingerprint(mForFingerprint)
|
||||
.setForFace(mForFace)
|
||||
.setUserId(mUserId);
|
||||
if (mHasChallenge) {
|
||||
builder.setChallenge(mChallenge);
|
||||
@@ -611,6 +640,30 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
unlockMethodIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps track of the biometric removal status. When all biometrics (including managed
|
||||
* profiles) are removed, finishes the activity. Otherwise, it's possible the UI still
|
||||
* shows enrolled biometrics due to the async remove.
|
||||
*/
|
||||
private class RemovalTracker {
|
||||
boolean mFingerprintDone;
|
||||
boolean mFaceDone;
|
||||
|
||||
void onFingerprintDone() {
|
||||
mFingerprintDone = true;
|
||||
if (mFingerprintDone && mFaceDone) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
void onFaceDone() {
|
||||
mFaceDone = true;
|
||||
if (mFingerprintDone && mFaceDone) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes an activity to change the user's pattern, password or PIN based on given quality
|
||||
* and minimum quality specified by DevicePolicyManager. If quality is
|
||||
@@ -647,12 +700,18 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
mChooseLockSettingsHelper.utils().clearLock(mUserPassword, mUserId);
|
||||
mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
|
||||
getActivity().setResult(Activity.RESULT_OK);
|
||||
removeAllFingerprintForUserAndFinish(mUserId);
|
||||
removeAllBiometricsForUserAndFinish(mUserId);
|
||||
} else {
|
||||
removeAllFingerprintForUserAndFinish(mUserId);
|
||||
removeAllBiometricsForUserAndFinish(mUserId);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeAllBiometricsForUserAndFinish(final int userId) {
|
||||
final RemovalTracker tracker = new RemovalTracker();
|
||||
removeAllFingerprintForUserAndFinish(userId, tracker);
|
||||
removeAllFaceForUserAndFinish(userId, tracker);
|
||||
}
|
||||
|
||||
private Intent getIntentForUnlockMethod(int quality) {
|
||||
Intent intent = null;
|
||||
if (quality >= DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
|
||||
@@ -668,7 +727,8 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
return intent;
|
||||
}
|
||||
|
||||
private void removeAllFingerprintForUserAndFinish(final int userId) {
|
||||
private void removeAllFingerprintForUserAndFinish(final int userId,
|
||||
RemovalTracker tracker) {
|
||||
if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
|
||||
if (mFingerprintManager.hasEnrolledFingerprints(userId)) {
|
||||
mFingerprintManager.setActiveUser(userId);
|
||||
@@ -690,25 +750,27 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
@Override
|
||||
public void onRemovalSucceeded(Fingerprint fp, int remaining) {
|
||||
if (remaining == 0) {
|
||||
removeManagedProfileFingerprintsAndFinishIfNecessary(userId);
|
||||
removeManagedProfileFingerprintsAndFinishIfNecessary(userId,
|
||||
tracker);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// No fingerprints in this user, we may also want to delete managed profile
|
||||
// fingerprints
|
||||
removeManagedProfileFingerprintsAndFinishIfNecessary(userId);
|
||||
removeManagedProfileFingerprintsAndFinishIfNecessary(userId, tracker);
|
||||
}
|
||||
} else {
|
||||
// The removal callback will call finish, once all fingerprints are removed.
|
||||
// We need to wait for that to occur, otherwise, the UI will still show that
|
||||
// fingerprints exist even though they are (about to) be removed depending on
|
||||
// the race condition.
|
||||
finish();
|
||||
tracker.onFingerprintDone();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId) {
|
||||
private void removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId,
|
||||
RemovalTracker tracker) {
|
||||
if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
|
||||
mFingerprintManager.setActiveUser(UserHandle.myUserId());
|
||||
}
|
||||
@@ -721,14 +783,69 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
final UserInfo userInfo = profiles.get(i);
|
||||
if (userInfo.isManagedProfile() && !mLockPatternUtils
|
||||
.isSeparateProfileChallengeEnabled(userInfo.id)) {
|
||||
removeAllFingerprintForUserAndFinish(userInfo.id);
|
||||
removeAllFingerprintForUserAndFinish(userInfo.id, tracker);
|
||||
hasChildProfile = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasChildProfile) {
|
||||
finish();
|
||||
tracker.onFingerprintDone();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: figure out how to eliminate duplicated code. It's a bit hard due to the async-ness
|
||||
private void removeAllFaceForUserAndFinish(final int userId, RemovalTracker tracker) {
|
||||
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
|
||||
if (mFaceManager.hasEnrolledFaces(userId)) {
|
||||
mFaceManager.setActiveUser(userId);
|
||||
Face face = new Face(null, 0, 0);
|
||||
mFaceManager.remove(face, userId,
|
||||
new FaceManager.RemovalCallback() {
|
||||
@Override
|
||||
public void onRemovalError(Face face, int errMsgId, CharSequence err) {
|
||||
Log.e(TAG, String.format("Can't remove face %d. Reason: %s",
|
||||
face.getBiometricId(), err));
|
||||
}
|
||||
@Override
|
||||
public void onRemovalSucceeded(Face face, int remaining) {
|
||||
if (remaining == 0) {
|
||||
removeManagedProfileFacesAndFinishIfNecessary(userId, tracker);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// No faces in this user, we may also want to delete managed profile faces
|
||||
removeManagedProfileFacesAndFinishIfNecessary(userId, tracker);
|
||||
}
|
||||
} else {
|
||||
tracker.onFaceDone();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: figure out how to eliminate duplicated code. It's a bit hard due to the async-ness
|
||||
private void removeManagedProfileFacesAndFinishIfNecessary(final int parentUserId,
|
||||
RemovalTracker tracker) {
|
||||
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
|
||||
mFaceManager.setActiveUser(UserHandle.myUserId());
|
||||
}
|
||||
boolean hasChildProfile = false;
|
||||
if (!mUserManager.getUserInfo(parentUserId).isManagedProfile()) {
|
||||
// Current user is primary profile, remove work profile faces if necessary
|
||||
final List<UserInfo> profiles = mUserManager.getProfiles(parentUserId);
|
||||
final int profilesSize = profiles.size();
|
||||
for (int i = 0; i < profilesSize; i++) {
|
||||
final UserInfo userInfo = profiles.get(i);
|
||||
if (userInfo.isManagedProfile() && !mLockPatternUtils
|
||||
.isSeparateProfileChallengeEnabled(userInfo.id)) {
|
||||
removeAllFaceForUserAndFinish(userInfo.id, tracker);
|
||||
hasChildProfile = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasChildProfile) {
|
||||
tracker.onFaceDone();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -126,6 +126,11 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder setForFace(boolean forFace) {
|
||||
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, forFace);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Intent build() {
|
||||
return mIntent;
|
||||
}
|
||||
@@ -144,11 +149,18 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
boolean forFingerprint = getIntent()
|
||||
final boolean forFingerprint = getIntent()
|
||||
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
|
||||
CharSequence msg = getText(forFingerprint
|
||||
? R.string.lockpassword_choose_your_password_header_for_fingerprint
|
||||
: R.string.lockpassword_choose_your_screen_lock_header);
|
||||
final boolean forFace = getIntent()
|
||||
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, 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);
|
||||
}
|
||||
|
||||
setTitle(msg);
|
||||
LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
|
||||
layout.setFitsSystemWindows(false);
|
||||
@@ -193,6 +205,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
private PasswordRequirementAdapter mPasswordRequirementAdapter;
|
||||
private GlifLayout mLayout;
|
||||
protected boolean mForFingerprint;
|
||||
protected boolean mForFace;
|
||||
|
||||
private String mFirstPin;
|
||||
private RecyclerView mPasswordRestrictionView;
|
||||
@@ -235,19 +248,23 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
protected enum Stage {
|
||||
|
||||
Introduction(
|
||||
R.string.lockpassword_choose_your_screen_lock_header,
|
||||
R.string.lockpassword_choose_your_screen_lock_header, // password
|
||||
R.string.lockpassword_choose_your_password_header_for_fingerprint,
|
||||
R.string.lockpassword_choose_your_screen_lock_header,
|
||||
R.string.lockpassword_choose_your_password_header_for_face,
|
||||
R.string.lockpassword_choose_your_screen_lock_header, // pin
|
||||
R.string.lockpassword_choose_your_pin_header_for_fingerprint,
|
||||
R.string.lockpassword_choose_your_password_message,
|
||||
R.string.lock_settings_picker_fingerprint_added_security_message,
|
||||
R.string.lockpassword_choose_your_pin_header_for_face,
|
||||
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,
|
||||
R.string.lock_settings_picker_fingerprint_added_security_message,
|
||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||
R.string.next_label),
|
||||
|
||||
NeedToConfirm(
|
||||
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,
|
||||
0,
|
||||
@@ -259,6 +276,8 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
ConfirmWrong(
|
||||
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,
|
||||
0,
|
||||
@@ -267,45 +286,71 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
0,
|
||||
R.string.lockpassword_confirm_label);
|
||||
|
||||
Stage(int hintInAlpha, int hintInAlphaForFingerprint,
|
||||
int hintInNumeric, int hintInNumericForFingerprint,
|
||||
int messageInAlpha, int messageInAlphaForFingerprint,
|
||||
int messageInNumeric, int messageInNumericForFingerprint,
|
||||
Stage(int hintInAlpha, int hintInAlphaForFingerprint, int hintInAlphaForFace,
|
||||
int hintInNumeric, int hintInNumericForFingerprint, int hintInNumericForFace,
|
||||
int messageInAlpha, int messageInAlphaForBiometrics,
|
||||
int messageInNumeric, int messageInNumericForBiometrics,
|
||||
int nextButtonText) {
|
||||
this.alphaHint = hintInAlpha;
|
||||
this.alphaHintForFingerprint = hintInAlphaForFingerprint;
|
||||
this.alphaHintForFace = hintInAlphaForFace;
|
||||
|
||||
this.numericHint = hintInNumeric;
|
||||
this.numericHintForFingerprint = hintInNumericForFingerprint;
|
||||
this.numericHintForFace = hintInNumericForFace;
|
||||
|
||||
this.alphaMessage = messageInAlpha;
|
||||
this.alphaMessageForFingerprint = messageInAlphaForFingerprint;
|
||||
this.alphaMessageForBiometrics = messageInAlphaForBiometrics;
|
||||
this.numericMessage = messageInNumeric;
|
||||
this.numericMessageForFingerprint = messageInNumericForFingerprint;
|
||||
this.numericMessageForBiometrics = messageInNumericForBiometrics;
|
||||
this.buttonText = nextButtonText;
|
||||
}
|
||||
|
||||
public static final int TYPE_NONE = 0;
|
||||
public static final int TYPE_FINGERPRINT = 1;
|
||||
public static final int TYPE_FACE = 2;
|
||||
|
||||
// Password
|
||||
public final int alphaHint;
|
||||
public final int alphaHintForFingerprint;
|
||||
public final int alphaHintForFace;
|
||||
|
||||
// PIN
|
||||
public final int numericHint;
|
||||
public final int numericHintForFingerprint;
|
||||
public final int numericHintForFace;
|
||||
|
||||
public final int alphaMessage;
|
||||
public final int alphaMessageForFingerprint;
|
||||
public final int alphaMessageForBiometrics;
|
||||
public final int numericMessage;
|
||||
public final int numericMessageForFingerprint;
|
||||
public final int numericMessageForBiometrics;
|
||||
public final int buttonText;
|
||||
|
||||
public @StringRes int getHint(boolean isAlpha, boolean isFingerprint) {
|
||||
public @StringRes int getHint(boolean isAlpha, int type) {
|
||||
if (isAlpha) {
|
||||
return isFingerprint ? alphaHintForFingerprint : alphaHint;
|
||||
if (type == TYPE_FINGERPRINT) {
|
||||
return alphaHintForFingerprint;
|
||||
} else if (type == TYPE_FACE) {
|
||||
return alphaHintForFace;
|
||||
} else {
|
||||
return alphaHint;
|
||||
}
|
||||
} else {
|
||||
return isFingerprint ? numericHintForFingerprint : numericHint;
|
||||
if (type == TYPE_FINGERPRINT) {
|
||||
return numericHintForFingerprint;
|
||||
} else if (type == TYPE_FACE) {
|
||||
return numericHintForFace;
|
||||
} else {
|
||||
return numericHint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public @StringRes int getMessage(boolean isAlpha, boolean isFingerprint) {
|
||||
public @StringRes int getMessage(boolean isAlpha, int type) {
|
||||
if (isAlpha) {
|
||||
return isFingerprint ? alphaMessageForFingerprint : alphaMessage;
|
||||
return type != TYPE_NONE ? alphaMessageForBiometrics : alphaMessage;
|
||||
} else {
|
||||
return isFingerprint ? numericMessageForFingerprint : numericMessage;
|
||||
return type != TYPE_NONE ? numericMessageForBiometrics : numericMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,6 +372,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
|
||||
mForFingerprint = intent.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
|
||||
mForFace = intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
|
||||
processPasswordRequirements(intent);
|
||||
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
|
||||
mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false);
|
||||
@@ -374,6 +420,8 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
mMessage = view.findViewById(R.id.message);
|
||||
if (mForFingerprint) {
|
||||
mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_fingerprint_header));
|
||||
} else if (mForFace) {
|
||||
mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_face_header));
|
||||
}
|
||||
|
||||
mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
|
||||
@@ -433,12 +481,18 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
|
||||
if (activity instanceof SettingsActivity) {
|
||||
final SettingsActivity sa = (SettingsActivity) activity;
|
||||
int title = Stage.Introduction.getHint(mIsAlphaMode, mForFingerprint);
|
||||
int title = Stage.Introduction.getHint(mIsAlphaMode, getStageType());
|
||||
sa.setTitle(title);
|
||||
mLayout.setHeaderText(title);
|
||||
}
|
||||
}
|
||||
|
||||
private int getStageType() {
|
||||
return mForFingerprint ? Stage.TYPE_FINGERPRINT :
|
||||
mForFace ? Stage.TYPE_FACE :
|
||||
Stage.TYPE_NONE;
|
||||
}
|
||||
|
||||
private void setupPasswordRequirementsView(View view) {
|
||||
final List<Integer> passwordRequirements = new ArrayList<>();
|
||||
if (mPasswordMinUpperCase > 0) {
|
||||
@@ -844,11 +898,11 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
} else {
|
||||
// Hide password requirement view when we are just asking user to confirm the pw.
|
||||
mPasswordRestrictionView.setVisibility(View.GONE);
|
||||
setHeaderText(getString(mUiStage.getHint(mIsAlphaMode, mForFingerprint)));
|
||||
setHeaderText(getString(mUiStage.getHint(mIsAlphaMode, getStageType())));
|
||||
setNextEnabled(canInput && length >= mPasswordMinLength);
|
||||
mClearButton.setEnabled(canInput && length > 0);
|
||||
}
|
||||
int message = mUiStage.getMessage(mIsAlphaMode, mForFingerprint);
|
||||
int message = mUiStage.getMessage(mIsAlphaMode, getStageType());
|
||||
if (message != 0) {
|
||||
mMessage.setVisibility(View.VISIBLE);
|
||||
mMessage.setText(message);
|
||||
|
@@ -121,6 +121,11 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder setForFace(boolean forFace) {
|
||||
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, forFace);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Intent build() {
|
||||
return mIntent;
|
||||
}
|
||||
@@ -140,10 +145,19 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
super.onCreate(savedInstanceState);
|
||||
boolean forFingerprint = getIntent()
|
||||
final boolean forFingerprint = getIntent()
|
||||
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
|
||||
setTitle(forFingerprint ? R.string.lockpassword_choose_your_pattern_header_for_fingerprint
|
||||
: R.string.lockpassword_choose_your_screen_lock_header);
|
||||
final boolean forFace = getIntent()
|
||||
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
|
||||
|
||||
int msg = R.string.lockpassword_choose_your_screen_lock_header;
|
||||
if (forFingerprint) {
|
||||
msg = R.string.lockpassword_choose_your_pattern_header_for_fingerprint;
|
||||
} else if (forFace) {
|
||||
msg = R.string.lockpassword_choose_your_pattern_header_for_face;
|
||||
}
|
||||
|
||||
setTitle(msg);
|
||||
LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
|
||||
layout.setFitsSystemWindows(false);
|
||||
}
|
||||
@@ -344,7 +358,7 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
protected enum Stage {
|
||||
|
||||
Introduction(
|
||||
R.string.lock_settings_picker_fingerprint_added_security_message,
|
||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||
R.string.lockpassword_choose_your_pattern_message,
|
||||
R.string.lockpattern_recording_intro_header,
|
||||
LeftButtonMode.Gone, RightButtonMode.ContinueDisabled,
|
||||
@@ -353,13 +367,13 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
ID_EMPTY_MESSAGE, ID_EMPTY_MESSAGE, R.string.lockpattern_settings_help_how_to_record,
|
||||
LeftButtonMode.Gone, RightButtonMode.Ok, ID_EMPTY_MESSAGE, false),
|
||||
ChoiceTooShort(
|
||||
R.string.lock_settings_picker_fingerprint_added_security_message,
|
||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||
R.string.lockpassword_choose_your_pattern_message,
|
||||
R.string.lockpattern_recording_incorrect_too_short,
|
||||
LeftButtonMode.Retry, RightButtonMode.ContinueDisabled,
|
||||
ID_EMPTY_MESSAGE, true),
|
||||
FirstChoiceValid(
|
||||
R.string.lock_settings_picker_fingerprint_added_security_message,
|
||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||
R.string.lockpassword_choose_your_pattern_message,
|
||||
R.string.lockpattern_pattern_entered_header,
|
||||
LeftButtonMode.Retry, RightButtonMode.Continue, ID_EMPTY_MESSAGE, false),
|
||||
@@ -377,7 +391,7 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
|
||||
|
||||
/**
|
||||
* @param messageForFingerprint The message displayed at the top, above header for
|
||||
* @param messageForBiometrics The message displayed at the top, above header for
|
||||
* fingerprint flow.
|
||||
* @param message The message displayed at the top.
|
||||
* @param headerMessage The message displayed at the top.
|
||||
@@ -386,12 +400,12 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
* @param footerMessage The footer message.
|
||||
* @param patternEnabled Whether the pattern widget is enabled.
|
||||
*/
|
||||
Stage(int messageForFingerprint, int message, int headerMessage,
|
||||
Stage(int messageForBiometrics, int message, int headerMessage,
|
||||
LeftButtonMode leftMode,
|
||||
RightButtonMode rightMode,
|
||||
int footerMessage, boolean patternEnabled) {
|
||||
this.headerMessage = headerMessage;
|
||||
this.messageForFingerprint = messageForFingerprint;
|
||||
this.messageForBiometrics = messageForBiometrics;
|
||||
this.message = message;
|
||||
this.leftMode = leftMode;
|
||||
this.rightMode = rightMode;
|
||||
@@ -400,7 +414,7 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
}
|
||||
|
||||
final int headerMessage;
|
||||
final int messageForFingerprint;
|
||||
final int messageForBiometrics;
|
||||
final int message;
|
||||
final LeftButtonMode leftMode;
|
||||
final RightButtonMode rightMode;
|
||||
@@ -420,6 +434,7 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
private SaveAndFinishWorker mSaveAndFinishWorker;
|
||||
protected int mUserId;
|
||||
protected boolean mForFingerprint;
|
||||
protected boolean mForFace;
|
||||
|
||||
private static final String KEY_UI_STAGE = "uiStage";
|
||||
private static final String KEY_PATTERN_CHOICE = "chosenPattern";
|
||||
@@ -451,6 +466,8 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false);
|
||||
mForFingerprint = intent.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
|
||||
mForFace = intent.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -467,6 +484,8 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
} else {
|
||||
if (mForFingerprint) {
|
||||
layout.setIcon(getActivity().getDrawable(R.drawable.ic_fingerprint_header));
|
||||
} else if (mForFace) {
|
||||
layout.setIcon(getActivity().getDrawable(R.drawable.ic_face_header));
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
@@ -663,7 +682,8 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
} else {
|
||||
mHeaderText.setText(stage.headerMessage);
|
||||
}
|
||||
int message = mForFingerprint ? stage.messageForFingerprint : stage.message;
|
||||
final boolean forBiometrics = mForFingerprint || mForFace;
|
||||
int message = forBiometrics ? stage.messageForBiometrics : stage.message;
|
||||
if (message == ID_EMPTY_MESSAGE) {
|
||||
mMessageText.setText("");
|
||||
} else {
|
||||
@@ -686,7 +706,7 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
mHeaderText.setTextColor(mDefaultHeaderColorList);
|
||||
}
|
||||
|
||||
if (stage == Stage.NeedToConfirm && mForFingerprint) {
|
||||
if (stage == Stage.NeedToConfirm && forBiometrics) {
|
||||
mHeaderText.setText("");
|
||||
mTitleText.setText(R.string.lockpassword_draw_your_pattern_again_header);
|
||||
}
|
||||
|
@@ -41,6 +41,7 @@ public final class ChooseLockSettingsHelper {
|
||||
public static final String EXTRA_KEY_CHALLENGE = "challenge";
|
||||
public static final String EXTRA_KEY_CHALLENGE_TOKEN = "hw_auth_token";
|
||||
public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
|
||||
public static final String EXTRA_KEY_FOR_FACE = "for_face";
|
||||
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
|
||||
|
||||
/**
|
||||
|
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.password;
|
||||
|
||||
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
|
||||
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE;
|
||||
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||
@@ -27,6 +28,7 @@ import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -57,6 +59,8 @@ final class SetNewPasswordController {
|
||||
private final PackageManager mPackageManager;
|
||||
@Nullable
|
||||
private final FingerprintManager mFingerprintManager;
|
||||
@Nullable
|
||||
private final FaceManager mFaceManager;
|
||||
private final DevicePolicyManager mDevicePolicyManager;
|
||||
private final Ui mUi;
|
||||
|
||||
@@ -77,9 +81,10 @@ final class SetNewPasswordController {
|
||||
}
|
||||
// Create a wrapper of FingerprintManager for testing, see IFingerPrintManager for details.
|
||||
final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context);
|
||||
final FaceManager faceManager = Utils.getFaceManagerOrNull(context);
|
||||
return new SetNewPasswordController(userId,
|
||||
context.getPackageManager(),
|
||||
fingerprintManager,
|
||||
fingerprintManager, faceManager,
|
||||
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), ui);
|
||||
}
|
||||
|
||||
@@ -88,11 +93,13 @@ final class SetNewPasswordController {
|
||||
int targetUserId,
|
||||
PackageManager packageManager,
|
||||
FingerprintManager fingerprintManager,
|
||||
FaceManager faceManager,
|
||||
DevicePolicyManager devicePolicyManager,
|
||||
Ui ui) {
|
||||
mTargetUserId = targetUserId;
|
||||
mPackageManager = checkNotNull(packageManager);
|
||||
mFingerprintManager = fingerprintManager;
|
||||
mFaceManager = faceManager;
|
||||
mDevicePolicyManager = checkNotNull(devicePolicyManager);
|
||||
mUi = checkNotNull(ui);
|
||||
}
|
||||
@@ -102,7 +109,14 @@ final class SetNewPasswordController {
|
||||
*/
|
||||
public void dispatchSetNewPasswordIntent() {
|
||||
final Bundle extras;
|
||||
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
|
||||
// TODO: handle the case with multiple biometrics, perhaps take an arg for biometric type?
|
||||
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)
|
||||
&& mFaceManager != null
|
||||
&& mFaceManager.isHardwareDetected()
|
||||
&& !mFaceManager.hasEnrolledFaces(mTargetUserId)
|
||||
&& !isFaceDisabledByAdmin()) {
|
||||
extras = getFaceChooseLockExtras();
|
||||
} else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
|
||||
&& mFingerprintManager != null
|
||||
&& mFingerprintManager.isHardwareDetected()
|
||||
&& !mFingerprintManager.hasEnrolledFingerprints(mTargetUserId)
|
||||
@@ -130,9 +144,28 @@ final class SetNewPasswordController {
|
||||
return chooseLockExtras;
|
||||
}
|
||||
|
||||
private Bundle getFaceChooseLockExtras() {
|
||||
Bundle chooseLockExtras = new Bundle();
|
||||
long challenge = mFaceManager.preEnroll();
|
||||
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
||||
PASSWORD_QUALITY_SOMETHING);
|
||||
chooseLockExtras.putBoolean(
|
||||
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
|
||||
chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
|
||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true);
|
||||
return chooseLockExtras;
|
||||
}
|
||||
|
||||
private boolean isFingerprintDisabledByAdmin() {
|
||||
int disabledFeatures =
|
||||
mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
|
||||
return (disabledFeatures & KEYGUARD_DISABLE_FINGERPRINT) != 0;
|
||||
}
|
||||
|
||||
private boolean isFaceDisabledByAdmin() {
|
||||
int disabledFeatures =
|
||||
mDevicePolicyManager.getKeyguardDisabledFeatures(null, mTargetUserId);
|
||||
return (disabledFeatures & KEYGUARD_DISABLE_FACE) != 0;
|
||||
}
|
||||
}
|
||||
|
@@ -102,8 +102,8 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
||||
|
||||
@Override
|
||||
protected void addHeaderView() {
|
||||
if (mForFingerprint) {
|
||||
setHeaderView(R.layout.setup_choose_lock_generic_fingerprint_header);
|
||||
if (mForFingerprint || mForFace) {
|
||||
setHeaderView(R.layout.setup_choose_lock_generic_biometrics_header);
|
||||
} else {
|
||||
setHeaderView(R.layout.setup_choose_lock_generic_header);
|
||||
}
|
||||
|
@@ -15,7 +15,8 @@
|
||||
*/
|
||||
package com.android.settings.security;
|
||||
|
||||
import static com.android.settings.security.EncryptionStatusPreferenceController.PREF_KEY_ENCRYPTION_SECURITY_PAGE;
|
||||
import static com.android.settings.security.EncryptionStatusPreferenceController
|
||||
.PREF_KEY_ENCRYPTION_SECURITY_PAGE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
@@ -26,11 +27,12 @@ import android.provider.SearchIndexableResource;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.face.FaceStatusPreferenceController;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintProfileStatusPreferenceController;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.enterprise.EnterprisePrivacyPreferenceController;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintProfileStatusPreferenceController;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
|
||||
import com.android.settings.location.LocationPreferenceController;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.security.trustagent.ManageTrustAgentsPreferenceController;
|
||||
@@ -123,6 +125,7 @@ public class SecuritySettings extends DashboardFragment {
|
||||
controllers.add(new TrustAgentListPreferenceController(context, host, lifecycle));
|
||||
|
||||
final List<AbstractPreferenceController> securityPreferenceControllers = new ArrayList<>();
|
||||
securityPreferenceControllers.add(new FaceStatusPreferenceController(context));
|
||||
securityPreferenceControllers.add(new FingerprintStatusPreferenceController(context));
|
||||
securityPreferenceControllers.add(new ChangeScreenLockPreferenceController(context, host));
|
||||
controllers.add(new PreferenceCategoryController(context, SECURITY_CATEGORY)
|
||||
|
Reference in New Issue
Block a user