Finish biometric enroll screens when backgrounded

Currently, there are some biometric security setting and enrollment
screens which remain open after the user has backgrounded them. This
means that they can later be resumed without requiring the user to
confirm their device credential as normal.

This commit fixes the issue in AOSP by adding logic to the affected
biometric enrollment/setting activities in to finish() with
RESULT_TIMEOUT in onStop(). We don't want to finish() these activities
prematurely if the user is currently in a wizard setup flow, however. In
that case, this commit ensures that the newly added logic will not run.

Test: Pixel 3 - Background at each step of fingerprint enroll => finish
Test: Pixel 3 - Rotate at each step of fingerprint enroll => no finish
Test: Pixel 3 - Proceed though fingerprint setup wizard => no change

Bug: 142544519
Change-Id: I8ec0fa1e30bafe097d9dc82991ff786ebf24844b
This commit is contained in:
Curtis Belmonte
2019-12-18 11:13:47 -08:00
parent 6b7b92ced5
commit 4ac1d25c2a
10 changed files with 103 additions and 51 deletions

View File

@@ -36,6 +36,7 @@ import com.android.settings.password.ChooseLockSettingsHelper;
import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.GlifLayout; import com.google.android.setupdesign.GlifLayout;
/** /**
@@ -120,6 +121,19 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
initViews(); initViews();
} }
@Override
protected void onStop() {
super.onStop();
if (!isChangingConfigurations() && shouldFinishWhenBackgrounded()) {
setResult(RESULT_TIMEOUT);
finish();
}
}
protected boolean shouldFinishWhenBackgrounded() {
return !WizardManagerHelper.isAnySetupWizard(getIntent());
}
protected void initViews() { protected void initViews() {
getWindow().setStatusBarColor(Color.TRANSPARENT); getWindow().setStatusBarColor(Color.TRANSPARENT);
} }

View File

@@ -178,6 +178,11 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
} }
} }
@Override
protected boolean shouldFinishWhenBackgrounded() {
return super.shouldFinishWhenBackgrounded() && !mConfirmingCredentials && !mNextClicked;
}
private void updatePasswordQuality() { private void updatePasswordQuality() {
final int passwordQuality = new ChooseLockSettingsHelper(this).utils() final int passwordQuality = new ChooseLockSettingsHelper(this).utils()
.getActivePasswordQuality(mUserManager.getCredentialOwnerProfile(mUserId)); .getActivePasswordQuality(mUserManager.getCredentialOwnerProfile(mUserId));
@@ -243,7 +248,8 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) { if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP) { if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP
|| resultCode == RESULT_TIMEOUT) {
setResult(resultCode, data); setResult(resultCode, data);
finish(); finish();
return; return;

View File

@@ -23,6 +23,8 @@ import android.view.View;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.google.android.setupcompat.util.WizardManagerHelper;
/** /**
* Abstract base activity which handles the actual enrolling for biometrics. * Abstract base activity which handles the actual enrolling for biometrics.
*/ */
@@ -58,7 +60,6 @@ public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop();
if (mSidecar != null) { if (mSidecar != null) {
mSidecar.setListener(null); mSidecar.setListener(null);
} }
@@ -69,6 +70,9 @@ public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
getSupportFragmentManager() getSupportFragmentManager()
.beginTransaction().remove(mSidecar).commitAllowingStateLoss(); .beginTransaction().remove(mSidecar).commitAllowingStateLoss();
} }
if (!WizardManagerHelper.isAnySetupWizard(getIntent())) {
setResult(RESULT_TIMEOUT);
}
finish(); finish();
} }
} }

View File

@@ -16,17 +16,13 @@
package com.android.settings.biometrics.face; package com.android.settings.biometrics.face;
import static android.security.KeyStore.getApplicationContext;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.hardware.face.FaceManager; import android.hardware.face.FaceManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
@@ -173,14 +169,8 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
} }
@Override @Override
protected void onStop() { protected boolean shouldFinishWhenBackgrounded() {
super.onStop(); return super.shouldFinishWhenBackgrounded() && !mNextClicked;
if (!isChangingConfigurations() && !WizardManagerHelper.isAnySetupWizard(getIntent())
&& !mNextClicked) {
setResult(RESULT_SKIP);
finish();
}
} }
@Override @Override
@@ -216,11 +206,13 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mResultIntent = data; mResultIntent = data;
if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) { if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
// If the user finished or skipped enrollment, finish this activity // If the user finished or skipped enrollment, finish this activity
if (resultCode == RESULT_SKIP || resultCode == RESULT_FINISHED) { if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP
setResult(resultCode); || resultCode == RESULT_TIMEOUT) {
setResult(resultCode, data);
finish(); finish();
} }
} }

View File

@@ -99,16 +99,6 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
footer2.setText(footer2TextResource); footer2.setText(footer2TextResource);
} }
@Override
protected void onStop() {
super.onStop();
if (!isChangingConfigurations() && !mConfirmingCredentials && !mNextClicked
&& !WizardManagerHelper.isAnySetupWizard(getIntent())) {
finish();
}
}
@Override @Override
protected boolean isDisabledByAdmin() { protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled( return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(

View File

@@ -19,7 +19,9 @@ package com.android.settings.biometrics.face;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST; import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.ENROLL_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED; import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
@@ -90,6 +92,9 @@ public class FaceSettings extends DashboardFragment {
mEnrollButton.setVisible(true); mEnrollButton.setVisible(true);
}; };
private final FaceSettingsEnrollButtonPreferenceController.Listener mEnrollListener = intent ->
startActivityForResult(intent, ENROLL_REQUEST);
public static boolean isAvailable(Context context) { public static boolean isAvailable(Context context) {
FaceManager manager = Utils.getFaceManagerOrNull(context); FaceManager manager = Utils.getFaceManagerOrNull(context);
return manager != null && manager.isHardwareDetected(); return manager != null && manager.isHardwareDetected();
@@ -230,11 +235,16 @@ public class FaceSettings extends DashboardFragment {
} }
} }
} }
} else if (requestCode == ENROLL_REQUEST) {
if (resultCode == RESULT_TIMEOUT) {
setResult(resultCode, data);
finish();
}
} }
if (mToken == null) { if (mToken == null) {
// Didn't get an authentication, finishing // Didn't get an authentication, finishing
getActivity().finish(); finish();
} }
} }
@@ -252,7 +262,7 @@ public class FaceSettings extends DashboardFragment {
} }
mToken = null; mToken = null;
} }
getActivity().finish(); finish();
} }
} }
@@ -277,6 +287,7 @@ public class FaceSettings extends DashboardFragment {
mRemoveController.setActivity((SettingsActivity) getActivity()); mRemoveController.setActivity((SettingsActivity) getActivity());
} else if (controller instanceof FaceSettingsEnrollButtonPreferenceController) { } else if (controller instanceof FaceSettingsEnrollButtonPreferenceController) {
mEnrollController = (FaceSettingsEnrollButtonPreferenceController) controller; mEnrollController = (FaceSettingsEnrollButtonPreferenceController) controller;
mEnrollController.setListener(mEnrollListener);
mEnrollController.setActivity((SettingsActivity) getActivity()); mEnrollController.setActivity((SettingsActivity) getActivity());
} }
} }

View File

@@ -43,6 +43,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
private SettingsActivity mActivity; private SettingsActivity mActivity;
private Button mButton; private Button mButton;
private boolean mIsClicked; private boolean mIsClicked;
private Listener mListener;
public FaceSettingsEnrollButtonPreferenceController(Context context) { public FaceSettingsEnrollButtonPreferenceController(Context context) {
this(context, KEY); this(context, KEY);
@@ -69,8 +70,12 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
intent.setClassName("com.android.settings", FaceEnrollIntroduction.class.getName()); intent.setClassName("com.android.settings", FaceEnrollIntroduction.class.getName());
intent.putExtra(Intent.EXTRA_USER_ID, mUserId); intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
if (mListener != null) {
mListener.onStartEnrolling(intent);
} else {
mContext.startActivity(intent); mContext.startActivity(intent);
} }
}
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
@@ -95,4 +100,19 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
public void setActivity(SettingsActivity activity) { public void setActivity(SettingsActivity activity) {
mActivity = activity; mActivity = activity;
} }
public void setListener(Listener listener) {
mListener = listener;
}
/**
* Interface for registering callbacks related to the face enroll preference button.
*/
public interface Listener {
/**
* Called when the user has indicated an intent to begin enrolling a new face.
* @param intent The Intent that should be used to launch face enrollment.
*/
void onStartEnrolling(Intent intent);
}
} }

View File

@@ -222,8 +222,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop();
stopIconAnimation(); stopIconAnimation();
super.onStop();
} }
private void animateProgress(int progress) { private void animateProgress(int progress) {

View File

@@ -115,10 +115,15 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop();
if (mAnimation != null) { if (mAnimation != null) {
mAnimation.pauseAnimation(); mAnimation.pauseAnimation();
} }
super.onStop();
}
@Override
protected boolean shouldFinishWhenBackgrounded() {
return super.shouldFinishWhenBackgrounded() && !mNextClicked;
} }
@Override @Override
@@ -163,16 +168,14 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
finish(); finish();
} }
} else if (requestCode == ENROLL_REQUEST) { } else if (requestCode == ENROLL_REQUEST) {
if (resultCode == RESULT_FINISHED) { switch (resultCode) {
setResult(RESULT_FINISHED); case RESULT_FINISHED:
case RESULT_SKIP:
case RESULT_TIMEOUT:
setResult(resultCode);
finish(); finish();
} else if (resultCode == RESULT_SKIP) { break;
setResult(RESULT_SKIP); default:
finish();
} else if (resultCode == RESULT_TIMEOUT) {
setResult(RESULT_TIMEOUT);
finish();
} else {
FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this); FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this);
int enrolled = fpm.getEnrolledFingerprints().size(); int enrolled = fpm.getEnrolledFingerprints().size();
int max = getResources().getInteger( int max = getResources().getInteger(
@@ -183,6 +186,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
// We came back from enrolling but it wasn't completed, start again. // We came back from enrolling but it wasn't completed, start again.
startLookingForFingerprint(); startLookingForFingerprint();
} }
break;
} }
} else { } else {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);

View File

@@ -133,6 +133,7 @@ public class FingerprintSettings extends SubSettings {
private Drawable mHighlightDrawable; private Drawable mHighlightDrawable;
private int mUserId; private int mUserId;
private CharSequence mFooterTitle; private CharSequence mFooterTitle;
private boolean mEnrollClicked;
private static final String TAG_AUTHENTICATE_SIDECAR = "authenticate_sidecar"; private static final String TAG_AUTHENTICATE_SIDECAR = "authenticate_sidecar";
private static final String TAG_REMOVAL_SIDECAR = "removal_sidecar"; private static final String TAG_REMOVAL_SIDECAR = "removal_sidecar";
@@ -463,6 +464,14 @@ public class FingerprintSettings extends SubSettings {
} }
} }
@Override
public void onStop() {
super.onStop();
if (!getActivity().isChangingConfigurations() && !mLaunchedConfirm && !mEnrollClicked) {
getActivity().finish();
}
}
@Override @Override
public void onSaveInstanceState(final Bundle outState) { public void onSaveInstanceState(final Bundle outState) {
outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
@@ -475,6 +484,7 @@ public class FingerprintSettings extends SubSettings {
public boolean onPreferenceTreeClick(Preference pref) { public boolean onPreferenceTreeClick(Preference pref) {
final String key = pref.getKey(); final String key = pref.getKey();
if (KEY_FINGERPRINT_ADD.equals(key)) { if (KEY_FINGERPRINT_ADD.equals(key)) {
mEnrollClicked = true;
Intent intent = new Intent(); Intent intent = new Intent();
intent.setClassName(SETTINGS_PACKAGE_NAME, intent.setClassName(SETTINGS_PACKAGE_NAME,
FingerprintEnrollEnrolling.class.getName()); FingerprintEnrollEnrolling.class.getName());
@@ -564,9 +574,10 @@ public class FingerprintSettings extends SubSettings {
} }
} }
} else if (requestCode == ADD_FINGERPRINT_REQUEST) { } else if (requestCode == ADD_FINGERPRINT_REQUEST) {
mEnrollClicked = false;
if (resultCode == RESULT_TIMEOUT) { if (resultCode == RESULT_TIMEOUT) {
Activity activity = getActivity(); Activity activity = getActivity();
activity.setResult(RESULT_TIMEOUT); activity.setResult(resultCode);
activity.finish(); activity.finish();
} }
} }