1/n: Prepare ConfirmDeviceCredentials to use BiometricPrompt
CDC is going to use BiometricPrompt instead. This change
removes FingerprintManager from CDC. BiometricPrompt
will show before pin/pattern/pass is shown.
Bug: 111461540
Test: modified BiometricPromptDemo to use
KeyguardManager#createConfirmDeviceCredentialIntent,
Test: Fingerprint is gone from CDC, rotation works
Test: atest SettingsRoboTests
Change-Id: I9ce2aad71961af8a0d5ee636600e2fbdb6154e47
This commit is contained in:
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.fingerprint;
|
||||
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.CancellationSignal;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
|
||||
/**
|
||||
* Small helper class to manage text/icon around fingerprint authentication UI.
|
||||
*/
|
||||
public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
|
||||
|
||||
private static final long ERROR_TIMEOUT = 1300;
|
||||
|
||||
private ImageView mIcon;
|
||||
private TextView mErrorTextView;
|
||||
private CancellationSignal mCancellationSignal;
|
||||
private int mUserId;
|
||||
|
||||
private Callback mCallback;
|
||||
private FingerprintManager mFingerprintManager;
|
||||
|
||||
public FingerprintUiHelper(ImageView icon, TextView errorTextView, Callback callback,
|
||||
int userId) {
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(icon.getContext());
|
||||
mIcon = icon;
|
||||
mErrorTextView = errorTextView;
|
||||
mCallback = callback;
|
||||
mUserId = userId;
|
||||
}
|
||||
|
||||
public void startListening() {
|
||||
if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()
|
||||
&& mFingerprintManager.getEnrolledFingerprints(mUserId).size() > 0) {
|
||||
mCancellationSignal = new CancellationSignal();
|
||||
mFingerprintManager.setActiveUser(mUserId);
|
||||
mFingerprintManager.authenticate(
|
||||
null, mCancellationSignal, 0 /* flags */, this, null, mUserId);
|
||||
setFingerprintIconVisibility(true);
|
||||
mIcon.setImageResource(R.drawable.ic_fingerprint);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopListening() {
|
||||
if (mCancellationSignal != null) {
|
||||
mCancellationSignal.cancel();
|
||||
mCancellationSignal = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isListening() {
|
||||
return mCancellationSignal != null && !mCancellationSignal.isCanceled();
|
||||
}
|
||||
|
||||
private void setFingerprintIconVisibility(boolean visible) {
|
||||
mIcon.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
mCallback.onFingerprintIconVisibilityChanged(visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationError(int errMsgId, CharSequence errString) {
|
||||
if (errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
|
||||
// Only happens if we get preempted by another activity. Ignored.
|
||||
return;
|
||||
}
|
||||
showError(errString);
|
||||
setFingerprintIconVisibility(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
|
||||
showError(helpString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
showError(mIcon.getResources().getString(
|
||||
R.string.fingerprint_not_recognized));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
|
||||
mIcon.setImageResource(R.drawable.ic_fingerprint_success);
|
||||
mCallback.onAuthenticated();
|
||||
}
|
||||
|
||||
private void showError(CharSequence error) {
|
||||
if (!isListening()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIcon.setImageResource(R.drawable.ic_fingerprint_error);
|
||||
mErrorTextView.setText(error);
|
||||
mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
|
||||
mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT);
|
||||
}
|
||||
|
||||
private Runnable mResetErrorTextRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mErrorTextView.setText("");
|
||||
mIcon.setImageResource(R.drawable.ic_fingerprint);
|
||||
}
|
||||
};
|
||||
|
||||
public interface Callback {
|
||||
void onAuthenticated();
|
||||
void onFingerprintIconVisibilityChanged(boolean visible);
|
||||
}
|
||||
}
|
||||
@@ -53,14 +53,12 @@ import androidx.fragment.app.FragmentManager;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintUiHelper;
|
||||
import com.android.settings.core.InstrumentedFragment;
|
||||
|
||||
/**
|
||||
* Base fragment to be shared for PIN/Pattern/Password confirmation fragments.
|
||||
*/
|
||||
public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment
|
||||
implements FingerprintUiHelper.Callback {
|
||||
public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment {
|
||||
|
||||
public static final String PACKAGE = "com.android.settings";
|
||||
public static final String TITLE_TEXT = PACKAGE + ".ConfirmCredentials.title";
|
||||
@@ -81,10 +79,8 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
/** Time we wait before clearing a wrong input attempt (e.g. pattern) and the error message. */
|
||||
protected static final long CLEAR_WRONG_ATTEMPT_TIMEOUT_MS = 3000;
|
||||
|
||||
private FingerprintUiHelper mFingerprintHelper;
|
||||
protected boolean mReturnCredentials = false;
|
||||
protected Button mCancelButton;
|
||||
protected ImageView mFingerprintIcon;
|
||||
protected int mEffectiveUserId;
|
||||
protected int mUserId;
|
||||
protected UserManager mUserManager;
|
||||
@@ -123,9 +119,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mCancelButton = (Button) view.findViewById(R.id.cancelButton);
|
||||
mFingerprintIcon = (ImageView) view.findViewById(R.id.fingerprintIcon);
|
||||
mFingerprintHelper = new FingerprintUiHelper(
|
||||
mFingerprintIcon, view.findViewById(R.id.errorText), this, mUserId);
|
||||
|
||||
boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
|
||||
SHOW_CANCEL_BUTTON, false);
|
||||
boolean hasAlternateButton = mFrp && !TextUtils.isEmpty(mFrpAlternateButtonText);
|
||||
@@ -153,29 +147,16 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFingerprintDisabledByAdmin() {
|
||||
final int disabledFeatures =
|
||||
mDevicePolicyManager.getKeyguardDisabledFeatures(null, mEffectiveUserId);
|
||||
return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
|
||||
}
|
||||
|
||||
// User could be locked while Effective user is unlocked even though the effective owns the
|
||||
// credential. Otherwise, fingerprint can't unlock fbe/keystore through
|
||||
// verifyTiedProfileChallenge. In such case, we also wanna show the user message that
|
||||
// fingerprint is disabled due to device restart.
|
||||
protected boolean isStrongAuthRequired() {
|
||||
return mFrp
|
||||
|| !mLockPatternUtils.isFingerprintAllowedForUser(mEffectiveUserId)
|
||||
|| !mLockPatternUtils.isBiometricAllowedForUser(mEffectiveUserId)
|
||||
|| !mUserManager.isUserUnlocked(mUserId);
|
||||
}
|
||||
|
||||
private boolean isFingerprintAllowed() {
|
||||
return !mReturnCredentials
|
||||
&& getActivity().getIntent().getBooleanExtra(ALLOW_FP_AUTHENTICATION, false)
|
||||
&& !isStrongAuthRequired()
|
||||
&& !isFingerprintDisabledByAdmin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
@@ -183,13 +164,6 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
}
|
||||
|
||||
protected void refreshLockScreen() {
|
||||
if (isFingerprintAllowed()) {
|
||||
mFingerprintHelper.startListening();
|
||||
} else {
|
||||
if (mFingerprintHelper.isListening()) {
|
||||
mFingerprintHelper.stopListening();
|
||||
}
|
||||
}
|
||||
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId));
|
||||
}
|
||||
|
||||
@@ -214,28 +188,10 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (mFingerprintHelper.isListening()) {
|
||||
mFingerprintHelper.stopListening();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticated() {
|
||||
// Check whether we are still active.
|
||||
if (getActivity() != null && getActivity().isResumed()) {
|
||||
TrustManager trustManager =
|
||||
(TrustManager) getActivity().getSystemService(Context.TRUST_SERVICE);
|
||||
trustManager.setDeviceLockedForUser(mEffectiveUserId, false);
|
||||
authenticationSucceeded();
|
||||
checkForPendingIntent();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void authenticationSucceeded();
|
||||
|
||||
@Override
|
||||
public void onFingerprintIconVisibilityChanged(boolean visible) {
|
||||
}
|
||||
|
||||
public void prepareEnterAnimation() {
|
||||
}
|
||||
|
||||
@@ -105,7 +105,6 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
private CountDownTimer mCountdownTimer;
|
||||
private boolean mIsAlpha;
|
||||
private InputMethodManager mImm;
|
||||
private boolean mUsingFingerprint = false;
|
||||
private AppearAnimationUtils mAppearAnimationUtils;
|
||||
private DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
|
||||
@@ -243,7 +242,6 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
mCancelButton.setAlpha(0f);
|
||||
mPasswordEntry.setAlpha(0f);
|
||||
mErrorTextView.setAlpha(0f);
|
||||
mFingerprintIcon.setAlpha(0f);
|
||||
}
|
||||
|
||||
private View[] getActiveViews() {
|
||||
@@ -255,9 +253,6 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
result.add(mPasswordEntry);
|
||||
result.add(mErrorTextView);
|
||||
if (mFingerprintIcon.getVisibility() == View.VISIBLE) {
|
||||
result.add(mFingerprintIcon);
|
||||
}
|
||||
return result.toArray(new View[] {});
|
||||
}
|
||||
|
||||
@@ -303,17 +298,12 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
mCredentialCheckResultTracker.setResult(true, new Intent(), 0, mEffectiveUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerprintIconVisibilityChanged(boolean visible) {
|
||||
mUsingFingerprint = visible;
|
||||
}
|
||||
|
||||
private void updatePasswordEntry() {
|
||||
final boolean isLockedOut =
|
||||
mLockPatternUtils.getLockoutAttemptDeadline(mEffectiveUserId) != 0;
|
||||
mPasswordEntry.setEnabled(!isLockedOut);
|
||||
mPasswordEntryInputDisabler.setInputEnabled(!isLockedOut);
|
||||
if (isLockedOut || mUsingFingerprint) {
|
||||
if (isLockedOut) {
|
||||
mImm.hideSoftInputFromWindow(mPasswordEntry.getWindowToken(), 0 /*flags*/);
|
||||
} else {
|
||||
mPasswordEntry.scheduleShowSoftInput();
|
||||
|
||||
@@ -231,7 +231,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
mCancelButton.setAlpha(0f);
|
||||
mLockPatternView.setAlpha(0f);
|
||||
mDetailsTextView.setAlpha(0f);
|
||||
mFingerprintIcon.setAlpha(0f);
|
||||
}
|
||||
|
||||
private int getDefaultDetails() {
|
||||
@@ -265,9 +264,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
result.add(row);
|
||||
}
|
||||
if (mFingerprintIcon.getVisibility() == View.VISIBLE) {
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mFingerprintIcon)));
|
||||
}
|
||||
Object[][] resultArr = new Object[result.size()][cellStates[0].length];
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
ArrayList<Object> row = result.get(i);
|
||||
@@ -377,16 +373,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerprintIconVisibilityChanged(boolean visible) {
|
||||
if (mLeftSpacerLandscape != null && mRightSpacerLandscape != null) {
|
||||
|
||||
// In landscape, adjust spacing depending on fingerprint icon visibility.
|
||||
mLeftSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
|
||||
mRightSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The pattern listener that responds according to a user confirming
|
||||
* an existing lock pattern.
|
||||
|
||||
Reference in New Issue
Block a user