[BiometricsV2] Refine fingerprint ui and flow
1. Fix "No thanks" become 2 lines, and fix the status when new fingerprint enrolled. 2. Fix Finish page shows again after pressing back from a new Finish page 3. Fix FindSensor page shows again after max number of fingerprint has reached. 4. Add missing tests, and remove some bypass-only tests Bug: 279134177 Bug: 279380583 Bug: 279386539 Bug: 279394069 Test: atest FingerprintEnrollIntroViewModelTest FingerprintEnrollFindSensorViewModelTest FingerprintEnrollEnrollingViewModelTest FingerprintEnrollmentViewModelTest FingerprintEnrollmentActivityTest Test: manually test 1, 2, and 3 Change-Id: I3797ceed8e7d6c10a4b4711f8bff8d7f222f0923
This commit is contained in:
@@ -78,4 +78,11 @@ public final class FingerprintEnrollIntroStatus {
|
|||||||
public boolean hasScrollToBottom() {
|
public boolean hasScrollToBottom() {
|
||||||
return mHasScrollToBottom;
|
return mHasScrollToBottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode())
|
||||||
|
+ "{scrollToBottom:" + mHasScrollToBottom
|
||||||
|
+ ", enrollableStatus:" + mEnrollableStatus + "}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -63,6 +63,7 @@ import com.google.android.setupdesign.util.DynamicColorPalette;
|
|||||||
public class FingerprintEnrollIntroFragment extends Fragment {
|
public class FingerprintEnrollIntroFragment extends Fragment {
|
||||||
|
|
||||||
private static final String TAG = "FingerprintEnrollIntroFragment";
|
private static final String TAG = "FingerprintEnrollIntroFragment";
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private FingerprintEnrollIntroViewModel mViewModel = null;
|
private FingerprintEnrollIntroViewModel mViewModel = null;
|
||||||
|
|
||||||
@@ -128,17 +129,6 @@ public class FingerprintEnrollIntroFragment extends Fragment {
|
|||||||
footerLink.setText(Html.fromHtml(footerLinkStr));
|
footerLink.setText(Html.fromHtml(footerLinkStr));
|
||||||
|
|
||||||
// footer buttons
|
// footer buttons
|
||||||
mPrimaryFooterButton = new FooterButton.Builder(context)
|
|
||||||
.setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
|
|
||||||
.setButtonType(FooterButton.ButtonType.OPT_IN)
|
|
||||||
.setTheme(R.style.SudGlifButton_Primary)
|
|
||||||
.build();
|
|
||||||
mSecondaryFooterButton = new FooterButton.Builder(context)
|
|
||||||
.setButtonType(FooterButton.ButtonType.NEXT)
|
|
||||||
.setTheme(R.style.SudGlifButton_Primary)
|
|
||||||
.build();
|
|
||||||
getFooterBarMixin().setPrimaryButton(mPrimaryFooterButton);
|
|
||||||
getFooterBarMixin().setSecondaryButton(mSecondaryFooterButton, true /* usePrimaryStyle */);
|
|
||||||
|
|
||||||
return mView;
|
return mView;
|
||||||
}
|
}
|
||||||
@@ -149,9 +139,6 @@ public class FingerprintEnrollIntroFragment extends Fragment {
|
|||||||
|
|
||||||
final Context context = view.getContext();
|
final Context context = view.getContext();
|
||||||
|
|
||||||
mPrimaryFooterButton.setOnClickListener(mOnNextClickListener);
|
|
||||||
mSecondaryFooterButton.setOnClickListener(mOnSkipOrCancelClickListener);
|
|
||||||
|
|
||||||
if (mViewModel.canAssumeUdfps()) {
|
if (mViewModel.canAssumeUdfps()) {
|
||||||
mFooterMessage6.setVisibility(View.VISIBLE);
|
mFooterMessage6.setVisibility(View.VISIBLE);
|
||||||
mIconShield.setVisibility(View.VISIBLE);
|
mIconShield.setVisibility(View.VISIBLE);
|
||||||
@@ -159,10 +146,6 @@ public class FingerprintEnrollIntroFragment extends Fragment {
|
|||||||
mFooterMessage6.setVisibility(View.GONE);
|
mFooterMessage6.setVisibility(View.GONE);
|
||||||
mIconShield.setVisibility(View.GONE);
|
mIconShield.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
mSecondaryFooterButton.setText(context,
|
|
||||||
mViewModel.getRequest().isAfterSuwOrSuwSuggestedAction()
|
|
||||||
? R.string.security_settings_fingerprint_enroll_introduction_cancel
|
|
||||||
: R.string.security_settings_fingerprint_enroll_introduction_no_thanks);
|
|
||||||
|
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(getActivity(), getLayout());
|
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(getActivity(), getLayout());
|
||||||
if (mViewModel.isBiometricUnlockDisabledByAdmin()
|
if (mViewModel.isBiometricUnlockDisabledByAdmin()
|
||||||
@@ -178,16 +161,64 @@ public class FingerprintEnrollIntroFragment extends Fragment {
|
|||||||
R.string.security_settings_fingerprint_enroll_introduction_v3_message,
|
R.string.security_settings_fingerprint_enroll_introduction_v3_message,
|
||||||
DeviceHelper.getDeviceName(context)));
|
DeviceHelper.getDeviceName(context)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
final Context context = requireContext();
|
||||||
|
final FooterBarMixin footerBarMixin = getFooterBarMixin();
|
||||||
|
initPrimaryFooterButton(context, footerBarMixin);
|
||||||
|
initSecondaryFooterButton(context, footerBarMixin);
|
||||||
observePageStatusLiveDataIfNeed();
|
observePageStatusLiveDataIfNeed();
|
||||||
|
super.onStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPrimaryFooterButton(@NonNull Context context,
|
||||||
|
@NonNull FooterBarMixin footerBarMixin) {
|
||||||
|
if (footerBarMixin.getPrimaryButton() != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPrimaryFooterButton = new FooterButton.Builder(context)
|
||||||
|
.setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
|
||||||
|
.setButtonType(FooterButton.ButtonType.OPT_IN)
|
||||||
|
.setTheme(R.style.SudGlifButton_Primary)
|
||||||
|
.build();
|
||||||
|
mPrimaryFooterButton.setOnClickListener(mOnNextClickListener);
|
||||||
|
footerBarMixin.setPrimaryButton(mPrimaryFooterButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSecondaryFooterButton(@NonNull Context context,
|
||||||
|
@NonNull FooterBarMixin footerBarMixin) {
|
||||||
|
if (footerBarMixin.getSecondaryButton() != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSecondaryFooterButton = new FooterButton.Builder(context)
|
||||||
|
.setText(mViewModel.getRequest().isAfterSuwOrSuwSuggestedAction()
|
||||||
|
? R.string.security_settings_fingerprint_enroll_introduction_cancel
|
||||||
|
: R.string.security_settings_fingerprint_enroll_introduction_no_thanks)
|
||||||
|
.setButtonType(FooterButton.ButtonType.NEXT)
|
||||||
|
.setTheme(R.style.SudGlifButton_Primary)
|
||||||
|
.build();
|
||||||
|
mSecondaryFooterButton.setOnClickListener(mOnSkipOrCancelClickListener);
|
||||||
|
footerBarMixin.setSecondaryButton(mSecondaryFooterButton, true /* usePrimaryStyle */);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void observePageStatusLiveDataIfNeed() {
|
private void observePageStatusLiveDataIfNeed() {
|
||||||
final LiveData<FingerprintEnrollIntroStatus> statusLiveData =
|
final LiveData<FingerprintEnrollIntroStatus> statusLiveData =
|
||||||
mViewModel.getPageStatusLiveData();
|
mViewModel.getPageStatusLiveData();
|
||||||
final FingerprintEnrollIntroStatus status = statusLiveData.getValue();
|
final FingerprintEnrollIntroStatus status = statusLiveData.getValue();
|
||||||
if (status != null && status.hasScrollToBottom()) {
|
if (DEBUG) {
|
||||||
// Do not requireScrollWithButton() again when "I agree" or "Done" button is visible,
|
Log.e(TAG, "observePageStatusLiveDataIfNeed() requireScrollWithButton, status:"
|
||||||
// because if we requireScrollWithButton() again, it will become "More" after scroll-up.
|
+ status);
|
||||||
|
}
|
||||||
|
if (status != null && (status.hasScrollToBottom()
|
||||||
|
|| status.getEnrollableStatus() == FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)) {
|
||||||
|
// Update once and do not requireScrollWithButton() again when page has scrolled to
|
||||||
|
// bottom or User has enrolled at least a fingerprint, because if we
|
||||||
|
// requireScrollWithButton() again, primary button will become "More" after scrolling.
|
||||||
|
updateFooterButtons(status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,10 +227,6 @@ public class FingerprintEnrollIntroFragment extends Fragment {
|
|||||||
requireScrollMixin.requireScrollWithButton(getActivity(), mPrimaryFooterButton,
|
requireScrollMixin.requireScrollWithButton(getActivity(), mPrimaryFooterButton,
|
||||||
getMoreButtonTextRes(), mOnNextClickListener);
|
getMoreButtonTextRes(), mOnNextClickListener);
|
||||||
|
|
||||||
// Always set true to setHasScrolledToBottom() before registering listener through
|
|
||||||
// setOnRequireScrollStateChangedListener(), because listener will not be called if first
|
|
||||||
// scrollNeeded is true
|
|
||||||
mViewModel.setHasScrolledToBottom(true);
|
|
||||||
requireScrollMixin.setOnRequireScrollStateChangedListener(
|
requireScrollMixin.setOnRequireScrollStateChangedListener(
|
||||||
scrollNeeded -> mViewModel.setHasScrolledToBottom(!scrollNeeded));
|
scrollNeeded -> mViewModel.setHasScrolledToBottom(!scrollNeeded));
|
||||||
statusLiveData.observe(this, this::updateFooterButtons);
|
statusLiveData.observe(this, this::updateFooterButtons);
|
||||||
@@ -249,15 +276,19 @@ public class FingerprintEnrollIntroFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateFooterButtons(@NonNull FingerprintEnrollIntroStatus status) {
|
void updateFooterButtons(@NonNull FingerprintEnrollIntroStatus status) {
|
||||||
@StringRes final int scrollToBottomPrimaryResId =
|
if (DEBUG) {
|
||||||
status.getEnrollableStatus() == FINGERPRINT_ENROLLABLE_OK
|
Log.d(TAG, "updateFooterButtons(" + status + ")");
|
||||||
? R.string.security_settings_fingerprint_enroll_introduction_agree
|
}
|
||||||
: R.string.done;
|
|
||||||
|
|
||||||
mPrimaryFooterButton.setText(getContext(),
|
mPrimaryFooterButton.setText(getContext(),
|
||||||
status.hasScrollToBottom() ? scrollToBottomPrimaryResId : getMoreButtonTextRes());
|
status.getEnrollableStatus() == FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
|
||||||
mSecondaryFooterButton.setVisibility(
|
? R.string.done
|
||||||
status.hasScrollToBottom() ? View.VISIBLE : View.INVISIBLE);
|
: status.hasScrollToBottom()
|
||||||
|
? R.string.security_settings_fingerprint_enroll_introduction_agree
|
||||||
|
: getMoreButtonTextRes());
|
||||||
|
mSecondaryFooterButton.setVisibility(status.hasScrollToBottom()
|
||||||
|
&& status.getEnrollableStatus() != FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
|
||||||
|
? View.VISIBLE
|
||||||
|
: View.INVISIBLE);
|
||||||
|
|
||||||
final TextView errorTextView = mView.findViewById(R.id.error_text);
|
final TextView errorTextView = mView.findViewById(R.id.error_text);
|
||||||
switch (status.getEnrollableStatus()) {
|
switch (status.getEnrollableStatus()) {
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package com.android.settings.biometrics2.ui.view;
|
package com.android.settings.biometrics2.ui.view;
|
||||||
|
|
||||||
import static androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
|
import static androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
|
||||||
|
import static androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
|
||||||
import static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY;
|
import static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY;
|
||||||
|
|
||||||
import static com.android.settings.biometrics2.factory.BiometricsViewModelFactory.CHALLENGE_GENERATOR_KEY;
|
import static com.android.settings.biometrics2.factory.BiometricsViewModelFactory.CHALLENGE_GENERATOR_KEY;
|
||||||
@@ -100,12 +101,8 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
private static final String TAG = "FingerprintEnrollmentActivity";
|
private static final String TAG = "FingerprintEnrollmentActivity";
|
||||||
|
|
||||||
private static final String INTRO_TAG = "intro";
|
private static final String INTRO_TAG = "intro";
|
||||||
private static final String FIND_UDFPS_TAG = "find-udfps";
|
private static final String FIND_SENSOR_TAG = "find-sensor";
|
||||||
private static final String FIND_SFPS_TAG = "find-sfps";
|
private static final String ENROLLING_TAG = "enrolling";
|
||||||
private static final String FIND_RFPS_TAG = "find-rfps";
|
|
||||||
private static final String ENROLLING_UDFPS_TAG = "enrolling-udfps";
|
|
||||||
private static final String ENROLLING_SFPS_TAG = "enrolling-sfps";
|
|
||||||
private static final String ENROLLING_RFPS_TAG = "enrolling-rfps";
|
|
||||||
private static final String FINISH_TAG = "finish";
|
private static final String FINISH_TAG = "finish";
|
||||||
private static final String SKIP_SETUP_FIND_FPS_DIALOG_TAG = "skip-setup-dialog";
|
private static final String SKIP_SETUP_FIND_FPS_DIALOG_TAG = "skip-setup-dialog";
|
||||||
private static final String ENROLLING_ERROR_DIALOG_TAG = "enrolling-error-dialog";
|
private static final String ENROLLING_ERROR_DIALOG_TAG = "enrolling-error-dialog";
|
||||||
@@ -213,12 +210,10 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
final String tag = fragment.getTag();
|
final String tag = fragment.getTag();
|
||||||
if (INTRO_TAG.equals(tag)) {
|
if (INTRO_TAG.equals(tag)) {
|
||||||
attachIntroViewModel();
|
attachIntroViewModel();
|
||||||
} else if (FIND_UDFPS_TAG.equals(tag) || FIND_SFPS_TAG.equals(tag)
|
} else if (FIND_SENSOR_TAG.equals(tag)) {
|
||||||
|| FIND_RFPS_TAG.equals(tag)) {
|
|
||||||
attachFindSensorViewModel();
|
attachFindSensorViewModel();
|
||||||
attachIntroViewModel();
|
attachIntroViewModel();
|
||||||
} else if (ENROLLING_UDFPS_TAG.equals(tag) || ENROLLING_SFPS_TAG.equals(tag)
|
} else if (ENROLLING_TAG.equals(tag)) {
|
||||||
|| ENROLLING_RFPS_TAG.equals(tag)) {
|
|
||||||
attachEnrollingViewModel();
|
attachEnrollingViewModel();
|
||||||
attachFindSensorViewModel();
|
attachFindSensorViewModel();
|
||||||
attachIntroViewModel();
|
attachIntroViewModel();
|
||||||
@@ -289,19 +284,15 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
|
|
||||||
attachFindSensorViewModel();
|
attachFindSensorViewModel();
|
||||||
|
|
||||||
final String tag;
|
|
||||||
final Class<? extends Fragment> fragmentClass;
|
final Class<? extends Fragment> fragmentClass;
|
||||||
if (mViewModel.canAssumeUdfps()) {
|
if (mViewModel.canAssumeUdfps()) {
|
||||||
tag = FIND_UDFPS_TAG;
|
|
||||||
fragmentClass = FingerprintEnrollFindUdfpsFragment.class;
|
fragmentClass = FingerprintEnrollFindUdfpsFragment.class;
|
||||||
} else if (mViewModel.canAssumeSfps()) {
|
} else if (mViewModel.canAssumeSfps()) {
|
||||||
tag = FIND_SFPS_TAG;
|
|
||||||
fragmentClass = FingerprintEnrollFindSfpsFragment.class;
|
fragmentClass = FingerprintEnrollFindSfpsFragment.class;
|
||||||
} else {
|
} else {
|
||||||
tag = FIND_RFPS_TAG;
|
|
||||||
fragmentClass = FingerprintEnrollFindRfpsFragment.class;
|
fragmentClass = FingerprintEnrollFindRfpsFragment.class;
|
||||||
}
|
}
|
||||||
startFragment(fragmentClass, tag);
|
startFragment(fragmentClass, FIND_SENSOR_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachFindSensorViewModel() {
|
private void attachFindSensorViewModel() {
|
||||||
@@ -325,19 +316,15 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
|
|
||||||
attachEnrollingViewModel();
|
attachEnrollingViewModel();
|
||||||
|
|
||||||
final String tag;
|
|
||||||
final Class<? extends Fragment> fragmentClass;
|
final Class<? extends Fragment> fragmentClass;
|
||||||
if (mViewModel.canAssumeUdfps()) {
|
if (mViewModel.canAssumeUdfps()) {
|
||||||
tag = ENROLLING_UDFPS_TAG;
|
|
||||||
fragmentClass = FingerprintEnrollEnrollingUdfpsFragment.class;
|
fragmentClass = FingerprintEnrollEnrollingUdfpsFragment.class;
|
||||||
} else if (mViewModel.canAssumeSfps()) {
|
} else if (mViewModel.canAssumeSfps()) {
|
||||||
tag = ENROLLING_SFPS_TAG;
|
|
||||||
fragmentClass = FingerprintEnrollEnrollingSfpsFragment.class;
|
fragmentClass = FingerprintEnrollEnrollingSfpsFragment.class;
|
||||||
} else {
|
} else {
|
||||||
tag = ENROLLING_RFPS_TAG;
|
|
||||||
fragmentClass = FingerprintEnrollEnrollingRfpsFragment.class;
|
fragmentClass = FingerprintEnrollEnrollingRfpsFragment.class;
|
||||||
}
|
}
|
||||||
startFragment(fragmentClass, tag);
|
startFragment(fragmentClass, ENROLLING_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachEnrollingViewModel() {
|
private void attachEnrollingViewModel() {
|
||||||
@@ -354,9 +341,8 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
mViewModel.setIsNewFingerprintAdded();
|
mViewModel.setIsNewFingerprintAdded();
|
||||||
attachFinishViewModel();
|
attachFinishViewModel();
|
||||||
|
|
||||||
getSupportFragmentManager().popBackStack();
|
if (mViewModel.getRequest().isSkipFindSensor()) {
|
||||||
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
|
// Set page to Finish
|
||||||
// Replace enrolling page
|
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
.setReorderingAllowed(true)
|
.setReorderingAllowed(true)
|
||||||
.setCustomAnimations(R.anim.shared_x_axis_activity_open_enter_dynamic_color,
|
.setCustomAnimations(R.anim.shared_x_axis_activity_open_enter_dynamic_color,
|
||||||
@@ -367,8 +353,21 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
null, FINISH_TAG)
|
null, FINISH_TAG)
|
||||||
.commit();
|
.commit();
|
||||||
} else {
|
} else {
|
||||||
// Remove Enrolling page from backstack, and add Finish page. Latest backstack will
|
// Remove Enrolling page
|
||||||
// be changed from Intro->FindSensor->Enrolling to Intro->FindSensor->Finish
|
getSupportFragmentManager().popBackStack();
|
||||||
|
|
||||||
|
// Remove old Finish page if any
|
||||||
|
if (getSupportFragmentManager().findFragmentByTag(FINISH_TAG) != null) {
|
||||||
|
getSupportFragmentManager().popBackStack(FINISH_TAG, POP_BACK_STACK_INCLUSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove FindSensor page if maxEnrolled
|
||||||
|
if (mViewModel.isMaxEnrolledReached(mAutoCredentialViewModel.getUserId())
|
||||||
|
&& getSupportFragmentManager().findFragmentByTag(FIND_SENSOR_TAG) != null) {
|
||||||
|
getSupportFragmentManager().popBackStack(FIND_SENSOR_TAG, POP_BACK_STACK_INCLUSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Finish page
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
.setReorderingAllowed(true)
|
.setReorderingAllowed(true)
|
||||||
.setCustomAnimations(R.anim.shared_x_axis_activity_open_enter_dynamic_color,
|
.setCustomAnimations(R.anim.shared_x_axis_activity_open_enter_dynamic_color,
|
||||||
|
@@ -107,8 +107,6 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel {
|
|||||||
enrollableValue != null ? enrollableValue : ENROLLABLE_STATUS_DEFAULT);
|
enrollableValue != null ? enrollableValue : ENROLLABLE_STATUS_DEFAULT);
|
||||||
mPageStatusLiveData.setValue(status);
|
mPageStatusLiveData.setValue(status);
|
||||||
});
|
});
|
||||||
|
|
||||||
updateEnrollableStatus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,6 +131,7 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel {
|
|||||||
* Get enrollable status and hasScrollToBottom live data
|
* Get enrollable status and hasScrollToBottom live data
|
||||||
*/
|
*/
|
||||||
public LiveData<FingerprintEnrollIntroStatus> getPageStatusLiveData() {
|
public LiveData<FingerprintEnrollIntroStatus> getPageStatusLiveData() {
|
||||||
|
updateEnrollableStatus();
|
||||||
return mPageStatusLiveData;
|
return mPageStatusLiveData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -87,7 +87,6 @@ public class FingerprintEnrollmentViewModel extends AndroidViewModel {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public ActivityResult getOverrideActivityResult(@NonNull ActivityResult result,
|
public ActivityResult getOverrideActivityResult(@NonNull ActivityResult result,
|
||||||
@Nullable Bundle generatingChallengeExtras) {
|
@Nullable Bundle generatingChallengeExtras) {
|
||||||
// TODO write tests
|
|
||||||
final int newResultCode = mIsNewFingerprintAdded
|
final int newResultCode = mIsNewFingerprintAdded
|
||||||
? BiometricEnrollBase.RESULT_FINISHED
|
? BiometricEnrollBase.RESULT_FINISHED
|
||||||
: (mRequest.isAfterSuwOrSuwSuggestedAction()
|
: (mRequest.isAfterSuwOrSuwSuggestedAction()
|
||||||
@@ -165,6 +164,14 @@ public class FingerprintEnrollmentViewModel extends AndroidViewModel {
|
|||||||
outState.putBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED, mIsNewFingerprintAdded);
|
outState.putBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED, mIsNewFingerprintAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the result about fingerprint enrollable
|
||||||
|
*/
|
||||||
|
public boolean isMaxEnrolledReached(int userId) {
|
||||||
|
return mFingerprintRepository.getMaxFingerprints()
|
||||||
|
<= mFingerprintRepository.getNumOfEnrolledFingerprintsSize(userId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first sensor type is UDFPS sensor or not
|
* The first sensor type is UDFPS sensor or not
|
||||||
*/
|
*/
|
||||||
|
@@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics2.ui.viewmodel;
|
package com.android.settings.biometrics2.ui.viewmodel;
|
||||||
|
|
||||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
|
|
||||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
|
|
||||||
|
|
||||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.ErrorDialogData;
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.ErrorDialogData;
|
||||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG;
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG;
|
||||||
@@ -151,26 +149,6 @@ public class FingerprintEnrollEnrollingViewModelTest {
|
|||||||
FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP);
|
FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCanAssumeUdfps_forUdfpsUltrasonicSensor() {
|
|
||||||
mViewModel = new FingerprintEnrollEnrollingViewModel(
|
|
||||||
mApplication,
|
|
||||||
TEST_USER_ID,
|
|
||||||
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_ULTRASONIC, 5)
|
|
||||||
);
|
|
||||||
assertThat(mViewModel.canAssumeUdfps()).isEqualTo(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCanAssumeUdfps_forRearSensor() {
|
|
||||||
mViewModel = new FingerprintEnrollEnrollingViewModel(
|
|
||||||
mApplication,
|
|
||||||
TEST_USER_ID,
|
|
||||||
newFingerprintRepository(mFingerprintManager, TYPE_REAR, 5)
|
|
||||||
);
|
|
||||||
assertThat(mViewModel.canAssumeUdfps()).isEqualTo(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetFirstFingerprintSensorPropertiesInternal() {
|
public void testGetFirstFingerprintSensorPropertiesInternal() {
|
||||||
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
|
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
|
||||||
|
@@ -18,6 +18,7 @@ package com.android.settings.biometrics2.ui.viewmodel;
|
|||||||
|
|
||||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG;
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG;
|
||||||
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_SKIP;
|
||||||
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
@@ -70,6 +71,13 @@ public class FingerprintEnrollFindSensorViewModelTest {
|
|||||||
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP);
|
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClickStartDialogButton() {
|
||||||
|
mViewModel.onStartButtonClick();
|
||||||
|
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
|
||||||
|
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClearActionLiveData() {
|
public void testClearActionLiveData() {
|
||||||
assertThat(mViewModel.getActionLiveData().getValue()).isNull();
|
assertThat(mViewModel.getActionLiveData().getValue()).isNull();
|
||||||
|
@@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics2.ui.viewmodel;
|
package com.android.settings.biometrics2.ui.viewmodel;
|
||||||
|
|
||||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
|
|
||||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
|
|
||||||
|
|
||||||
import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX;
|
import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX;
|
||||||
import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus.FINGERPRINT_ENROLLABLE_OK;
|
import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus.FINGERPRINT_ENROLLABLE_OK;
|
||||||
@@ -100,6 +98,25 @@ public class FingerprintEnrollIntroViewModelTest {
|
|||||||
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_OK);
|
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPageStatusLiveDataRefreshWhenRefetch() {
|
||||||
|
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
|
||||||
|
TYPE_UDFPS_OPTICAL, 1);
|
||||||
|
final FingerprintEnrollIntroViewModel viewModel = newFingerprintEnrollIntroViewModel(
|
||||||
|
repository,
|
||||||
|
newAllFalseRequest(mApplication));
|
||||||
|
FingerprintEnrollIntroStatus status = viewModel.getPageStatusLiveData().getValue();
|
||||||
|
assertThat(status.hasScrollToBottom()).isFalse();
|
||||||
|
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_OK);
|
||||||
|
|
||||||
|
setupFingerprintEnrolledFingerprints(mFingerprintManager, TEST_USER_ID, 1);
|
||||||
|
|
||||||
|
// Refetch PageStatusLiveData
|
||||||
|
status = viewModel.getPageStatusLiveData().getValue();
|
||||||
|
assertThat(status.hasScrollToBottom()).isFalse();
|
||||||
|
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClearActionLiveData() {
|
public void testClearActionLiveData() {
|
||||||
final FingerprintEnrollIntroViewModel viewModel = newFingerprintEnrollIntroViewModel(
|
final FingerprintEnrollIntroViewModel viewModel = newFingerprintEnrollIntroViewModel(
|
||||||
@@ -210,24 +227,6 @@ public class FingerprintEnrollIntroViewModelTest {
|
|||||||
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX);
|
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCanAssumeUdfps_forUdfpsUltrasonicSensor() {
|
|
||||||
final FingerprintEnrollIntroViewModel viewModel = newFingerprintEnrollIntroViewModel(
|
|
||||||
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_ULTRASONIC, 5),
|
|
||||||
newAllFalseRequest(mApplication));
|
|
||||||
|
|
||||||
assertThat(viewModel.canAssumeUdfps()).isEqualTo(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCanAssumeUdfps_forRearSensor() {
|
|
||||||
final FingerprintEnrollIntroViewModel viewModel = newFingerprintEnrollIntroViewModel(
|
|
||||||
newFingerprintRepository(mFingerprintManager, TYPE_REAR, 5),
|
|
||||||
newAllFalseRequest(mApplication));
|
|
||||||
|
|
||||||
assertThat(viewModel.canAssumeUdfps()).isEqualTo(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsParentalConsentRequired() {
|
public void testIsParentalConsentRequired() {
|
||||||
// We shall not mock FingerprintRepository, but
|
// We shall not mock FingerprintRepository, but
|
||||||
|
@@ -16,16 +16,22 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics2.ui.viewmodel;
|
package com.android.settings.biometrics2.ui.viewmodel;
|
||||||
|
|
||||||
|
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||||
|
|
||||||
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_NEW_FINGERPRINT_ADDED;
|
||||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel.SAVED_STATE_IS_WAITING_ACTIVITY_RESULT;
|
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.newAllFalseRequest;
|
||||||
|
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
|
||||||
|
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.content.Intent;
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.activity.result.ActivityResult;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -55,7 +61,8 @@ public class FingerprintEnrollmentViewModelTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mApplication = ApplicationProvider.getApplicationContext();
|
mApplication = ApplicationProvider.getApplicationContext();
|
||||||
mFingerprintRepository = new FingerprintRepository(mFingerprintManager);
|
mFingerprintRepository = newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL,
|
||||||
|
5);
|
||||||
mViewModel = new FingerprintEnrollmentViewModel(mApplication, mFingerprintRepository,
|
mViewModel = new FingerprintEnrollmentViewModel(mApplication, mFingerprintRepository,
|
||||||
newAllFalseRequest(mApplication));
|
newAllFalseRequest(mApplication));
|
||||||
}
|
}
|
||||||
@@ -124,4 +131,130 @@ public class FingerprintEnrollmentViewModelTest {
|
|||||||
mViewModel.onSaveInstanceState(bundle);
|
mViewModel.onSaveInstanceState(bundle);
|
||||||
assertThat(bundle.getBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED)).isTrue();
|
assertThat(bundle.getBoolean(SAVED_STATE_IS_NEW_FINGERPRINT_ADDED)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideActivityResult_shallKeepNullIntent_woChallengeExtra() {
|
||||||
|
final ActivityResult retResult = mViewModel.getOverrideActivityResult(
|
||||||
|
new ActivityResult(22, null), null);
|
||||||
|
|
||||||
|
assertThat(retResult).isNotNull();
|
||||||
|
assertThat(retResult.getData()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideActivityResult_shallKeepNullIntent_noIntent_woChallengeExtra() {
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
|
||||||
|
final ActivityResult retResult = mViewModel.getOverrideActivityResult(
|
||||||
|
new ActivityResult(33, intent), null);
|
||||||
|
|
||||||
|
assertThat(retResult).isNotNull();
|
||||||
|
assertThat(retResult.getData()).isEqualTo(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideActivityResult_shallKeepNull_woAdded_woIntent_withChallenge() {
|
||||||
|
final Bundle extra = new Bundle();
|
||||||
|
extra.putString("test1", "test123");
|
||||||
|
|
||||||
|
final ActivityResult retResult = mViewModel.getOverrideActivityResult(
|
||||||
|
new ActivityResult(33, null), extra);
|
||||||
|
|
||||||
|
assertThat(retResult).isNotNull();
|
||||||
|
assertThat(retResult.getData()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideActivityResult_shallCreateNew_woIntent_withChallenge() {
|
||||||
|
final String key1 = "test1";
|
||||||
|
final String key2 = "test2";
|
||||||
|
final Bundle extra = new Bundle();
|
||||||
|
extra.putString(key1, "test123");
|
||||||
|
extra.putInt(key2, 9999);
|
||||||
|
|
||||||
|
mViewModel.setIsNewFingerprintAdded();
|
||||||
|
final ActivityResult retResult = mViewModel.getOverrideActivityResult(
|
||||||
|
new ActivityResult(33, null), extra);
|
||||||
|
|
||||||
|
assertThat(retResult).isNotNull();
|
||||||
|
final Intent retIntent = retResult.getData();
|
||||||
|
assertThat(retIntent).isNotNull();
|
||||||
|
final Bundle retExtra = retIntent.getExtras();
|
||||||
|
assertThat(retExtra).isNotNull();
|
||||||
|
assertThat(retExtra.getSize()).isEqualTo(extra.getSize());
|
||||||
|
assertThat(retExtra.getString(key1)).isEqualTo(extra.getString(key1));
|
||||||
|
assertThat(retExtra.getInt(key2)).isEqualTo(extra.getInt(key2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideActivityResult_shallNotMerge_nonAdded_woIntent_withChallenge() {
|
||||||
|
final Bundle extra = new Bundle();
|
||||||
|
extra.putString("test2", "test123");
|
||||||
|
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
final String key2 = "test2";
|
||||||
|
intent.putExtra(key2, 3456L);
|
||||||
|
|
||||||
|
final ActivityResult retResult = mViewModel.getOverrideActivityResult(
|
||||||
|
new ActivityResult(33, intent), extra);
|
||||||
|
|
||||||
|
assertThat(retResult).isNotNull();
|
||||||
|
final Intent retIntent = retResult.getData();
|
||||||
|
assertThat(retIntent).isNotNull();
|
||||||
|
final Bundle retExtra = retIntent.getExtras();
|
||||||
|
assertThat(retExtra).isNotNull();
|
||||||
|
assertThat(retExtra.getSize()).isEqualTo(intent.getExtras().getSize());
|
||||||
|
assertThat(retExtra.getString(key2)).isEqualTo(intent.getExtras().getString(key2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideActivityResult_shallMerge_added_woIntent_withChallenge() {
|
||||||
|
final String key1 = "test1";
|
||||||
|
final String key2 = "test2";
|
||||||
|
final Bundle extra = new Bundle();
|
||||||
|
extra.putString(key1, "test123");
|
||||||
|
extra.putInt(key2, 9999);
|
||||||
|
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
final String key3 = "test3";
|
||||||
|
intent.putExtra(key3, 3456L);
|
||||||
|
|
||||||
|
mViewModel.setIsNewFingerprintAdded();
|
||||||
|
final ActivityResult retResult = mViewModel.getOverrideActivityResult(
|
||||||
|
new ActivityResult(33, intent), extra);
|
||||||
|
|
||||||
|
assertThat(retResult).isNotNull();
|
||||||
|
final Intent retIntent = retResult.getData();
|
||||||
|
assertThat(retIntent).isNotNull();
|
||||||
|
final Bundle retExtra = retIntent.getExtras();
|
||||||
|
assertThat(retExtra).isNotNull();
|
||||||
|
assertThat(retExtra.getSize()).isEqualTo(extra.getSize() + intent.getExtras().getSize());
|
||||||
|
assertThat(retExtra.getString(key1)).isEqualTo(extra.getString(key1));
|
||||||
|
assertThat(retExtra.getInt(key2)).isEqualTo(extra.getInt(key2));
|
||||||
|
assertThat(retExtra.getLong(key3)).isEqualTo(intent.getExtras().getLong(key3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsMaxEnrolledReached() {
|
||||||
|
final int uid = 100;
|
||||||
|
mFingerprintRepository = newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL,
|
||||||
|
3);
|
||||||
|
mViewModel = new FingerprintEnrollmentViewModel(mApplication, mFingerprintRepository,
|
||||||
|
newAllFalseRequest(mApplication));
|
||||||
|
|
||||||
|
setupFingerprintEnrolledFingerprints(mFingerprintManager, uid, 0);
|
||||||
|
assertThat(mViewModel.isMaxEnrolledReached(uid)).isFalse();
|
||||||
|
|
||||||
|
setupFingerprintEnrolledFingerprints(mFingerprintManager, uid, 1);
|
||||||
|
assertThat(mViewModel.isMaxEnrolledReached(uid)).isFalse();
|
||||||
|
|
||||||
|
setupFingerprintEnrolledFingerprints(mFingerprintManager, uid, 2);
|
||||||
|
assertThat(mViewModel.isMaxEnrolledReached(uid)).isFalse();
|
||||||
|
|
||||||
|
setupFingerprintEnrolledFingerprints(mFingerprintManager, uid, 3);
|
||||||
|
assertThat(mViewModel.isMaxEnrolledReached(uid)).isTrue();
|
||||||
|
|
||||||
|
setupFingerprintEnrolledFingerprints(mFingerprintManager, uid, 4);
|
||||||
|
assertThat(mViewModel.isMaxEnrolledReached(uid)).isTrue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user