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

Commit dc8f9673 authored by Milton Wu's avatar Milton Wu Committed by Android (Google) Code Review
Browse files

Merge "Refactor FingerprintEnrollFindSensor"

parents 7bc6dd96 3be7385d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -53,6 +53,14 @@ public class FingerprintRepository {
        return prop != null && prop.isAnyUdfpsType();
    }

    /**
     * The first sensor type is Side fps sensor or not
     */
    public boolean canAssumeSfps() {
        FingerprintSensorPropertiesInternal prop = getFirstFingerprintSensorPropertiesInternal();
        return prop != null && prop.isAnySidefpsType();
    }

    /**
     * Get max possible number of fingerprints for a user
     */
@@ -78,6 +86,7 @@ public class FingerprintRepository {

    @Nullable
    private FingerprintSensorPropertiesInternal getFirstFingerprintSensorPropertiesInternal() {
        // TODO(b/264827022) use API addAuthenticatorsRegisteredCallback
        final List<FingerprintSensorPropertiesInternal> props =
                mFingerprintManager.getSensorPropertiesInternal();
        return props.size() > 0 ? props.get(0) : null;
+10 −1
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@ import com.android.settings.biometrics2.data.repository.FingerprintRepository;
 */
public class BiometricsRepositoryProviderImpl implements BiometricsRepositoryProvider {

    private static volatile FingerprintRepository sFingerprintRepository;

    /**
     * Get FingerprintRepository
     */
@@ -41,6 +43,13 @@ public class BiometricsRepositoryProviderImpl implements BiometricsRepositoryPro
        if (fingerprintManager == null) {
            return null;
        }
        return new FingerprintRepository(fingerprintManager);
        if (sFingerprintRepository == null) {
            synchronized (FingerprintRepository.class) {
                if (sFingerprintRepository == null) {
                    sFingerprintRepository = new FingerprintRepository(fingerprintManager);
                }
            }
        }
        return sFingerprintRepository;
    }
}
+26 −10
Original line number Diff line number Diff line
@@ -27,12 +27,18 @@ import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory;
import androidx.lifecycle.viewmodel.CreationExtras;

import com.android.internal.widget.LockPatternUtils;
import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel;
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator;
import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel;
import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel;
import com.android.settings.overlay.FeatureFactory;
import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;

/**
 * View model factory for biometric enrollment fragment
@@ -42,7 +48,7 @@ public class BiometricsViewModelFactory implements ViewModelProvider.Factory {
    private static final String TAG = "BiometricsViewModelFact";

    public static final CreationExtras.Key<ChallengeGenerator> CHALLENGE_GENERATOR =
            new CreationExtras.Key<ChallengeGenerator>() {};
            new CreationExtras.Key<>() {};

    @NonNull
    @Override
@@ -59,7 +65,22 @@ public class BiometricsViewModelFactory implements ViewModelProvider.Factory {
        final BiometricsRepositoryProvider provider = FeatureFactory.getFactory(application)
                .getBiometricsRepositoryProvider();

        if (modelClass.isAssignableFrom(FingerprintEnrollIntroViewModel.class)) {
        if (modelClass.isAssignableFrom(AutoCredentialViewModel.class)) {
            final LockPatternUtils lockPatternUtils =
                    featureFactory.getSecurityFeatureProvider().getLockPatternUtils(application);
            final ChallengeGenerator challengeGenerator = extras.get(CHALLENGE_GENERATOR);
            if (challengeGenerator != null) {
                return (T) new AutoCredentialViewModel(application, lockPatternUtils,
                        challengeGenerator);
            }
        } else if (modelClass.isAssignableFrom(DeviceFoldedViewModel.class)) {
            return (T) new DeviceFoldedViewModel(new ScreenSizeFoldProvider(application),
                    application.getMainExecutor());
        } else if (modelClass.isAssignableFrom(DeviceRotationViewModel.class)) {
            return (T) new DeviceRotationViewModel(application);
        } else if (modelClass.isAssignableFrom(FingerprintEnrollFindSensorViewModel.class)) {
            return (T) new FingerprintEnrollFindSensorViewModel(application);
        } else if (modelClass.isAssignableFrom(FingerprintEnrollIntroViewModel.class)) {
            final FingerprintRepository repository = provider.getFingerprintRepository(application);
            if (repository != null) {
                return (T) new FingerprintEnrollIntroViewModel(application, repository);
@@ -70,14 +91,9 @@ public class BiometricsViewModelFactory implements ViewModelProvider.Factory {
                return (T) new FingerprintEnrollmentViewModel(application, repository,
                        application.getSystemService(KeyguardManager.class));
            }
        } else if (modelClass.isAssignableFrom(AutoCredentialViewModel.class)) {
            final LockPatternUtils lockPatternUtils =
                    featureFactory.getSecurityFeatureProvider().getLockPatternUtils(application);
            final ChallengeGenerator challengeGenerator = extras.get(CHALLENGE_GENERATOR);
            if (challengeGenerator != null) {
                return (T) new AutoCredentialViewModel(application, lockPatternUtils,
                        challengeGenerator);
            }
        } else if (modelClass.isAssignableFrom(FingerprintEnrollProgressViewModel.class)) {
            return (T) new FingerprintEnrollProgressViewModel(application,
                    new FingerprintUpdater(application));
        }
        return create(modelClass);
    }
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.ui.model;

/**
 * Biometric Enrollment progress
 */
public final class EnrollmentProgress {

    public static final int INITIAL_STEPS = -1;
    public static final int INITIAL_REMAINING = 0;

    private final int mSteps;
    private final int mRemaining;

    public EnrollmentProgress(int steps, int remaining) {
        mSteps = steps;
        mRemaining = remaining;
    }

    public int getSteps() {
        return mSteps;
    }

    public int getRemaining() {
        return mRemaining;
    }

    public boolean isInitialStep() {
        return mSteps == INITIAL_STEPS;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode())
                + "{steps:" + mSteps + ", remaining:" + mRemaining + "}";
    }
}
+209 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.ui.view;

import static android.hardware.fingerprint.FingerprintManager.ENROLL_FIND_SENSOR;
import static android.view.View.OnClickListener;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
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.Observer;
import androidx.lifecycle.ViewModelProvider;

import com.android.settings.R;
import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;

import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;

/**
 * Fragment explaining the side fingerprint sensor location for fingerprint enrollment.
 * It interacts with ProgressViewModel, and FingerprintFindSensorAnimation.
 * <pre>
 | Has                 | UDFPS | SFPS | Other (Rear FPS) |
 |---------------------|-------|------|------------------|
 | Primary button      | Yes   | No   | No               |
 | Illustration Lottie | Yes   | Yes  | No               |
 | Animation           | No    | No   | Depend on layout |
 | Progress ViewModel  | No    | Yes  | Yes              |
 | Orientation detect  | No    | Yes  | No               |
 | Foldable detect     | No    | Yes  | No               |
 </pre>
 */
public class FingerprintEnrollFindRfpsFragment extends Fragment {

    private static final boolean DEBUG = false;
    private static final String TAG = "FingerprintEnrollFindRfpsFragment";

    private FingerprintEnrollFindSensorViewModel mViewModel;
    private FingerprintEnrollProgressViewModel mPorgressViewModel;

    private View mView;
    private GlifLayout mGlifLayout;
    private FooterBarMixin mFooterBarMixin;
    private final OnClickListener mOnSkipClickListener = (v) -> mViewModel.onSkipButtonClick();
    @Nullable private FingerprintFindSensorAnimation mAnimation;

    private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
        if (DEBUG) {
            Log.d(TAG, "mProgressObserver(" + progress + ")");
        }
        if (progress != null && !progress.isInitialStep()) {
            mViewModel.onStartButtonClick();
        }
    };

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        final Context context = inflater.getContext();
        mView = inflater.inflate(R.layout.fingerprint_enroll_find_sensor, container, false);
        mGlifLayout = mView.findViewById(R.id.setup_wizard_layout);
        mFooterBarMixin = mGlifLayout.getMixin(FooterBarMixin.class);
        mFooterBarMixin.setSecondaryButton(
                new FooterButton.Builder(context)
                        .setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
                        .setButtonType(FooterButton.ButtonType.SKIP)
                        .setTheme(R.style.SudGlifButton_Secondary)
                        .build()
        );
        View animationView = mView.findViewById(R.id.fingerprint_sensor_location_animation);
        if (animationView instanceof FingerprintFindSensorAnimation) {
            mAnimation = (FingerprintFindSensorAnimation) animationView;
        }
        return mView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        final Activity activity = getActivity();
        final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity, mGlifLayout);
        glifLayoutHelper.setHeaderText(
                R.string.security_settings_fingerprint_enroll_find_sensor_title);
        glifLayoutHelper.setDescriptionText(
                getText(R.string.security_settings_fingerprint_enroll_find_sensor_message));
        mFooterBarMixin.getSecondaryButton().setOnClickListener(mOnSkipClickListener);
    }

    @Override
    public void onStart() {
        super.onStart();

        if (DEBUG) {
            Log.d(TAG, "onStart(), start looking for fingerprint, animation exist:"
                    + (mAnimation != null));
        }
        startLookingForFingerprint();
    }

    @Override
    public void onResume() {
        if (mAnimation != null) {
            if (DEBUG) {
                Log.d(TAG, "onResume(), start animation");
            }
            mAnimation.startAnimation();
        }
        super.onResume();
    }

    @Override
    public void onPause() {
        if (mAnimation != null) {
            if (DEBUG) {
                Log.d(TAG, "onPause(), pause animation");
            }
            mAnimation.pauseAnimation();
        }
        super.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (DEBUG) {
            Log.d(TAG, "onStop(), stop looking for fingerprint, animation exist:"
                    + (mAnimation != null));
        }
        stopLookingForFingerprint();
    }

    private void startLookingForFingerprint() {
        if (mPorgressViewModel.isEnrolling()) {
            Log.d(TAG, "startLookingForFingerprint(), failed because isEnrolling is true before"
                    + " starting");
            return;
        }

        mPorgressViewModel.clearProgressLiveData();
        mPorgressViewModel.getProgressLiveData().observe(this, mProgressObserver);
        final boolean startResult = mPorgressViewModel.startEnrollment(ENROLL_FIND_SENSOR);
        if (!startResult) {
            Log.e(TAG, "startLookingForFingerprint(), failed to start enrollment");
        }
    }

    private void stopLookingForFingerprint() {
        if (!mPorgressViewModel.isEnrolling()) {
            Log.d(TAG, "stopLookingForFingerprint(), failed because isEnrolling is false before"
                    + " stopping");
            return;
        }

        mPorgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
        final boolean cancelResult = mPorgressViewModel.cancelEnrollment();
        if (!cancelResult) {
            Log.e(TAG, "stopLookingForFingerprint(), failed to cancel enrollment");
        }
    }

    @Override
    public void onDestroy() {
        if (mAnimation != null) {
            if (DEBUG) {
                Log.d(TAG, "onDestroy(), stop animation");
            }
            mAnimation.stopAnimation();
        }
        super.onDestroy();
    }

    @Override
    public void onAttach(@NonNull Context context) {
        final FragmentActivity activity = getActivity();
        final ViewModelProvider provider = new ViewModelProvider(activity);
        mViewModel = provider.get(FingerprintEnrollFindSensorViewModel.class);
        mPorgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
        super.onAttach(context);
    }
}
Loading