From af5a7d8dc0c1983751816c694fd91ec9c811ef71 Mon Sep 17 00:00:00 2001 From: Milton Wu Date: Fri, 26 Aug 2022 09:57:40 +0000 Subject: [PATCH] Bypass cancel error code during "Add another" 1. When user chooses "Add another" on latest fingerprint enroll page, we shall bypass RESULT_CANCELED from FingerprintEnrollEnrolling. This is because user has successfully enrolled a fingerprint before enter FingerprintEnrollFinish page. 2. In FingerprintEnrollFindSensor A. Do not call startLookingForFingerprint() if mNextClick is true because it is wating the result back from FingerprintEnrollEnrolling, and let onActivityResult() mehtod to handle correct behavior. B. Add tests for following cases a. Sidecar existence b. Activity recycled and recreate in order to get activity result. Bug: 243701933 Bug: 243762418 Test: ROBOTEST for SetupFingerprintEnrollFindSensorTest, FingerprintEnrollFindSensorTest, SetupFingerprintEnrollFinishTest Test: Test scenarios w/ and w/o always_finish_activities 1. Enroll a fingerprint but cancel it during enrolling in SuW 2. Enroll a fingerprint in SuW 3. Add another fingerprint in SuW 4. Run "Add another" but cancel it during enrolling in SuW 5. W/o enrolled fingerprint, add first fingerprint in settings 6. W/o enrolled fingerprint, add first fingerprint but cancel it during enrolling in settings 7. W/o enrolled fingerprint, add first fingerprint and choose "Add another" in settings 8. W/o enrolled fingerprint, add first fingerprint and choose "Add another" then cancel it during enrolling in settings 9. W/ 1 enrolled fingerprint, add fingerprint in settings 10. W/ 1 enrolled fingerprint, add fingerprint but cancel it during enrolling in settings 11. W/ 1 enrolled fingerprint, add fingerprint and choose "Add another" in settings 12. W/ 1 enrolled fingerprint, add fingerprint and choose "Add another" then canel it during enrolling in settings Change-Id: I03d8d8ebc39eb34f8fc28acb5cd267e37c7a0311 --- .../FingerprintEnrollFindSensor.java | 21 +- .../fingerprint/FingerprintEnrollFinish.java | 23 +- .../FingerprintEnrollFindSensorTest.java | 334 +++++++++++++++--- 3 files changed, 326 insertions(+), 52 deletions(-) diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java index fd589f46dbc..9abf38d3aa1 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java @@ -134,6 +134,9 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title); setDescriptionText(R.string.security_settings_fingerprint_enroll_find_sensor_message); } + if (savedInstanceState != null) { + mNextClicked = savedInstanceState.getBoolean(SAVED_STATE_IS_NEXT_CLICKED, mNextClicked); + } // This is an entry point for SetNewPasswordController, e.g. // adb shell am start -a android.app.action.SET_NEW_PASSWORD @@ -148,11 +151,19 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements // it passed in. getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); - startLookingForFingerprint(); + // Do not start looking for fingerprint if this activity is re-created because it is + // waiting for activity result from enrolling activity. + if (!mNextClicked) { + startLookingForFingerprint(); + } }); } else if (mToken != null) { - // HAT passed in from somewhere else, such as FingerprintEnrollIntroduction - startLookingForFingerprint(); + // Do not start looking for fingerprint if this activity is re-created because it is + // waiting for activity result from enrolling activity. + if (!mNextClicked) { + // HAT passed in from somewhere else, such as FingerprintEnrollIntroduction + startLookingForFingerprint(); + } } else { // There's something wrong with the enrollment flow, this should never happen. throw new IllegalStateException("HAT and GkPwHandle both missing..."); @@ -173,9 +184,6 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements mAnimation = (FingerprintFindSensorAnimation) animationView; } } - if (savedInstanceState != null) { - mNextClicked = savedInstanceState.getBoolean(SAVED_STATE_IS_NEXT_CLICKED, mNextClicked); - } } @Override @@ -297,6 +305,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements return; } } + mSidecar.setListener(null); getSupportFragmentManager().beginTransaction().remove(mSidecar). commitAllowingStateLoss(); mSidecar = null; diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java index b606b607a5a..c24e9f0d5e7 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java @@ -50,6 +50,8 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase { static final String FINGERPRINT_SUGGESTION_ACTIVITY = "com.android.settings.SetupFingerprintSuggestionActivity"; + private boolean mIsAddAnotherOrFinish; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -107,9 +109,23 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase { } } + @Override + protected void onStart() { + super.onStart(); + + // Reset it to false every time activity back to fg because this flag is stateless between + // different life cycle. + mIsAddAnotherOrFinish = false; + } + @Override protected void onNextButtonClick(View view) { updateFingerprintSuggestionEnableState(); + finishAndToNext(); + } + + private void finishAndToNext() { + mIsAddAnotherOrFinish = true; setResult(RESULT_FINISHED); if (WizardManagerHelper.isAnySetupWizard(getIntent())) { postEnroll(); @@ -145,20 +161,21 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase { } private void onAddAnotherButtonClick(View view) { + mIsAddAnotherOrFinish = true; startActivityForResult(getFingerprintEnrollingIntent(), BiometricUtils.REQUEST_ADD_ANOTHER); } @Override protected boolean shouldFinishWhenBackgrounded() { - return !isFinishing() && super.shouldFinishWhenBackgrounded(); + return !mIsAddAnotherOrFinish && super.shouldFinishWhenBackgrounded(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { updateFingerprintSuggestionEnableState(); if (requestCode == BiometricUtils.REQUEST_ADD_ANOTHER && resultCode != RESULT_CANCELED) { - setResult(resultCode, data); - finish(); + // If user cancel during "Add another", just use similar flow on "Next" button + finishAndToNext(); } else { super.onActivityResult(requestCode, resultCode, data); } 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 49a16cbc77b..fad3abf2a3a 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java @@ -19,6 +19,11 @@ package com.android.settings.biometrics.fingerprint; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL; +import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED; +import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_SKIP; +import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT; +import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.TAG_SIDECAR; + import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -29,6 +34,7 @@ import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; import static org.robolectric.RuntimeEnvironment.application; +import android.annotation.NonNull; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; @@ -38,9 +44,12 @@ import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; +import android.os.Bundle; import android.os.CancellationSignal; import android.view.View; +import androidx.fragment.app.Fragment; + import com.android.settings.R; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.password.ChooseLockSettingsHelper; @@ -82,12 +91,7 @@ public class FingerprintEnrollFindSensorTest { private FingerprintEnrollFindSensor mActivity; - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - ShadowUtils.setFingerprintManager(mFingerprintManager); - FakeFeatureFactory.setupForTest(); - + private void buildActivity() { mActivityController = Robolectric.buildActivity( FingerprintEnrollFindSensor.class, new Intent() @@ -97,6 +101,14 @@ public class FingerprintEnrollFindSensorTest { mActivity = mActivityController.get(); } + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + ShadowUtils.setFingerprintManager(mFingerprintManager); + FakeFeatureFactory.setupForTest(); + buildActivity(); + } + private void setupActivity_onRearDevice() { final ArrayList props = new ArrayList<>(); props.add(newFingerprintSensorPropertiesInternal(TYPE_REAR)); @@ -187,7 +199,7 @@ public class FingerprintEnrollFindSensorTest { ShadowActivity shadowActivity = Shadows.shadowOf(mActivity); assertWithMessage("result code").that(shadowActivity.getResultCode()) - .isEqualTo(BiometricEnrollBase.RESULT_SKIP); + .isEqualTo(RESULT_SKIP); } private EnrollmentCallback verifyAndCaptureEnrollmentCallback() { @@ -214,123 +226,320 @@ public class FingerprintEnrollFindSensorTest { } @Test - public void enrollingFinishResultShallSentBack_onRearDevice() { + public void resultFinishShallForward_onRearDevice() { setupActivity_onRearDevice(); triggerEnrollProgressAndError_onRearDevice(); verifyStartEnrollingActivity(); - // onStop shall not change default activity result + // pause activity mActivityController.pause().stop(); + + // onStop shall not change default activity result assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_FINISHED); + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_FINISHED); } @Test - public void enrollingSkipResultShallSentBack_onRearDevice() { + public void resultFinishShallForward_onRearDevice_recreate() { setupActivity_onRearDevice(); triggerEnrollProgressAndError_onRearDevice(); verifyStartEnrollingActivity(); + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + // onStop shall not change default activity result - mActivityController.pause().stop(); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_SKIP); + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_FINISHED, bundle); } @Test - public void enrollingTimeoutResultShallSentBack_onRearDevice() { + public void resultSkipShallForward_onRearDevice() { setupActivity_onRearDevice(); + verifySidecar_onRearOrSfpsDevice(); + triggerEnrollProgressAndError_onRearDevice(); verifyStartEnrollingActivity(); - // onStop shall not change default activity result + // pause activity mActivityController.pause().stop(); + + // onStop shall not change default activity result assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_TIMEOUT); + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_SKIP); } @Test - public void enrollingFinishResultShallSentBack_onUdfpsDevice_triggeredByLottieClick() { + public void resultSkipShallForward_onRearDevice_recreate() { + setupActivity_onRearDevice(); + verifySidecar_onRearOrSfpsDevice(); + + triggerEnrollProgressAndError_onRearDevice(); + verifyStartEnrollingActivity(); + + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_SKIP, bundle); + } + + @Test + public void resultTimeoutShallForward_onRearDevice() { + setupActivity_onRearDevice(); + verifySidecar_onRearOrSfpsDevice(); + + triggerEnrollProgressAndError_onRearDevice(); + verifyStartEnrollingActivity(); + + // pause activity + mActivityController.pause().stop(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_TIMEOUT); + } + + @Test + public void resultTimeoutShallForward_onRearDevice_recreate() { + setupActivity_onRearDevice(); + verifySidecar_onRearOrSfpsDevice(); + + triggerEnrollProgressAndError_onRearDevice(); + verifyStartEnrollingActivity(); + + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_TIMEOUT, bundle); + } + + @Test + public void clickLottieResultFinishShallForward_onUdfpsDevice() { setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + clickLottieView_onUdfpsDevice(); verifyStartEnrollingActivity(); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - // onStop shall not change default activity result + // pause activity mActivityController.pause().stop(); + + // onStop shall not change default activity result assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_FINISHED); + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_FINISHED); } @Test - public void enrollingSkipResultShallSentBack_onUdfpsDevice_triggeredByLottieClick() { + public void clickLottieResultFinishShallForward_onUdfpsDevice_ifActivityRecycled() { setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + clickLottieView_onUdfpsDevice(); verifyStartEnrollingActivity(); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + // onStop shall not change default activity result - mActivityController.pause().stop(); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_SKIP); + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_FINISHED, bundle); } @Test - public void enrollingTimeoutResultShallSentBack_onUdfpsDevice_triggeredByLottieClick() { + public void clickLottieResultSkipShallForward_onUdfpsDevice() { setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + clickLottieView_onUdfpsDevice(); verifyStartEnrollingActivity(); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - // onStop shall not change default activity result + // pause activity mActivityController.pause().stop(); + + // onStop shall not change default activity result assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_TIMEOUT); + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_SKIP); } @Test - public void enrollingFinishResultShallSentBack_onUdfpsDevice_triggeredByPrimaryButtonClick() { + public void clickLottieResultSkipShallForward_onUdfpsDevice_ifActivityRecycled() { setupActivity_onUdfpsDevice(); - clickPrimaryButton_onUdfpsDevice(); - verifyStartEnrollingActivity(); + verifyNoSidecar(); - // onStop shall not change default activity result - mActivityController.pause().stop(); + clickLottieView_onUdfpsDevice(); + verifyStartEnrollingActivity(); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_FINISHED); + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_SKIP, bundle); } @Test - public void enrollingSkipResultShallSentBack_onUdfpsDevice_triggeredByPrimaryButtonClick() { + public void clickLottieResultTimeoutShallForward_onUdfpsDevice() { setupActivity_onUdfpsDevice(); - clickPrimaryButton_onUdfpsDevice(); - verifyStartEnrollingActivity(); + verifyNoSidecar(); - // onStop shall not change default activity result - mActivityController.pause().stop(); + clickLottieView_onUdfpsDevice(); + verifyStartEnrollingActivity(); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_SKIP); + // pause activity + mActivityController.pause().stop(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_TIMEOUT); } @Test - public void enrollingTimeoutResultShallSentBack_onUdfpsDevice_triggeredByPrimaryButtonClick() { + public void clickLottieResultTimeoutShallForward_onUdfpsDevice_ifActivityRecycled() { setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + + clickLottieView_onUdfpsDevice(); + verifyStartEnrollingActivity(); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_TIMEOUT, bundle); + } + + @Test + public void clickPrimiaryButtonResultFinishShallForward_onUdfpsDevice() { + setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + clickPrimaryButton_onUdfpsDevice(); verifyStartEnrollingActivity(); - // onStop shall not change default activity result + // pause activity mActivityController.pause().stop(); + + // onStop shall not change default activity result assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); - gotEnrollingResult_verifyResultSentBack(BiometricEnrollBase.RESULT_TIMEOUT); + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_FINISHED); + } + + @Test + public void clickPrimiaryButtonResultFinishShallForward_onUdfpsDevice_ifActivityRecycled() { + setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + + clickPrimaryButton_onUdfpsDevice(); + verifyStartEnrollingActivity(); + + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_FINISHED, bundle); + } + + @Test + public void clickPrimiaryButtonResultSkipShallForward_onUdfpsDevice() { + setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + + clickPrimaryButton_onUdfpsDevice(); + verifyStartEnrollingActivity(); + + // pause activity + mActivityController.pause().stop(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_SKIP); + } + + @Test + public void clickPrimaryButtonResultSkipShallForward_onUdfpsDevice_ifActivityRecycled() { + setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + + clickPrimaryButton_onUdfpsDevice(); + verifyStartEnrollingActivity(); + + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_SKIP, bundle); + } + + @Test + public void clickPrimaryButtonResultTimeoutShallForward_onUdfpsDevice() { + setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + + clickPrimaryButton_onUdfpsDevice(); + verifyStartEnrollingActivity(); + + // pause activity + mActivityController.pause().stop(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_resumeActivityAndVerifyResultThenForward(RESULT_TIMEOUT); + } + + @Test + public void clickPrimaryButtonResultTimeoutShallForward_onUdfpsDevice_ifActivityRecycled() { + setupActivity_onUdfpsDevice(); + verifyNoSidecar(); + + clickPrimaryButton_onUdfpsDevice(); + verifyStartEnrollingActivity(); + + // recycle activity + final Bundle bundle = new Bundle(); + mActivityController.pause().stop().saveInstanceState(bundle).destroy(); + + // onStop shall not change default activity result + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(DEFAULT_ACTIVITY_RESULT); + + gotEnrollingResult_recreateActivityAndVerifyResultThenForward(RESULT_TIMEOUT, bundle); } private void triggerEnrollProgressAndError_onRearDevice() { @@ -355,9 +564,13 @@ public class FingerprintEnrollFindSensorTest { lottieView.performClick(); } - private void gotEnrollingResult_verifyResultSentBack(int testActivityResult) { - // onActivityResult from Enrolling activity shall be sent back + private void gotEnrollingResult_resumeActivityAndVerifyResultThenForward( + int testActivityResult) { + // resume activity mActivityController.start().resume().visible(); + verifyNoSidecar(); + + // onActivityResult from Enrolling activity shall be forward back Shadows.shadowOf(mActivity).receiveResult( new Intent(mActivity, FingerprintEnrollEnrolling.class), testActivityResult, @@ -366,7 +579,42 @@ public class FingerprintEnrollFindSensorTest { assertThat(mActivity.isFinishing()).isEqualTo(true); // onStop shall not change last activity result - mActivityController.pause().stop(); + mActivityController.pause().stop().destroy(); assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testActivityResult); } + + private void gotEnrollingResult_recreateActivityAndVerifyResultThenForward( + int testActivityResult, @NonNull Bundle savedInstance) { + // Rebuild activity and use savedInstance to restore. + buildActivity(); + mActivityController.setup(savedInstance); + verifyNoSidecar(); + + // onActivityResult from Enrolling activity shall be forward back + Shadows.shadowOf(mActivity).receiveResult( + new Intent(mActivity, FingerprintEnrollEnrolling.class), + testActivityResult, + null); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testActivityResult); + assertThat(mActivity.isFinishing()).isEqualTo(true); + + // onStop shall not change last activity result + mActivityController.pause().stop().destroy(); + assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testActivityResult); + } + + private void verifySidecar_onRearOrSfpsDevice() { + final Fragment sidecar = mActivity.getSupportFragmentManager().findFragmentByTag( + TAG_SIDECAR); + assertThat(sidecar).isNotNull(); + assertThat(sidecar.isAdded()).isTrue(); + } + + private void verifyNoSidecar() { + final Fragment sidecar = mActivity.getSupportFragmentManager().findFragmentByTag( + TAG_SIDECAR); + if (sidecar != null) { + assertThat(sidecar.isAdded()).isFalse(); + } + } }