Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 505be79c authored by Milton Wu's avatar Milton Wu
Browse files

Fix FingerprintEnrollIntroFragment buttons

1. Fix FingerprintEnrollIntroFragment button status not sync after
   rotation.
2. Finetune code orders in FingerprintEnrollmentActivity.onCreate(),
3. Refine some API names and java doc

Bug: 260205364
Test: atest AutoCredentialViewModelTest
            FingerprintEnrollIntroViewModelTest
Test: Manually test rotation with different display size
Change-Id: Ib992e10a1c90e3bbac6cf73114df4e96b5ab0a03
parent 0514e9a9
Loading
Loading
Loading
Loading
+33 −18
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModelProvider;

import com.android.settings.R;
@@ -120,15 +121,6 @@ public class FingerprintEnrollIntroFragment extends Fragment {
        footerTitle2.setText(
                R.string.security_settings_fingerprint_enroll_introduction_footer_title_2);

        return mView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        final Context context = view.getContext();

        final TextView footerLink = mView.findViewById(R.id.footer_learn_more);
        footerLink.setMovementMethod(LinkMovementMethod.getInstance());
        final String footerLinkStr = getContext().getString(
@@ -139,18 +131,28 @@ public class FingerprintEnrollIntroFragment extends Fragment {
        // footer buttons
        mPrimaryFooterButton = new FooterButton.Builder(context)
                .setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
                .setListener(mViewModel::onNextButtonClick)
                .setButtonType(FooterButton.ButtonType.OPT_IN)
                .setTheme(R.style.SudGlifButton_Primary)
                .build();
        mSecondaryFooterButton = new FooterButton.Builder(context)
                .setListener(mViewModel::onSkipOrCancelButtonClick)
                .setButtonType(FooterButton.ButtonType.NEXT)
                .setTheme(R.style.SudGlifButton_Primary)
                .build();
        getFooterBarMixin().setPrimaryButton(mPrimaryFooterButton);
        getFooterBarMixin().setSecondaryButton(mSecondaryFooterButton, true /* usePrimaryStyle */);

        return mView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        final Context context = view.getContext();

        mPrimaryFooterButton.setOnClickListener(mViewModel::onNextButtonClick);
        mSecondaryFooterButton.setOnClickListener(mViewModel::onSkipOrCancelButtonClick);

        if (mViewModel.canAssumeUdfps()) {
            mFooterMessage6.setVisibility(View.VISIBLE);
            mIconShield.setVisibility(View.VISIBLE);
@@ -158,7 +160,7 @@ public class FingerprintEnrollIntroFragment extends Fragment {
            mFooterMessage6.setVisibility(View.GONE);
            mIconShield.setVisibility(View.GONE);
        }
        mSecondaryFooterButton.setText(getContext(),
        mSecondaryFooterButton.setText(context,
                mViewModel.getEnrollmentRequest().isAfterSuwOrSuwSuggestedAction()
                ? R.string.security_settings_fingerprint_enroll_introduction_cancel
                : R.string.security_settings_fingerprint_enroll_introduction_no_thanks);
@@ -174,18 +176,31 @@ public class FingerprintEnrollIntroFragment extends Fragment {
            setHeaderText(getActivity(),
                    R.string.security_settings_fingerprint_enroll_introduction_title);
        }
        observePageStatusLiveDataIfNeed();
    }

        mViewModel.getPageStatusLiveData().observe(this, this::updateFooterButtons);
    private void observePageStatusLiveDataIfNeed() {
        final LiveData<FingerprintEnrollIntroStatus> statusLiveData =
                mViewModel.getPageStatusLiveData();
        final FingerprintEnrollIntroStatus status = statusLiveData.getValue();
        if (status != null && status.hasScrollToBottom()) {
            // Do not requireScrollWithButton() again when "I agree" or "Done" button is visible,
            // because if we requireScrollWithButton() again, it will become "More" after scroll-up.
            return;
        }

        final RequireScrollMixin requireScrollMixin = getLayout()
                .getMixin(RequireScrollMixin.class);
        requireScrollMixin.requireScrollWithButton(getActivity(), mPrimaryFooterButton,
                getMoreButtonTextRes(), mViewModel::onNextButtonClick);
        requireScrollMixin.setOnRequireScrollStateChangedListener(scrollNeeded -> {
            if (!scrollNeeded) {
                mViewModel.setHasScrolledToBottom();
            }
        });

        // 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(
                scrollNeeded -> mViewModel.setHasScrolledToBottom(!scrollNeeded));
        statusLiveData.observe(this, this::updateFooterButtons);
    }

    @Override
+19 −18
Original line number Diff line number Diff line
@@ -95,14 +95,9 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
        mViewModel = viewModelProvider.get(FingerprintEnrollmentViewModel.class);
        mViewModel.setRequest(new EnrollmentRequest(getIntent(), getApplicationContext()));
        mViewModel.setSavedInstanceState(savedInstanceState);
        getLifecycle().addObserver(mViewModel);

        mAutoCredentialViewModel = viewModelProvider.get(AutoCredentialViewModel.class);
        mAutoCredentialViewModel.setCredentialModel(savedInstanceState, getIntent());
        mAutoCredentialViewModel.getGenerateChallengeFailLiveData().observe(this,
                this::onGenerateChallengeFail);

        mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult);
        checkCredential();

        // Theme
@@ -113,16 +108,10 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
        // fragment
        setContentView(R.layout.biometric_enrollment_container);

        final FingerprintEnrollIntroViewModel fingerprintEnrollIntroViewModel =
        final FingerprintEnrollIntroViewModel introViewModel =
                viewModelProvider.get(FingerprintEnrollIntroViewModel.class);
        fingerprintEnrollIntroViewModel.setEnrollmentRequest(mViewModel.getRequest());
        fingerprintEnrollIntroViewModel.setUserId(mAutoCredentialViewModel.getUserId());

        // Clear ActionLiveData in FragmentViewModel to prevent getting previous action when
        // recreate
        fingerprintEnrollIntroViewModel.clearActionLiveData();
        fingerprintEnrollIntroViewModel.getActionLiveData().observe(
                this, this::observeIntroAction);
        introViewModel.setEnrollmentRequest(mViewModel.getRequest());
        introViewModel.setUserId(mAutoCredentialViewModel.getUserId());
        if (savedInstanceState == null) {
            final String tag = "FingerprintEnrollIntroFragment";
            getSupportFragmentManager().beginTransaction()
@@ -131,9 +120,21 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
                            tag)
                    .commit();
        }

        // observe LiveData
        getLifecycle().addObserver(mViewModel);
        mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult);

        mAutoCredentialViewModel.getGenerateChallengeFailedLiveData().observe(this,
                this::onGenerateChallengeFailed);

        // Clear ActionLiveData in FragmentViewModel to prevent getting previous action during
        // recreate, like press 'I agree' then press 'back' in FingerprintEnrollFindSensor activity.
        introViewModel.clearActionLiveData();
        introViewModel.getActionLiveData().observe(this, this::observeIntroAction);
    }

    private void onGenerateChallengeFail(@NonNull Boolean isFail) {
    private void onGenerateChallengeFailed(@NonNull Boolean ignoredBoolean) {
        onSetActivityResult(new ActivityResult(RESULT_CANCELED, null));
    }

@@ -148,7 +149,7 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
    private void checkCredential() {
        switch (mAutoCredentialViewModel.checkCredential()) {
            case CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK: {
                final Intent intent = mAutoCredentialViewModel.getChooseLockIntent(this,
                final Intent intent = mAutoCredentialViewModel.createChooseLockIntent(this,
                        mViewModel.getRequest().isSuw(), mViewModel.getRequest().getSuwExtras());
                if (!mViewModel.isWaitingActivityResult().compareAndSet(false, true)) {
                    Log.w(TAG, "chooseLock, fail to set isWaiting flag to true");
@@ -157,7 +158,7 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
                return;
            }
            case CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK: {
                final boolean launched = mAutoCredentialViewModel.getConfirmLockLauncher(
                final boolean launched = mAutoCredentialViewModel.createConfirmLockLauncher(
                        this,
                        LAUNCH_CONFIRM_LOCK_ACTIVITY,
                        getString(R.string.security_settings_fingerprint_preference_title)
@@ -215,7 +216,7 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
                final Intent intent = new Intent(this, isSuw
                        ? SetupFingerprintEnrollFindSensor.class
                        : FingerprintEnrollFindSensor.class);
                intent.putExtras(mAutoCredentialViewModel.getCredentialIntentExtra());
                intent.putExtras(mAutoCredentialViewModel.createCredentialIntentExtra());
                intent.putExtras(mViewModel.getNextActivityBaseIntentExtras());
                mNextActivityLauncher.launch(intent);
            }
+18 −16
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ public class AutoCredentialViewModel extends AndroidViewModel {
    private static final boolean DEBUG = false;

    /**
     * Valid credential, activity doesn't need to do anything.
     * Valid credential, activity does nothing.
     */
    public static final int CREDENTIAL_VALID = 0;

@@ -170,7 +170,7 @@ public class AutoCredentialViewModel extends AndroidViewModel {
    @NonNull private final LockPatternUtils mLockPatternUtils;
    @NonNull private final ChallengeGenerator mChallengeGenerator;
    private CredentialModel mCredentialModel = null;
    @NonNull private final MutableLiveData<Boolean> mGenerateChallengeFailLiveData =
    @NonNull private final MutableLiveData<Boolean> mGenerateChallengeFailedLiveData =
            new MutableLiveData<>();

    public AutoCredentialViewModel(
@@ -186,11 +186,13 @@ public class AutoCredentialViewModel extends AndroidViewModel {
     * Set CredentialModel, the source is coming from savedInstanceState or activity intent
     */
    public void setCredentialModel(@Nullable Bundle savedInstanceState, @NonNull Intent intent) {
        mCredentialModel = new CredentialModel(
                savedInstanceState != null
                        ? savedInstanceState.getBundle(KEY_CREDENTIAL_MODEL)
                        : intent.getExtras(),
                SystemClock.elapsedRealtimeClock());
        final Bundle bundle;
        if (savedInstanceState != null) {
            bundle = savedInstanceState.getBundle(KEY_CREDENTIAL_MODEL);
        } else {
            bundle = intent.getExtras();
        }
        mCredentialModel = new CredentialModel(bundle, SystemClock.elapsedRealtimeClock());

        if (DEBUG) {
            Log.d(TAG, "setCredentialModel " + mCredentialModel + ", savedInstanceState exist:"
@@ -206,8 +208,8 @@ public class AutoCredentialViewModel extends AndroidViewModel {
    }

    @NonNull
    public LiveData<Boolean> getGenerateChallengeFailLiveData() {
        return mGenerateChallengeFailLiveData;
    public LiveData<Boolean> getGenerateChallengeFailedLiveData() {
        return mGenerateChallengeFailedLiveData;
    }

    /**
@@ -238,7 +240,7 @@ public class AutoCredentialViewModel extends AndroidViewModel {
                mCredentialModel.setToken(newToken);
            } catch (IllegalStateException e) {
                Log.e(TAG, "generateChallenge, IllegalStateException", e);
                mGenerateChallengeFailLiveData.postValue(true);
                mGenerateChallengeFailedLiveData.postValue(true);
                return;
            }

@@ -252,7 +254,7 @@ public class AutoCredentialViewModel extends AndroidViewModel {
            // Check credential again
            if (!isValidCredential()) {
                Log.w(TAG, "generateChallenge, invalid Credential");
                mGenerateChallengeFailLiveData.postValue(true);
                mGenerateChallengeFailedLiveData.postValue(true);
            }
        });
        mChallengeGenerator.generateChallenge(getUserId());
@@ -312,7 +314,7 @@ public class AutoCredentialViewModel extends AndroidViewModel {
     * Get Credential intent extra which will be used to launch next activity.
     */
    @NonNull
    public Bundle getCredentialIntentExtra() {
    public Bundle createCredentialIntentExtra() {
        final Bundle retBundle = new Bundle();
        final long gkPwHandle = mCredentialModel.getGkPwHandle();
        if (CredentialModel.isValidGkPwHandle(gkPwHandle)) {
@@ -332,10 +334,10 @@ public class AutoCredentialViewModel extends AndroidViewModel {
    }

    /**
     * Get Intent for choosing lock
     * Create Intent for choosing lock
     */
    @NonNull
    public Intent getChooseLockIntent(@NonNull Context context, boolean isSuw,
    public Intent createChooseLockIntent(@NonNull Context context, boolean isSuw,
            @NonNull Bundle suwExtras) {
        final Intent intent = BiometricUtils.getChooseLockIntent(context, isSuw,
                suwExtras);
@@ -352,10 +354,10 @@ public class AutoCredentialViewModel extends AndroidViewModel {
    }

    /**
     * Get ConfirmLockLauncher
     * Create ConfirmLockLauncher
     */
    @NonNull
    public ChooseLockSettingsHelper getConfirmLockLauncher(@NonNull Activity activity,
    public ChooseLockSettingsHelper createConfirmLockLauncher(@NonNull Activity activity,
            int requestCode, @NonNull String title) {
        final ChooseLockSettingsHelper.Builder builder =
                new ChooseLockSettingsHelper.Builder(activity);
+3 −3
Original line number Diff line number Diff line
@@ -145,7 +145,7 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel
    }

    /**
     * Clear user's action live data (like clicking Agree, Skip, or Done)
     * Clear user's action live data
     */
    public void clearActionLiveData() {
        mActionLiveData.setValue(null);
@@ -168,8 +168,8 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel
    /**
     * Update onboarding intro page has scrolled to bottom
     */
    public void setHasScrolledToBottom() {
        mHasScrolledToBottomLiveData.postValue(true);
    public void setHasScrolledToBottom(boolean value) {
        mHasScrolledToBottomLiveData.postValue(value);
    }

    /**
+72 −82

File changed.

Preview size limit exceeded, changes collapsed.

Loading