From 211313b52d0a278598f205d3d1a6a7bdd3eae7c6 Mon Sep 17 00:00:00 2001 From: Milton Wu Date: Tue, 14 Feb 2023 18:28:45 +0800 Subject: [PATCH] Attach FingerprintEnrollFinishFragment to activity Start FingerprintEnrollFinishFragment when enrolling page is done. Bug: 260960831 Test: atest FingerprintEnrollmentActivityTest FingerprintEnrollmentViewModelTest Change-Id: Ia751c20330dfdcac91e961acc70aa033b05de03f --- .../fingerprint/FingerprintEnrollFinish.java | 2 +- .../repository/PackageManagerRepository.java | 43 ---- .../factory/BiometricsViewModelFactory.java | 14 +- .../view/FingerprintEnrollFinishFragment.java | 89 +++------ .../view/FingerprintEnrollmentActivity.java | 139 ++++++++----- .../FingerprintEnrollFinishViewModel.java | 104 +++++----- .../FingerprintEnrollmentViewModel.java | 108 +++++++---- .../FingerprintEnrollmentViewModelTest.java | 183 +++--------------- 8 files changed, 283 insertions(+), 399 deletions(-) delete mode 100644 src/com/android/settings/biometrics2/data/repository/PackageManagerRepository.java diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java index bbaa3c7b489..a5d198d8d2b 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java @@ -47,7 +47,7 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase { private static final String ACTION_FINGERPRINT_SETTINGS = "android.settings.FINGERPRINT_SETTINGS"; @VisibleForTesting - static final String FINGERPRINT_SUGGESTION_ACTIVITY = + public static final String FINGERPRINT_SUGGESTION_ACTIVITY = "com.android.settings.SetupFingerprintSuggestionActivity"; private FingerprintManager mFingerprintManager; diff --git a/src/com/android/settings/biometrics2/data/repository/PackageManagerRepository.java b/src/com/android/settings/biometrics2/data/repository/PackageManagerRepository.java deleted file mode 100644 index ae00221a138..00000000000 --- a/src/com/android/settings/biometrics2/data/repository/PackageManagerRepository.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2023 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.biometrics2.data.repository; - -import android.annotation.NonNull; -import android.content.ComponentName; -import android.content.pm.PackageManager; - -/** - * This repository is used to call all APIs in {@link PackageManager} - */ -public class PackageManagerRepository { - - private final PackageManager mPackageManager; - - public PackageManagerRepository(PackageManager packageManager) { - mPackageManager = packageManager; - } - - /** - * Set the enabled setting for a package component (activity, receiver, service, provider). - * This setting will override any enabled state which may have been set by the component in its - * manifest. - */ - public void setComponentEnabledSetting(@NonNull ComponentName componentName, - @PackageManager.EnabledState int newState, @PackageManager.EnabledFlags int flags) { - mPackageManager.setComponentEnabledSetting(componentName, newState, flags); - } -} diff --git a/src/com/android/settings/biometrics2/factory/BiometricsViewModelFactory.java b/src/com/android/settings/biometrics2/factory/BiometricsViewModelFactory.java index 19971a78ba5..970ed0279a2 100644 --- a/src/com/android/settings/biometrics2/factory/BiometricsViewModelFactory.java +++ b/src/com/android/settings/biometrics2/factory/BiometricsViewModelFactory.java @@ -17,7 +17,6 @@ package com.android.settings.biometrics2.factory; import android.app.Application; -import android.app.KeyguardManager; import android.util.Log; import androidx.annotation.NonNull; @@ -38,6 +37,7 @@ import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel; import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel; +import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel; @@ -103,8 +103,7 @@ public class BiometricsViewModelFactory implements ViewModelProvider.Factory { final FingerprintRepository repository = provider.getFingerprintRepository(application); final EnrollmentRequest request = extras.get(ENROLLMENT_REQUEST_KEY); if (repository != null && request != null) { - return (T) new FingerprintEnrollmentViewModel(application, repository, - application.getSystemService(KeyguardManager.class), request); + return (T) new FingerprintEnrollmentViewModel(application, repository, request); } } else if (modelClass.isAssignableFrom(FingerprintEnrollProgressViewModel.class)) { final Integer userId = extras.get(USER_ID_KEY); @@ -123,6 +122,15 @@ public class BiometricsViewModelFactory implements ViewModelProvider.Factory { return (T) new FingerprintEnrollEnrollingViewModel(application, userId, fingerprint, accessibility, vibrator); } + } else if (modelClass.isAssignableFrom(FingerprintEnrollFinishViewModel.class)) { + final Integer userId = extras.get(USER_ID_KEY); + final EnrollmentRequest request = extras.get(ENROLLMENT_REQUEST_KEY); + final FingerprintRepository fingerprint = provider.getFingerprintRepository( + application); + if (fingerprint != null && userId != null) { + return (T) new FingerprintEnrollFinishViewModel(application, userId, request, + fingerprint); + } } return create(modelClass); } diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFinishFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFinishFragment.java index 3f98d255405..e0b991aeb4f 100644 --- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFinishFragment.java +++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFinishFragment.java @@ -26,7 +26,6 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.ViewModelProvider; import com.android.settings.R; @@ -36,37 +35,23 @@ import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupdesign.GlifLayout; - /** * Fragment which concludes fingerprint enrollment. */ public class FingerprintEnrollFinishFragment extends Fragment { - private static final String TAG = FingerprintEnrollFinishFragment.class.getSimpleName(); - - private FingerprintEnrollFinishViewModel mFingerprintEnrollFinishViewModel; - private boolean mCanAssumeSfps; - - private View mView; - private FooterBarMixin mFooterBarMixin; + private FingerprintEnrollFinishViewModel mViewModel; private final View.OnClickListener mAddButtonClickListener = - (v) -> mFingerprintEnrollFinishViewModel.onAddButtonClick(); + (v) -> mViewModel.onAddButtonClick(); private final View.OnClickListener mNextButtonClickListener = - (v) -> mFingerprintEnrollFinishViewModel.onNextButtonClick(); + (v) -> mViewModel.onNextButtonClick(); @Override public void onAttach(@NonNull Context context) { super.onAttach(context); - final FragmentActivity activity = getActivity(); - final ViewModelProvider provider = new ViewModelProvider(activity); - mFingerprintEnrollFinishViewModel = provider.get(FingerprintEnrollFinishViewModel.class); - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mCanAssumeSfps = mFingerprintEnrollFinishViewModel.canAssumeSfps(); + final ViewModelProvider provider = new ViewModelProvider(getActivity()); + mViewModel = provider.get(FingerprintEnrollFinishViewModel.class); } @Nullable @@ -74,55 +59,45 @@ public class FingerprintEnrollFinishFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - if (mCanAssumeSfps) { - mView = inflater.inflate(R.layout.sfps_enroll_finish, container, false); - } else { - mView = inflater.inflate(R.layout.fingerprint_enroll_finish, container, false); - } + GlifLayout view = (GlifLayout) inflater.inflate( + mViewModel.canAssumeSfps() + ? R.layout.sfps_enroll_finish + : R.layout.fingerprint_enroll_finish, + container, + false); final Activity activity = getActivity(); - final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity, - (GlifLayout) mView); + final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity, view); glifLayoutHelper.setHeaderText(R.string.security_settings_fingerprint_enroll_finish_title); - glifLayoutHelper.setDescriptionText(getString( - R.string.security_settings_fingerprint_enroll_finish_v2_message)); - - final int maxEnrollments = mFingerprintEnrollFinishViewModel.getMaxFingerprints(); - final int enrolled = mFingerprintEnrollFinishViewModel.getNumOfEnrolledFingerprintsSize(); - if (mCanAssumeSfps) { - if (enrolled < maxEnrollments) { - glifLayoutHelper.setDescriptionText(getString(R.string - .security_settings_fingerprint_enroll_finish_v2_add_fingerprint_message)); - } + if (mViewModel.canAssumeSfps() && mViewModel.isAnotherFingerprintEnrollable()) { + glifLayoutHelper.setDescriptionText(getString(R.string + .security_settings_fingerprint_enroll_finish_v2_add_fingerprint_message)); + } else { + glifLayoutHelper.setDescriptionText(getString( + R.string.security_settings_fingerprint_enroll_finish_v2_message)); } - mFooterBarMixin = ((GlifLayout) mView).getMixin(FooterBarMixin.class); - mFooterBarMixin.setSecondaryButton( - new FooterButton.Builder(getActivity()) - .setText(R.string.fingerprint_enroll_button_add) - .setButtonType(FooterButton.ButtonType.SKIP) - .setTheme(R.style.SudGlifButton_Secondary) - .build() - ); - - mFooterBarMixin.setPrimaryButton( - new FooterButton.Builder(getActivity()) - .setText(R.string.security_settings_fingerprint_enroll_done) + final FooterBarMixin footerBarMixin = view.getMixin(FooterBarMixin.class); + footerBarMixin.setPrimaryButton( + new FooterButton.Builder(activity) + .setText(mViewModel.getRequest().isSuw() + ? R.string.next_label + : R.string.security_settings_fingerprint_enroll_done) .setListener(mNextButtonClickListener) .setButtonType(FooterButton.ButtonType.NEXT) .setTheme(R.style.SudGlifButton_Primary) .build() ); - - FooterButton addButton = mFooterBarMixin.getSecondaryButton(); - if (enrolled >= maxEnrollments) { - addButton.setVisibility(View.INVISIBLE); - } else { - addButton.setOnClickListener(mAddButtonClickListener); + if (mViewModel.isAnotherFingerprintEnrollable()) { + footerBarMixin.setSecondaryButton(new FooterButton.Builder(activity) + .setText(R.string.fingerprint_enroll_button_add) + .setListener(mAddButtonClickListener) + .setButtonType(FooterButton.ButtonType.SKIP) + .setTheme(R.style.SudGlifButton_Secondary) + .build()); } - return mView; + return view; } - } diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java index 74486787baf..eba9bba2628 100644 --- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java +++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java @@ -40,6 +40,9 @@ import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFin import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FingerprintEnrollFindSensorAction; +import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK; +import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK; +import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FingerprintEnrollFinishAction; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_CONTINUE_ENROLL; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_SKIP_OR_CANCEL; @@ -73,8 +76,6 @@ import androidx.lifecycle.viewmodel.MutableCreationExtras; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricEnrollBase; -import com.android.settings.biometrics.fingerprint.FingerprintEnrollFinish; -import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFinish; import com.android.settings.biometrics2.data.repository.FingerprintRepository; import com.android.settings.biometrics2.factory.BiometricsViewModelFactory; import com.android.settings.biometrics2.ui.model.CredentialModel; @@ -84,6 +85,7 @@ import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.Fin import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel; +import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel; import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel; @@ -156,11 +158,14 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { onEnrollingErrorDialogAction(action); } }; - private final ActivityResultCallback mNextActivityResultCallback = - result -> mViewModel.onContinueEnrollActivityResult(result, - mAutoCredentialViewModel.getUserId()); - private final ActivityResultLauncher mNextActivityLauncher = - registerForActivityResult(new StartActivityForResult(), mNextActivityResultCallback); + private final Observer mFinishActionObserver = action -> { + if (DEBUG) { + Log.d(TAG, "mFinishActionObserver(" + action + ")"); + } + if (action != null) { + onFinishAction(action); + } + }; private final ActivityResultCallback mChooseLockResultCallback = result -> onChooseOrConfirmLockResult(true /* isChooseLock */, result); private final ActivityResultLauncher mChooseLockLauncher = @@ -195,6 +200,7 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { } else { final FragmentManager manager = getSupportFragmentManager(); String[] tags = new String[] { + FINISH_TAG, ENROLLING_UDFPS_TAG, ENROLLING_SFPS_TAG, ENROLLING_RFPS_TAG, @@ -217,10 +223,15 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { || tag.equals(FIND_RFPS_TAG)) { attachFindSensorViewModel(); attachIntroViewModel(); - } else { // ENROLLING_UDFPS_TAG, ENROLLING_SFPS_TAG, ENROLLING_RFPS_TAG + } else if (tag.equals(ENROLLING_UDFPS_TAG) || tag.equals(ENROLLING_SFPS_TAG) + || tag.equals(ENROLLING_RFPS_TAG)) { attachEnrollingViewModel(); attachFindSensorViewModel(); attachIntroViewModel(); + } else { // FINISH_TAG + attachFinishViewModel(); + attachFindSensorViewModel(); + attachIntroViewModel(); } break; } @@ -330,59 +341,37 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { mEnrollingErrorDialogActionObserver); } - private void startFinishActivity() { - final FingerprintEnrollEnrollingViewModel enrollingViewModel = - mViewModelProvider.get(FingerprintEnrollEnrollingViewModel.class); - enrollingViewModel.clearActionLiveData(); + private void startFinishFragment() { + attachFinishViewModel(); - final boolean isSuw = mViewModel.getRequest().isSuw(); - if (!mViewModel.isWaitingActivityResult().compareAndSet(false, true)) { - Log.w(TAG, "startNext, isSuw:" + isSuw + ", fail to set isWaiting flag"); - } - Intent intent = new Intent(this, isSuw - ? SetupFingerprintEnrollFinish.class - : FingerprintEnrollFinish.class); - intent.putExtras(mAutoCredentialViewModel.createCredentialIntentExtra()); - intent.putExtras(mViewModel.getNextActivityBaseIntentExtras()); - mNextActivityLauncher.launch(intent); + getSupportFragmentManager().beginTransaction() + .setReorderingAllowed(true) + .setCustomAnimations(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out, + R.anim.sud_slide_back_in, R.anim.sud_slide_back_out) + .replace(R.id.fragment_container_view, FingerprintEnrollFinishFragment.class, null, + FINISH_TAG) + .addToBackStack(FINISH_TAG) + .commit(); + } + + private void attachFinishViewModel() { + final FingerprintEnrollFinishViewModel viewModel = + mViewModelProvider.get(FingerprintEnrollFinishViewModel.class); + viewModel.clearActionLiveData(); + viewModel.getActionLiveData().observe(this, mFinishActionObserver); } private void onGenerateChallengeFailed(@NonNull Boolean ignoredBoolean) { onSetActivityResult(new ActivityResult(RESULT_CANCELED, null)); } - /** - * Get intent which passing back to FingerprintSettings for late generateChallenge() - */ - @Nullable - private Intent createSetResultIntentWithGeneratingChallengeExtra( - @Nullable Intent activityResultIntent) { - if (!mViewModel.getRequest().isFromSettingsSummery()) { - return activityResultIntent; - } - - final Bundle extra = mAutoCredentialViewModel.createGeneratingChallengeExtras(); - if (extra != null) { - if (activityResultIntent == null) { - activityResultIntent = new Intent(); - } - activityResultIntent.putExtras(extra); - } - return activityResultIntent; - } - private void onSetActivityResult(@NonNull ActivityResult result) { - final int resultCode = mViewModel.getRequest().isAfterSuwOrSuwSuggestedAction() - ? RESULT_CANCELED - : result.getResultCode(); - final Intent intent = resultCode == BiometricEnrollBase.RESULT_FINISHED - ? createSetResultIntentWithGeneratingChallengeExtra(result.getData()) - : result.getData(); + final ActivityResult overrideResult = mViewModel.getOverrideActivityResult( + result, mAutoCredentialViewModel.createGeneratingChallengeExtras()); if (DEBUG) { - Log.d(TAG, "onSetActivityResult(" + result + "), call setResult(" + resultCode - + ", " + intent + ")"); + Log.d(TAG, "onSetActivityResult(" + result + "), override:" + overrideResult + ")"); } - setResult(resultCode, intent); + setResult(overrideResult.getResultCode(), overrideResult.getData()); finish(); } @@ -471,7 +460,12 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { private void onEnrollingAction(@FingerprintEnrollEnrollingAction int action) { switch (action) { case FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE: { - startFinishActivity(); + mViewModel.setIsNewFingerprintAdded(); + + // Remove Enrolling page from backstack, and add Finish page. Latest backstack will + // be changed from Intro->FindSensor->Enrolling to Intro->FindSensor->Finish + getSupportFragmentManager().popBackStack(); + startFinishFragment(); break; } case FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP: { @@ -488,7 +482,18 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { break; } case FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED: { - getSupportFragmentManager().popBackStack(); + if (mViewModel.isNewFingerprintAdded()) { + // Add another fingerprint case. Remove Enrolling page from + // backstack, and add Finish page. Latest backstack will be changed from + // Intro->FindSensor->Enrolling to Intro->FindSensor->Finish + getSupportFragmentManager().popBackStack(); + startFinishFragment(); + } else { + // First fingerprint case. Remove Enrolling page from backstack, and add Finish + // page. Latest backstack will be changed from + // Intro->FindSensor->Enrolling to Intro->FindSensor + getSupportFragmentManager().popBackStack(); + } break; } } @@ -505,12 +510,40 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { } } + private void onFinishAction(@FingerprintEnrollFinishAction int action) { + switch (action) { + case FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK: { + getSupportFragmentManager().popBackStack(); // Remove Finish page from backstack + startEnrollingFragment(); + break; + } + case FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK: { + final Intent data; + if (mViewModel.getRequest().isSuw()) { + data = new Intent(); + data.putExtras(mViewModel.getSuwFingerprintCountExtra( + mAutoCredentialViewModel.getUserId())); + } else { + data = null; + } + onSetActivityResult(new ActivityResult(BiometricEnrollBase.RESULT_FINISHED, data)); + break; + } + } + } + @Override protected void onPause() { super.onPause(); mViewModel.checkFinishActivityDuringOnPause(isFinishing(), isChangingConfigurations()); } + @Override + protected void onDestroy() { + mViewModel.updateFingerprintSuggestionEnableState(mAutoCredentialViewModel.getUserId()); + super.onDestroy(); + } + @Override protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid, boolean first) { theme.applyStyle(R.style.SetupWizardPartnerResource, true); diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModel.java index 2cf0b4780cd..ae67f74477e 100644 --- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModel.java +++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModel.java @@ -16,17 +16,20 @@ package com.android.settings.biometrics2.ui.viewmodel; - +import android.annotation.IntDef; import android.app.Application; -import android.content.ComponentName; -import android.content.pm.PackageManager; +import android.util.Log; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import com.android.settings.biometrics2.data.repository.FingerprintRepository; -import com.android.settings.biometrics2.data.repository.PackageManagerRepository; +import com.android.settings.biometrics2.ui.model.EnrollmentRequest; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Finish ViewModel handles the state of the fingerprint renroll final stage @@ -34,29 +37,43 @@ import com.android.settings.biometrics2.data.repository.PackageManagerRepository public class FingerprintEnrollFinishViewModel extends AndroidViewModel { private static final String TAG = FingerprintEnrollFinishViewModel.class.getSimpleName(); + private static final boolean DEBUG = false; - private static final String FINGERPRINT_SUGGESTION_ACTIVITY = - "com.android.settings.SetupFingerprintSuggestionActivity"; + /** + * User clicks "Add" button + */ + public static final int FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK = 0; - private static final int ACTION_NONE = -1; - private static final int ACTION_ADD_BUTTON_CLICK = 0; - private static final int ACTION_NEXT_BUTTON_CLICK = 1; + /** + * User clicks "Next" button + */ + public static final int FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK = 1; - private final FingerprintRepository mFingerprintRepository; - private final PackageManagerRepository mPackageManagerRepository; + @IntDef(prefix = { "FINGERPRINT_ENROLL_FINISH_ACTION_" }, value = { + FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK, + FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK + }) + @Retention(RetentionPolicy.SOURCE) + public @interface FingerprintEnrollFinishAction {} + + @NonNull private final FingerprintRepository mFingerprintRepository; + @NonNull private final EnrollmentRequest mRequest; private final int mUserId; private final MutableLiveData mActionLiveData = new MutableLiveData<>(); - public FingerprintEnrollFinishViewModel(@NonNull Application application, - FingerprintRepository fingerprintRepository, - PackageManagerRepository packageManagerRepository, - int userId) { + public FingerprintEnrollFinishViewModel(@NonNull Application application, int userId, + @NonNull EnrollmentRequest request, + @NonNull FingerprintRepository fingerprintRepository) { super(application); - mFingerprintRepository = fingerprintRepository; - mPackageManagerRepository = packageManagerRepository; mUserId = userId; - mActionLiveData.setValue(ACTION_NONE); + mRequest = request; + mFingerprintRepository = fingerprintRepository; + } + + @NonNull + public EnrollmentRequest getRequest() { + return mRequest; } /** @@ -67,57 +84,46 @@ public class FingerprintEnrollFinishViewModel extends AndroidViewModel { } /** - * Get number of fingerprints that this user enrolled. + * Device allows user to enroll another fingerprint or not. */ - public int getNumOfEnrolledFingerprintsSize() { - return mFingerprintRepository.getNumOfEnrolledFingerprintsSize(mUserId); + public boolean isAnotherFingerprintEnrollable() { + return mFingerprintRepository.getNumOfEnrolledFingerprintsSize(mUserId) + < mFingerprintRepository.getMaxFingerprints(); } /** - * Get max possible number of fingerprints for a user + * Clear action LiveData */ - public int getMaxFingerprints() { - return mFingerprintRepository.getMaxFingerprints(); + public void clearActionLiveData() { + mActionLiveData.setValue(null); } /** - * Clear life data + * Get action LiveData */ - public void clearLiveData() { - mActionLiveData.setValue(ACTION_NONE); + public LiveData getActionLiveData() { + return mActionLiveData; } /** * Handle add button Click */ public void onAddButtonClick() { - mActionLiveData.postValue(ACTION_ADD_BUTTON_CLICK); + final int action = FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK; + if (DEBUG) { + Log.d(TAG, "onAddButtonClick post(" + action + ")"); + } + mActionLiveData.postValue(action); } /** * Handle next button Click */ public void onNextButtonClick() { - updateFingerprintSuggestionEnableState(); - mActionLiveData.postValue(ACTION_NEXT_BUTTON_CLICK); - } - - /** - * Handle back key pressed - */ - public void onBackKeyPressed() { - updateFingerprintSuggestionEnableState(); - } - - private void updateFingerprintSuggestionEnableState() { - final int enrollNum = mFingerprintRepository.getNumOfEnrolledFingerprintsSize(mUserId); - final int flag = (enrollNum == 1) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED - : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; - - ComponentName componentName = new ComponentName(getApplication(), - FINGERPRINT_SUGGESTION_ACTIVITY); - - mPackageManagerRepository.setComponentEnabledSetting(componentName, flag, - PackageManager.DONT_KILL_APP); + final int action = FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK; + if (DEBUG) { + Log.d(TAG, "onNextButtonClick post(" + action + ")"); + } + mActionLiveData.postValue(action); } } diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModel.java index 110ca278a9d..4f07ae6bacd 100644 --- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModel.java +++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModel.java @@ -16,15 +16,13 @@ package com.android.settings.biometrics2.ui.viewmodel; -import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY; -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.FingerprintEnrollFinish.FINGERPRINT_SUGGESTION_ACTIVITY; import static com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollIntroduction.EXTRA_FINGERPRINT_ENROLLED_COUNT; import android.app.Application; -import android.app.KeyguardManager; +import android.content.ComponentName; import android.content.Intent; +import android.content.pm.PackageManager; import android.os.Bundle; import android.util.Log; @@ -39,7 +37,6 @@ import androidx.lifecycle.MutableLiveData; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics2.data.repository.FingerprintRepository; import com.android.settings.biometrics2.ui.model.EnrollmentRequest; -import com.android.settings.password.SetupSkipDialog; import java.util.concurrent.atomic.AtomicBoolean; @@ -53,21 +50,22 @@ public class FingerprintEnrollmentViewModel extends AndroidViewModel { @VisibleForTesting static final String SAVED_STATE_IS_WAITING_ACTIVITY_RESULT = "is_waiting_activity_result"; + @VisibleForTesting + static final String SAVED_STATE_IS_NEW_FINGERPRINT_ADDED = "is_new_fingerprint_added"; + @NonNull private final FingerprintRepository mFingerprintRepository; - @Nullable private final KeyguardManager mKeyguardManager; private final AtomicBoolean mIsWaitingActivityResult = new AtomicBoolean(false); private final MutableLiveData mSetResultLiveData = new MutableLiveData<>(); @NonNull private final EnrollmentRequest mRequest; + private boolean mIsNewFingerprintAdded = false; public FingerprintEnrollmentViewModel( @NonNull Application application, @NonNull FingerprintRepository fingerprintRepository, - @Nullable KeyguardManager keyguardManager, @NonNull EnrollmentRequest request) { super(application); mFingerprintRepository = fingerprintRepository; - mKeyguardManager = keyguardManager; mRequest = request; } @@ -80,41 +78,31 @@ public class FingerprintEnrollmentViewModel extends AndroidViewModel { } /** - * Copy necessary extra data from activity intent + * Get override activity result as current ViewModel status. + * + * FingerprintEnrollmentActivity supports user enrolls 2nd fingerprint or starts a new flow + * through Deferred-SUW, Portal-SUW, or SUW Suggestion. Use a method to get override activity + * result instead of putting these if-else on every setResult(), . */ @NonNull - public Bundle getNextActivityBaseIntentExtras() { - final Bundle bundle = mRequest.getSuwExtras(); - bundle.putBoolean(EXTRA_FROM_SETTINGS_SUMMARY, mRequest.isFromSettingsSummery()); - return bundle; - } + public ActivityResult getOverrideActivityResult(@NonNull ActivityResult result, + @Nullable Bundle generatingChallengeExtras) { + // TODO write tests + final int newResultCode = mIsNewFingerprintAdded + ? BiometricEnrollBase.RESULT_FINISHED + : (mRequest.isAfterSuwOrSuwSuggestedAction() + ? BiometricEnrollBase.RESULT_CANCELED + : result.getResultCode()); - /** - * Handle activity result from FingerprintFindSensor - */ - public void onContinueEnrollActivityResult(@NonNull ActivityResult result, int userId) { - if (!mIsWaitingActivityResult.compareAndSet(true, false)) { - Log.w(TAG, "fail to reset isWaiting flag for enrollment"); - } - if (result.getResultCode() == RESULT_FINISHED - || result.getResultCode() == RESULT_TIMEOUT) { - Intent data = result.getData(); - if (mRequest.isSuw() && isKeyguardSecure() - && result.getResultCode() == RESULT_FINISHED) { - if (data == null) { - data = new Intent(); - } - data.putExtras(getSuwFingerprintCountExtra(userId)); + Intent newData = result.getData(); + if (newResultCode == BiometricEnrollBase.RESULT_FINISHED + && generatingChallengeExtras != null) { + if (newData == null) { + newData = new Intent(); } - mSetResultLiveData.postValue(new ActivityResult(result.getResultCode(), data)); - } else if (result.getResultCode() == RESULT_SKIP - || result.getResultCode() == SetupSkipDialog.RESULT_SKIP) { - mSetResultLiveData.postValue(result); + newData.putExtras(generatingChallengeExtras); } - } - - private boolean isKeyguardSecure() { - return mKeyguardManager != null && mKeyguardManager.isKeyguardSecure(); + return new ActivityResult(newResultCode, newData); } /** @@ -130,11 +118,15 @@ public class FingerprintEnrollmentViewModel extends AndroidViewModel { return; } - mSetResultLiveData.postValue(new ActivityResult(BiometricEnrollBase.RESULT_TIMEOUT, null)); + mSetResultLiveData.postValue( + new ActivityResult(BiometricEnrollBase.RESULT_TIMEOUT, null)); } + /** + * Get Suw fingerprint count extra for statistics + */ @NonNull - private Bundle getSuwFingerprintCountExtra(int userId) { + public Bundle getSuwFingerprintCountExtra(int userId) { final Bundle bundle = new Bundle(); bundle.putInt(EXTRA_FINGERPRINT_ENROLLED_COUNT, mFingerprintRepository.getNumOfEnrolledFingerprintsSize(userId)); @@ -161,6 +153,8 @@ public class FingerprintEnrollmentViewModel extends AndroidViewModel { mIsWaitingActivityResult.set( savedInstanceState.getBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT, false) ); + mIsNewFingerprintAdded = savedInstanceState.getBoolean( + SAVED_STATE_IS_NEW_FINGERPRINT_ADDED, false); } /** @@ -168,6 +162,7 @@ public class FingerprintEnrollmentViewModel extends AndroidViewModel { */ public void onSaveInstanceState(@NonNull Bundle outState) { outState.putBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT, mIsWaitingActivityResult.get()); + outState.putBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED, mIsNewFingerprintAdded); } /** @@ -183,4 +178,35 @@ public class FingerprintEnrollmentViewModel extends AndroidViewModel { public boolean canAssumeSfps() { return mFingerprintRepository.canAssumeSfps(); } + + public boolean isNewFingerprintAdded() { + return mIsNewFingerprintAdded; + } + + /** + * Sets mIsNewFingerprintAdded to true + */ + public void setIsNewFingerprintAdded() { + mIsNewFingerprintAdded = true; + } + + /** + * Update FINGERPRINT_SUGGESTION_ACTIVITY into package manager + */ + public void updateFingerprintSuggestionEnableState(int userId) { + final int enrolled = mFingerprintRepository.getNumOfEnrolledFingerprintsSize(userId); + + // Only show "Add another fingerprint" if the user already enrolled one. + // "Add fingerprint" will be shown in the main flow if the user hasn't enrolled any + // fingerprints. If the user already added more than one fingerprint, they already know + // to add multiple fingerprints so we don't show the suggestion. + final int flag = (enrolled == 1) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED + : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; + + ComponentName componentName = new ComponentName(getApplication(), + FINGERPRINT_SUGGESTION_ACTIVITY); + getApplication().getPackageManager().setComponentEnabledSetting(componentName, flag, + PackageManager.DONT_KILL_APP); + Log.d(TAG, FINGERPRINT_SUGGESTION_ACTIVITY + " enabled state = " + (enrolled == 1)); + } } diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModelTest.java index 04295318b23..2c3fbf03b11 100644 --- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModelTest.java +++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModelTest.java @@ -16,31 +16,20 @@ package com.android.settings.biometrics2.ui.viewmodel; -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.SetupFingerprintEnrollIntroduction.EXTRA_FINGERPRINT_ENROLLED_COUNT; +import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel.SAVED_STATE_IS_NEW_FINGERPRINT_ADDED; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel.SAVED_STATE_IS_WAITING_ACTIVITY_RESULT; import static com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newAllFalseRequest; -import static com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwRequest; -import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.when; - import android.app.Application; -import android.app.KeyguardManager; -import android.content.Intent; import android.hardware.fingerprint.FingerprintManager; import android.os.Bundle; -import androidx.activity.result.ActivityResult; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.biometrics2.data.repository.FingerprintRepository; -import com.android.settings.password.SetupSkipDialog; import com.android.settings.testutils.InstantTaskExecutorRule; import org.junit.Before; @@ -58,7 +47,6 @@ public class FingerprintEnrollmentViewModelTest { @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule(); @Mock private FingerprintManager mFingerprintManager; - @Mock private KeyguardManager mKeyguardManager; private Application mApplication; private FingerprintRepository mFingerprintRepository; @@ -69,7 +57,7 @@ public class FingerprintEnrollmentViewModelTest { mApplication = ApplicationProvider.getApplicationContext(); mFingerprintRepository = new FingerprintRepository(mFingerprintManager); mViewModel = new FingerprintEnrollmentViewModel(mApplication, mFingerprintRepository, - mKeyguardManager, newAllFalseRequest(mApplication)); + newAllFalseRequest(mApplication)); } @Test @@ -77,165 +65,56 @@ public class FingerprintEnrollmentViewModelTest { assertThat(mViewModel.getRequest()).isNotNull(); } - @Test - public void testGetNextActivityBaseIntentExtras() { - assertThat(mViewModel.getNextActivityBaseIntentExtras()).isNotNull(); - } - - @Test - public void testOnContinueEnrollActivityResult_shouldRelaySkip1Result() { - final ActivityResult result = new ActivityResult(RESULT_SKIP, null); - - // Run onContinueEnrollActivityResult - mViewModel.onContinueEnrollActivityResult(result, 100); - - assertThat(mViewModel.getSetResultLiveData().getValue()).isEqualTo(result); - } - - @Test - public void testOnContinueEnrollActivityResult_shouldRelaySkip2Result() { - final ActivityResult result = new ActivityResult(SetupSkipDialog.RESULT_SKIP, null); - - // Run onContinueEnrollActivityResult - mViewModel.onContinueEnrollActivityResult(result, 100); - - assertThat(mViewModel.getSetResultLiveData().getValue()).isEqualTo(result); - } - - @Test - public void testOnContinueEnrollActivityResult_shouldRelayNullDataTimeoutResult() { - final ActivityResult result = new ActivityResult(RESULT_TIMEOUT, null); - - // Run onContinueEnrollActivityResult - mViewModel.onContinueEnrollActivityResult(result, 100); - final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue(); - - assertThat(setResult).isNotNull(); - assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode()); - assertThat(setResult.getData()).isEqualTo(result.getData()); - } - - @Test - public void testOnContinueEnrollActivityResult_shouldRelayWithDataTimeoutResult() { - final Intent intent = new Intent("testAction"); - intent.putExtra("testKey", "testValue"); - final ActivityResult result = new ActivityResult(RESULT_TIMEOUT, intent); - - // Run onContinueEnrollActivityResult - mViewModel.onContinueEnrollActivityResult(result, 100); - final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue(); - - assertThat(setResult).isNotNull(); - assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode()); - assertThat(setResult.getData()).isEqualTo(intent); - } - - @Test - public void testOnContinueEnrollActivityResult_shouldRelayNullDataFinishResult() { - final ActivityResult result = new ActivityResult(RESULT_FINISHED, null); - - // Run onContinueEnrollActivityResult - mViewModel.onContinueEnrollActivityResult(result, 100); - final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue(); - - assertThat(setResult).isNotNull(); - assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode()); - assertThat(setResult.getData()).isEqualTo(result.getData()); - } - - @Test - public void testOnContinueEnrollActivityResult_shouldRelayWithDataFinishResult() { - final Intent intent = new Intent("testAction"); - intent.putExtra("testKey", "testValue"); - final ActivityResult result = new ActivityResult(RESULT_FINISHED, intent); - - // Run onContinueEnrollActivityResult - mViewModel.onContinueEnrollActivityResult(result, 100); - final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue(); - - assertThat(setResult).isNotNull(); - assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode()); - assertThat(setResult.getData()).isEqualTo(intent); - } - - @Test - public void testOnContinueEnrollActivityResult_shouldRelayNullDataFinishResultAsNewData() { - mViewModel = new FingerprintEnrollmentViewModel(mApplication, mFingerprintRepository, - mKeyguardManager, newIsSuwRequest(mApplication)); - when(mKeyguardManager.isKeyguardSecure()).thenReturn(true); - final int userId = 111; - final int numOfFp = 4; - setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, numOfFp); - final ActivityResult result = new ActivityResult(RESULT_FINISHED, null); - - // Run onContinueEnrollActivityResult - mViewModel.onContinueEnrollActivityResult(result, userId); - final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue(); - - assertThat(setResult).isNotNull(); - assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode()); - assertThat(setResult.getData()).isNotNull(); - assertThat(setResult.getData().getExtras()).isNotNull(); - assertThat(setResult.getData().getExtras().getInt(EXTRA_FINGERPRINT_ENROLLED_COUNT, -1)) - .isEqualTo(numOfFp); - } - - @Test - public void testOnContinueEnrollActivityResult_shouldRelayWithDataFinishResultAsNewData() { - mViewModel = new FingerprintEnrollmentViewModel(mApplication, mFingerprintRepository, - mKeyguardManager, newIsSuwRequest(mApplication)); - when(mKeyguardManager.isKeyguardSecure()).thenReturn(true); - final int userId = 20; - final int numOfFp = 9; - setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, numOfFp); - final String action = "testAction"; - final String key = "testKey"; - final String value = "testValue"; - final Intent intent = new Intent(action); - intent.putExtra(key, value); - final ActivityResult result = new ActivityResult(RESULT_FINISHED, intent); - - // Run onContinueEnrollActivityResult - mViewModel.onContinueEnrollActivityResult(result, userId); - final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue(); - - assertThat(setResult).isNotNull(); - assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode()); - assertThat(setResult.getData()).isNotNull(); - assertThat(setResult.getData().getExtras()).isNotNull(); - assertThat(setResult.getData().getExtras().getInt(EXTRA_FINGERPRINT_ENROLLED_COUNT, -1)) - .isEqualTo(numOfFp); - assertThat(setResult.getData().getExtras().getString(key)).isEqualTo(value); - } - @Test public void testSetSavedInstanceState() { - final Bundle bundle = new Bundle(); - mViewModel.isWaitingActivityResult().set(true); - // setSavedInstanceState() as false + final Bundle bundle = new Bundle(); bundle.putBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT, false); mViewModel.setSavedInstanceState(bundle); assertThat(mViewModel.isWaitingActivityResult().get()).isFalse(); // setSavedInstanceState() as false + bundle.clear(); bundle.putBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT, true); mViewModel.setSavedInstanceState(bundle); assertThat(mViewModel.isWaitingActivityResult().get()).isTrue(); + + // setSavedInstanceState() as false + bundle.clear(); + bundle.putBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED, false); + mViewModel.setSavedInstanceState(bundle); + assertThat(mViewModel.isNewFingerprintAdded()).isFalse(); + + // setSavedInstanceState() as false + bundle.clear(); + bundle.putBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED, true); + mViewModel.setSavedInstanceState(bundle); + assertThat(mViewModel.isNewFingerprintAdded()).isTrue(); } @Test public void testOnSaveInstanceState() { - final Bundle bundle = new Bundle(); - - // setSavedInstanceState() as false + // Test isWaitingActivityResult false mViewModel.isWaitingActivityResult().set(false); + final Bundle bundle = new Bundle(); mViewModel.onSaveInstanceState(bundle); assertThat(bundle.getBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT)).isFalse(); - // setSavedInstanceState() as false + // Test isWaitingActivityResult true mViewModel.isWaitingActivityResult().set(true); + bundle.clear(); mViewModel.onSaveInstanceState(bundle); assertThat(bundle.getBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT)).isTrue(); + + // Test isNewFingerprintAdded default false + bundle.clear(); + mViewModel.onSaveInstanceState(bundle); + assertThat(bundle.getBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED)).isFalse(); + + // Test isNewFingerprintAdded true + mViewModel.setIsNewFingerprintAdded(); + bundle.clear(); + mViewModel.onSaveInstanceState(bundle); + assertThat(bundle.getBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED)).isTrue(); } }