diff --git a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java index 3a61d5e2243..2a1d049af1b 100644 --- a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java +++ b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java @@ -24,8 +24,6 @@ import android.view.View; import com.android.settings.R; import com.android.settings.password.ChooseLockSettingsHelper; -import com.google.android.setupcompat.util.WizardManagerHelper; - /** * Abstract base activity which handles the actual enrolling for biometrics. */ @@ -62,30 +60,18 @@ public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase @Override protected void onStop() { - super.onStop(); - if (mSidecar != null) { mSidecar.setListener(null); } - if (!isChangingConfigurations()) { if (mSidecar != null) { mSidecar.cancelEnrollment(); getSupportFragmentManager() .beginTransaction().remove(mSidecar).commitAllowingStateLoss(); } - if (!WizardManagerHelper.isAnySetupWizard(getIntent()) - && !BiometricUtils.isAnyMultiBiometricFlow(this)) { - setResult(RESULT_TIMEOUT); - } - finish(); } - } - @Override - protected boolean shouldFinishWhenBackgrounded() { - // Prevent super.onStop() from finishing, since we handle this in our onStop(). - return false; + super.onStop(); } @Override diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java index bf4a1d46187..68fbe3899f1 100644 --- a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java +++ b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java @@ -31,11 +31,13 @@ import com.android.settings.R; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.BiometricEnrollSidecar; import com.android.settings.biometrics.BiometricErrorDialog; +import com.android.settings.biometrics.BiometricUtils; import com.android.settings.biometrics.BiometricsEnrollEnrolling; import com.android.settings.slices.CustomSliceRegistry; import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; +import com.google.android.setupcompat.util.WizardManagerHelper; import java.util.ArrayList; @@ -112,6 +114,25 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling { startEnrollment(); } + @Override + protected void onStop() { + if (!isChangingConfigurations()) { + if (!WizardManagerHelper.isAnySetupWizard(getIntent()) + && !BiometricUtils.isAnyMultiBiometricFlow(this)) { + setResult(RESULT_TIMEOUT); + } + finish(); + } + + super.onStop(); + } + + @Override + protected boolean shouldFinishWhenBackgrounded() { + // Prevent super.onStop() from finishing, since we handle this in our onStop(). + return false; + } + @Override public void startEnrollment() { super.startEnrollment(); diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java index 5f9a74f931a..bad1bbdfc1b 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java @@ -339,8 +339,23 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { @Override protected void onStop() { - super.onStop(); + if (!isChangingConfigurations()) { + if (!WizardManagerHelper.isAnySetupWizard(getIntent()) + && !BiometricUtils.isAnyMultiBiometricFlow(this) + && !mFromSettingsSummary) { + setResult(RESULT_TIMEOUT); + } + finish(); + } stopIconAnimation(); + + super.onStop(); + } + + @Override + protected boolean shouldFinishWhenBackgrounded() { + // Prevent super.onStop() from finishing, since we handle this in our onStop(). + return false; } @Override diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java index 627a5143a38..427b50aa7c4 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java @@ -49,8 +49,8 @@ import java.util.List; public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements BiometricEnrollSidecar.Listener { - private static final String TAG = "FingerprintEnrollFindSensor"; + private static final String SAVED_STATE_IS_NEXT_CLICKED = "is_next_clicked"; @Nullable private FingerprintFindSensorAnimation mAnimation; @@ -174,6 +174,15 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements mAnimation = (FingerprintFindSensorAnimation) animationView; } } + if (savedInstanceState != null) { + mNextClicked = savedInstanceState.getBoolean(SAVED_STATE_IS_NEXT_CLICKED, mNextClicked); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(SAVED_STATE_IS_NEXT_CLICKED, mNextClicked); } @Override @@ -240,7 +249,6 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements @Override public void onEnrollmentError(int errMsgId, CharSequence errString) { if (mNextClicked && errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) { - mNextClicked = false; proceedToEnrolling(false /* cancelEnrollment */); } else { FingerprintErrorDialog.showErrorDialog(this, errMsgId); @@ -341,6 +349,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements finish(); } else { // We came back from enrolling but it wasn't completed, start again. + mNextClicked = false; startLookingForFingerprint(); } break; diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java index 16773d3cbda..b606b607a5a 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java @@ -32,7 +32,6 @@ import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.BiometricUtils; -import com.android.settings.password.ChooseLockSettingsHelper; import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; @@ -114,9 +113,6 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase { setResult(RESULT_FINISHED); if (WizardManagerHelper.isAnySetupWizard(getIntent())) { postEnroll(); - } else if (mFromSettingsSummary) { - // Only launch fingerprint settings if enrollment was triggered through settings summary - launchFingerprintSettings(); } finish(); } @@ -148,21 +144,15 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase { } } - private void launchFingerprintSettings() { - final Intent intent = new Intent(ACTION_FINGERPRINT_SETTINGS); - intent.setPackage(Utils.SETTINGS_PACKAGE_NAME); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra(Intent.EXTRA_USER_ID, mUserId); - intent.putExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, mChallenge); - startActivity(intent); - overridePendingTransition(R.anim.sud_slide_back_in, R.anim.sud_slide_back_out); - } - private void onAddAnotherButtonClick(View view) { startActivityForResult(getFingerprintEnrollingIntent(), BiometricUtils.REQUEST_ADD_ANOTHER); } + @Override + protected boolean shouldFinishWhenBackgrounded() { + return !isFinishing() && super.shouldFinishWhenBackgrounded(); + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { updateFingerprintSuggestionEnableState(); diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java index 46ea7f42351..e1acec72e34 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java @@ -22,6 +22,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROF import static android.app.admin.DevicePolicyResources.UNDEFINED; import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; +import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY; import android.app.Activity; import android.app.Dialog; @@ -62,6 +63,7 @@ import com.android.settings.SubSettings; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.BiometricUtils; +import com.android.settings.core.SettingsBaseActivity; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.password.ChooseLockGeneric; import com.android.settings.password.ChooseLockSettingsHelper; @@ -69,6 +71,7 @@ import com.android.settingslib.HelpUtils; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedLockUtilsInternal; +import com.android.settingslib.transition.SettingsTransitionHelper; import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.TwoTargetPreference; @@ -129,6 +132,8 @@ public class FingerprintSettings extends SubSettings { private static final String KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE = "fingerprint_enable_keyguard_toggle"; private static final String KEY_LAUNCHED_CONFIRM = "launched_confirm"; + private static final String KEY_HAS_FIRST_ENROLLED = "has_first_enrolled"; + private static final String KEY_IS_ENROLLING = "is_enrolled"; private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000; private static final int MSG_FINGER_AUTH_SUCCESS = 1001; @@ -140,6 +145,7 @@ public class FingerprintSettings extends SubSettings { private static final int CHOOSE_LOCK_GENERIC_REQUEST = 102; private static final int ADD_FINGERPRINT_REQUEST = 10; + private static final int AUTO_ADD_FIRST_FINGERPRINT_REQUEST = 11; protected static final boolean DEBUG = false; @@ -149,10 +155,11 @@ public class FingerprintSettings extends SubSettings { private boolean mInFingerprintLockout; private byte[] mToken; private boolean mLaunchedConfirm; + private boolean mHasFirstEnrolled = true; private Drawable mHighlightDrawable; private int mUserId; private final List mFooterColumns = new ArrayList<>(); - private boolean mEnrollClicked; + private boolean mIsEnrolling; private long mChallenge; @@ -341,6 +348,9 @@ public class FingerprintSettings extends SubSettings { } mFingerprintsRenaming = new HashMap(); + mUserId = getActivity().getIntent().getIntExtra( + Intent.EXTRA_USER_ID, UserHandle.myUserId()); + mHasFirstEnrolled = mFingerprintManager.hasEnrolledFingerprints(mUserId); if (savedInstanceState != null) { mFingerprintsRenaming = (HashMap) @@ -349,9 +359,10 @@ public class FingerprintSettings extends SubSettings { ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); mLaunchedConfirm = savedInstanceState.getBoolean( KEY_LAUNCHED_CONFIRM, false); + mIsEnrolling = savedInstanceState.getBoolean(KEY_IS_ENROLLING, mIsEnrolling); + mHasFirstEnrolled = savedInstanceState.getBoolean(KEY_HAS_FIRST_ENROLLED, + mHasFirstEnrolled); } - mUserId = getActivity().getIntent().getIntExtra( - Intent.EXTRA_USER_ID, UserHandle.myUserId()); // Need to authenticate a session token if none if (mToken == null && mLaunchedConfirm == false) { @@ -546,7 +557,7 @@ public class FingerprintSettings extends SubSettings { @Override public void onStop() { super.onStop(); - if (!getActivity().isChangingConfigurations() && !mLaunchedConfirm && !mEnrollClicked) { + if (!getActivity().isChangingConfigurations() && !mLaunchedConfirm && !mIsEnrolling) { getActivity().finish(); } } @@ -557,13 +568,15 @@ public class FingerprintSettings extends SubSettings { mToken); outState.putBoolean(KEY_LAUNCHED_CONFIRM, mLaunchedConfirm); outState.putSerializable("mFingerprintsRenaming", mFingerprintsRenaming); + outState.putBoolean(KEY_IS_ENROLLING, mIsEnrolling); + outState.putBoolean(KEY_HAS_FIRST_ENROLLED, mHasFirstEnrolled); } @Override public boolean onPreferenceTreeClick(Preference pref) { final String key = pref.getKey(); if (KEY_FINGERPRINT_ADD.equals(key)) { - mEnrollClicked = true; + mIsEnrolling = true; Intent intent = new Intent(); intent.setClassName(SETTINGS_PACKAGE_NAME, FingerprintEnrollEnrolling.class.getName()); @@ -659,6 +672,11 @@ public class FingerprintSettings extends SubSettings { BiometricUtils.removeGatekeeperPasswordHandle(getActivity(), data); updateAddPreference(); + if (!mHasFirstEnrolled && !mIsEnrolling) { + mIsEnrolling = true; + addFirstFingerprint( + BiometricUtils.getGatekeeperPasswordHandle(data)); + } }); } else { Log.d(TAG, "Data null or GK PW missing"); @@ -669,12 +687,19 @@ public class FingerprintSettings extends SubSettings { finish(); } } else if (requestCode == ADD_FINGERPRINT_REQUEST) { - mEnrollClicked = false; + mIsEnrolling = false; if (resultCode == RESULT_TIMEOUT) { Activity activity = getActivity(); activity.setResult(resultCode); activity.finish(); } + } else if (requestCode == AUTO_ADD_FIRST_FINGERPRINT_REQUEST) { + mIsEnrolling = false; + mHasFirstEnrolled = false; + if (resultCode != RESULT_FINISHED) { + Log.d(TAG, "Add first fingerprint fail, result:" + resultCode); + finish(); + } } } @@ -746,6 +771,23 @@ public class FingerprintSettings extends SubSettings { } } + private void addFirstFingerprint(@Nullable Long gkPwHandle) { + Intent intent = new Intent(); + intent.setClassName(SETTINGS_PACKAGE_NAME, + FingerprintEnrollIntroductionInternal.class.getName()); + + intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, true); + intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE, + SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE); + + intent.putExtra(Intent.EXTRA_USER_ID, mUserId); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); + if (gkPwHandle != null) { + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, (long) gkPwHandle); + } + startActivityForResult(intent, AUTO_ADD_FIRST_FINGERPRINT_REQUEST); + } + @VisibleForTesting void deleteFingerPrint(Fingerprint fingerPrint) { mRemovalSidecar.startRemove(fingerPrint, mUserId); diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java index 82ceed6c878..71cdcf73b84 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java @@ -78,8 +78,7 @@ public class FingerprintStatusUtils { * Returns the class name of the Settings page corresponding to fingerprint settings. */ public String getSettingsClassName() { - return hasEnrolled() ? FingerprintSettings.class.getName() - : FingerprintEnrollIntroductionInternal.class.getName(); + return FingerprintSettings.class.getName(); } /** diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java index ec17a8602c0..a78dbb1f52a 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java @@ -165,4 +165,76 @@ public class FingerprintEnrollFindSensorTest { null); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(Activity.RESULT_CANCELED); } + + @Test + public void onActivityResult_EnrollRequestResultFinishShallBeSentBack() { + final int defaultActivityResult = Shadows.shadowOf(mActivity).getResultCode(); + + // Start enrolling + EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback(); + enrollmentCallback.onEnrollmentProgress(123); + enrollmentCallback.onEnrollmentError(FingerprintManager.FINGERPRINT_ERROR_CANCELED, "test"); + + // onStop shall not change default activity result + mActivity.onStop(); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(defaultActivityResult); + + // onActivityResult from Enrolling activity shall be sent back + final int testResult = BiometricEnrollBase.RESULT_FINISHED; + mActivity.onActivityResult(BiometricEnrollBase.ENROLL_REQUEST, testResult, null); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult); + assertThat(mActivity.isFinishing()).isEqualTo(true); + + // onStop shall not change last activity result + mActivity.onStop(); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult); + } + + @Test + public void onActivityResult_EnrollRequestResultSkipShallBeSentBack() { + final int defaultActivityResult = Shadows.shadowOf(mActivity).getResultCode(); + + // Start enrolling + EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback(); + enrollmentCallback.onEnrollmentProgress(123); + enrollmentCallback.onEnrollmentError(FingerprintManager.FINGERPRINT_ERROR_CANCELED, "test"); + + // onStop shall not change default activity result + mActivity.onStop(); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(defaultActivityResult); + + // onActivityResult from Enrolling activity shall be sent back + final int testResult = BiometricEnrollBase.RESULT_SKIP; + mActivity.onActivityResult(BiometricEnrollBase.ENROLL_REQUEST, testResult, null); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult); + assertThat(mActivity.isFinishing()).isEqualTo(true); + + // onStop shall not change last activity result + mActivity.onStop(); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult); + } + + @Test + public void onActivityResult_EnrollRequestResultTimeoutShallBeSentBack() { + final int defaultActivityResult = Shadows.shadowOf(mActivity).getResultCode(); + + // Start enrolling + EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback(); + enrollmentCallback.onEnrollmentProgress(123); + enrollmentCallback.onEnrollmentError(FingerprintManager.FINGERPRINT_ERROR_CANCELED, "test"); + + // onStop shall not change default activity result + mActivity.onStop(); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(defaultActivityResult); + + // onActivityResult from Enrolling activity shall be sent back + final int testResult = BiometricEnrollBase.RESULT_TIMEOUT; + mActivity.onActivityResult(BiometricEnrollBase.ENROLL_REQUEST, testResult, null); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult); + assertThat(mActivity.isFinishing()).isEqualTo(true); + + // onStop shall not change last activity result + mActivity.onStop(); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult); + } } diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java index 6faf8011278..69e5e2f485b 100644 --- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java +++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java @@ -179,11 +179,11 @@ public class FingerprintStatusUtilsTest { } @Test - public void getSettingsClassName_whenNotEnrolled_returnsFingerprintEnrollInduction() { + public void getSettingsClassName_whenNotEnrolled_returnsFingerprintSettings() { when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); assertThat(mFingerprintStatusUtils.getSettingsClassName()) - .isEqualTo(FingerprintEnrollIntroductionInternal.class.getName()); + .isEqualTo(FingerprintSettings.class.getName()); } @Test diff --git a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java index 7ff407db43a..07c1571f987 100644 --- a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java @@ -47,7 +47,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.Settings; import com.android.settings.biometrics.face.FaceEnrollIntroductionInternal; -import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroductionInternal; import com.android.settings.biometrics.fingerprint.FingerprintSettings; import com.android.settings.testutils.ResourcesUtils; @@ -186,7 +185,7 @@ public class BiometricsSafetySourceTest { assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_fingerprint_preference_title", "security_settings_fingerprint_preference_summary_none", - FingerprintEnrollIntroductionInternal.class.getName()); + FingerprintSettings.class.getName()); } @Test