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:
Kevin Chyn
2018-10-03 18:39:22 -07:00
parent dd3feeb155
commit e5a016e076
13 changed files with 6 additions and 307 deletions

View File

@@ -1,30 +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
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32.0"
android:viewportHeight="32.0">
<path
android:fillColor="?android:attr/colorError"
android:pathData="M15.99,2.5C8.53,2.5 2.5,8.54 2.5,16.0s6.03,13.5 13.49,13.5S29.5,23.46 29.5,16.0S23.45,2.5 15.99,2.5zM16.0,26.8c-5.97,0.0 -10.8,-4.83 -10.8,-10.8S10.03,5.2 16.0,5.2S26.8,10.03 26.8,16.0S21.97,26.8 16.0,26.8z"/>
<path
android:fillColor="?android:attr/colorError"
android:pathData="M14.65,20.05l2.7,0.0l0.0,2.7l-2.7,0.0z"/>
<path
android:fillColor="?android:attr/colorError"
android:pathData="M14.65,9.25l2.7,0.0l0.0,8.1l-2.7,0.0z"/>
</vector>

View File

@@ -87,14 +87,6 @@
</LinearLayout>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="end|bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="28dp"
android:layout_marginEnd="20dp"
android:visibility="gone"/>
</FrameLayout>
</LinearLayout>

View File

@@ -108,14 +108,6 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_vertical"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:visibility="gone"/>
</LinearLayout>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>

View File

@@ -85,14 +85,6 @@
android:layout_marginEnd="?attr/suwMarginSides"
android:layout_marginBottom="24dp"
android:gravity="center_vertical"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/confirm_fingerprint_icon_content_description"
android:visibility="gone"/>
</LinearLayout>
</ScrollView>

View File

@@ -89,19 +89,5 @@
</LinearLayout>
<View android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="24dp"
android:contentDescription="@string/confirm_fingerprint_icon_content_description"
android:visibility="gone"/>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
</FrameLayout>

View File

@@ -70,16 +70,6 @@
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="24dp"
android:contentDescription="@string/confirm_fingerprint_icon_content_description"
android:visibility="gone"/>
<Button
android:id="@+id/cancelButton"
style="@style/SuwGlifButton.Secondary"

View File

@@ -97,15 +97,6 @@
android:layout_marginEnd="12dp"
android:gravity="center_vertical"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="24dp"
android:contentDescription="@string/confirm_fingerprint_icon_content_description"
android:visibility="gone"/>
</LinearLayout>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>

View File

@@ -90,16 +90,6 @@
android:layout_marginTop="12dp"
android:gravity="center_vertical"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="?attr/suwMarginSides"
android:layout_marginBottom="24dp"
android:contentDescription="@string/confirm_fingerprint_icon_content_description"
android:visibility="gone"/>
<Button
android:id="@+id/cancelButton"
style="@style/SuwGlifButton.Secondary"

View File

@@ -1051,9 +1051,6 @@
<!-- Button to confirm the last removing the last fingerprint. [CHAR LIMIT=20]-->
<string name="fingerprint_last_delete_confirm">Yes, remove</string>
<!-- Content description for the fingerprint icon when the user is prompted to enter his credentials. Not shown on the screen. [CHAR LIMIT=NONE] -->
<string name="confirm_fingerprint_icon_content_description">Use your fingerprint to continue.</string>
<!-- Title of the preferences category for preference items to control encryption -->
<string name="crypt_keeper_settings_title">Encryption</string>
@@ -3771,8 +3768,8 @@
<string name="lockpassword_confirm_your_password_generic_profile">Enter your work password to continue</string>
<!-- This string shows up on a screen where a user can enter a pattern that
unlocks their device. This is an extra security measure that's required for them to
continue. [CHAR LIMIT=100] -->
unlocks their device. This is an extra security measure that's required for them to
continue. [CHAR LIMIT=100] -->
<string name="lockpassword_strong_auth_required_device_pattern">For added security, use your device pattern</string>
<!-- This string shows up on a screen where a user can enter a PIN that unlocks their device.
This is an extra security measure that's required for them to continue. [CHAR LIMIT=100]
@@ -8371,9 +8368,6 @@
<!-- Explanation that the app that will NEVER be launched to open web links to domains that it understands -->
<string name="app_link_open_never">Don&#8217;t open in this app</string>
<!-- Fingerprint hint message when finger was not recognized.-->
<string name="fingerprint_not_recognized">Not recognized</string>
<!-- Title for Default Apps settings [CHAR LIMIT=30] -->
<string name="default_apps_title">Default</string>

View File

@@ -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);
}
}

View File

@@ -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() {
}

View File

@@ -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();

View File

@@ -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.