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

Commit 98d2e83c authored by Vincent Wang's avatar Vincent Wang Committed by Android (Google) Code Review
Browse files

Merge "Refactor FingerprintEnrollEnrolling to fragment" into udc-dev

parents 02f4727a 7ba30ffc
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -142,7 +142,10 @@ public class UdfpsEnrollHelper extends InstrumentedFragment {
        setRetainInstance(true);
    }

    void onEnrollmentProgress(int totalSteps, int remaining) {
    /**
     * Called when a enroll progress update
     */
    public void onEnrollmentProgress(int totalSteps, int remaining) {
        if (mTotalSteps == -1) {
            mTotalSteps = totalSteps;
        }
@@ -161,25 +164,37 @@ public class UdfpsEnrollHelper extends InstrumentedFragment {
        }
    }

    void onEnrollmentHelp() {
    /**
     * Called when a receive error has been encountered during enrollment.
     */
    public void onEnrollmentHelp() {
        if (mListener != null) {
            mListener.onEnrollmentHelp(mRemainingSteps, mTotalSteps);
        }
    }

    void onAcquired(boolean isAcquiredGood) {
    /**
     * Called when a fingerprint image has been acquired, but wasn't processed yet.
     */
    public void onAcquired(boolean isAcquiredGood) {
        if (mListener != null && mTotalSteps != -1) {
            mListener.onAcquired(isAcquiredGood && animateIfLastStep());
        }
    }

    void onPointerDown(int sensorId) {
    /**
     * Called when pointer down
     */
    public void onPointerDown(int sensorId) {
        if (mListener != null) {
            mListener.onPointerDown(sensorId);
        }
    }

    void onPointerUp(int sensorId) {
    /**
     * Called when pointer up
     */
    public void onPointerUp(int sensorId) {
        if (mListener != null) {
            mListener.onPointerUp(sensorId);
        }
+10 −2
Original line number Diff line number Diff line
@@ -108,7 +108,10 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
        return mOverlayParams;
    }

    void setOverlayParams(UdfpsOverlayParams params) {
    /**
     * Set UdfpsOverlayParams
     */
    public void setOverlayParams(UdfpsOverlayParams params) {
        mOverlayParams = params;

        post(() -> {
@@ -121,7 +124,10 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
        });
    }

    void setEnrollHelper(UdfpsEnrollHelper enrollHelper) {
    /**
     * Set UdfpsEnrollHelper
     */
    public void setEnrollHelper(UdfpsEnrollHelper enrollHelper) {
        mFingerprintDrawable.setEnrollHelper(enrollHelper);
        enrollHelper.setListener(this);
    }
@@ -193,6 +199,8 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
        params.height = rotatedBounds.height() + 2 * getPaddingX();
        params.width = rotatedBounds.width() + 2 * getPaddingY();
        setLayoutParams(params);


    }

    private void onFingerDown() {
+9 −0
Original line number Diff line number Diff line
@@ -65,4 +65,13 @@ public class AccessibilityRepository {
    public void sendAccessibilityEvent(@NonNull AccessibilityEvent event) {
        mAccessibilityManager.sendAccessibilityEvent(event);
    }

    /**
     * Returns if the touch exploration in the system is enabled.
     *
     * @return True if touch exploration is enabled, false otherwise.
     */
    public boolean isTouchExplorationEnabled() {
        return mAccessibilityManager.isTouchExplorationEnabled();
    }
}
+1 −7
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -329,12 +328,7 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
    }

    private void announceEnrollmentProgress(CharSequence announcement) {
        AccessibilityEvent event = new AccessibilityEvent();
        event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
        event.setClassName(getClass().getName());
        event.setPackageName(getClass().getPackageName());
        event.getText().add(announcement);
        mEnrollingViewModel.sendAccessibilityEvent(event);
        mEnrollingViewModel.sendAccessibilityEvent(announcement);
    }

    private void onEnrollmentProgressChange(@NonNull EnrollmentProgress progress) {
+185 −23
Original line number Diff line number Diff line
@@ -22,18 +22,23 @@ import android.annotation.RawRes;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.DisplayInfo;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

@@ -47,15 +52,20 @@ import androidx.transition.TransitionSet;

import com.android.settings.R;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.fingerprint.UdfpsEnrollHelper;
import com.android.settings.biometrics.fingerprint.UdfpsEnrollView;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
import com.android.settingslib.display.DisplayDensityUtils;
import com.android.settingslib.udfps.UdfpsOverlayParams;
import com.android.settingslib.udfps.UdfpsUtils;

import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieCompositionFactory;
import com.google.android.setupcompat.template.FooterActionButton;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;
@@ -70,9 +80,6 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
    private static final String TAG = FingerprintEnrollEnrollingUdfpsFragment.class.getSimpleName();

    private static final int PROGRESS_BAR_MAX = 10000;
    private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
    private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
    private static final int HINT_TIMEOUT_DURATION = 2500;

    private static final int STAGE_UNKNOWN = -1;
    private static final int STAGE_CENTER = 0;
@@ -100,35 +107,52 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
    private GlifLayout mView;
    private TextView mErrorText;
    private FooterBarMixin mFooterBarMixin;
    private AnimatedVectorDrawable mIconAnimationDrawable;
    private AnimatedVectorDrawable mIconBackgroundBlinksDrawable;

    private boolean mShouldShowLottie;
    private boolean mIsAccessibilityEnabled;

    private final View.OnClickListener mOnSkipClickListener =
            (v) -> mEnrollingViewModel.onCancelledDueToOnSkipPressed();
    private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
        // TODO

    private Observer<EnrollmentProgress> mProgressObserver = progress -> {
        if (progress != null) {
            onEnrollmentProgressChange(progress);
        }
    };
    private final Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
        // TODO
    private Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
        if (helpMessage != null) {
            onEnrollmentHelp(helpMessage.getMsgId(), helpMessage.getStr());
        }
    };
    private final Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
    private Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
        // TODO
    };
    private final Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
        // TODO
    private Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
        if (isAcquiredGood != null) {
            onAcquired(isAcquiredGood);
        }
    };
    private final Observer<Integer> mPointerDownObserver = sensorId -> {
        // TODO
        if (sensorId != null) {
            onPointerDown(sensorId);
        }
    };
    private final Observer<Integer> mPointerUpObserver = sensorId -> {
        // TODO
        if (sensorId != null) {
            onPointerUp(sensorId);
        }
    };

    private int mIconTouchCount;

    private UdfpsUtils mUdfpsUtils;
    private float mScaleFactor = 1.0f;
    //TODO UdfpsEnrollHelper should not be a Fragment, we should tell enrollview & progress
    // drawable enough information EnrollView & ProgressDrawable should draw themselves without
    // UdfpsEnrollHelper
    private UdfpsEnrollHelper mUdfpsEnrollHelper;


    @Override
    public void onAttach(@NonNull Context context) {
        final FragmentActivity activity = getActivity();
@@ -176,6 +200,10 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
        super.onCreate(savedInstanceState);
        mEnrollingViewModel.restoreSavedState(savedInstanceState);
        mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
        mUdfpsUtils = new UdfpsUtils();
        mUdfpsEnrollHelper = new UdfpsEnrollHelper(getActivity(), getActivity().getSystemService(
                FingerprintManager.class
        ));
    }

    @Override
@@ -188,13 +216,15 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        mView = initUdfpsLayout(inflater, container);

        return mView;
    }

    private GlifLayout initUdfpsLayout(LayoutInflater inflater, ViewGroup container) {
        final GlifLayout containView = (GlifLayout) inflater.inflate(
                R.layout.udfps_enroll_enrolling, container, false);

        final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(inflater,
                mEnrollingViewModel.getFirstFingerprintSensorPropertiesInternal());
        final int rotation = mRotationViewModel.getLiveData().getValue();
        if (rotation == Surface.ROTATION_90) {
            final boolean isLayoutRtl = (TextUtils.getLayoutDirectionFromLocale(
@@ -207,19 +237,36 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
                    isLayoutRtl ? 0 : (int) getResources().getDimension(
                            R.dimen.rotation_90_enroll_padding_end),
                    0);

            final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT);
            lp.setMarginEnd((int) getResources().getDimension(
                    R.dimen.rotation_90_enroll_margin_end));
            layoutContainer.setLayoutParams(lp);
            containView.addView(udfpsEnrollView);
            containView.setClipChildren(false);
            containView.setClipToPadding(false);
            containView.setLayoutParams(lp);
            setOnHoverListener(true, containView, udfpsEnrollView);
        } else if (rotation == Surface.ROTATION_270) {
            containView.addView(udfpsEnrollView);
            containView.setClipChildren(false);
            containView.setClipToPadding(false);
            setOnHoverListener(true, containView, udfpsEnrollView);
        } else {
            final FrameLayout portraitLayoutContainer = containView.findViewById(
                    R.id.layout_container);
            portraitLayoutContainer.addView(udfpsEnrollView);
            ViewGroup parent = ((ViewGroup) portraitLayoutContainer.getParent());
            parent.setClipChildren(false);
            parent.setClipToPadding(false);
            setOnHoverListener(false, containView, udfpsEnrollView);
        }

        final Activity activity = getActivity();
        new GlifLayoutHelper(activity, containView).setDescriptionText(
                getString(R.string.security_settings_udfps_enroll_start_message));
        updateTitleAndDescription();

        mShouldShowLottie = shouldShowLottie();
        boolean isLandscape = BiometricUtils.isReverseLandscape(activity)
@@ -245,6 +292,19 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
        mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
                activity, android.R.interpolator.fast_out_linear_in);

        final LinearLayout buttonContainer = mFooterBarMixin.getButtonContainer();
        View spaceView = null;
        for (int i = 0; i < buttonContainer.getChildCount(); i++) {
            if (!(buttonContainer.getChildAt(i) instanceof FooterActionButton)) {
                spaceView = buttonContainer.getChildAt(i);
                break;
            }
        }
        if (spaceView != null) {
            spaceView.setVisibility(View.GONE);
            buttonContainer.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
        }

        return containView;
    }

@@ -298,6 +358,9 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {

        final int progress = getProgress(enrollmentProgress);

        mUdfpsEnrollHelper.onEnrollmentProgress(enrollmentProgress.getSteps(),
                enrollmentProgress.getRemaining());

        if (animate) {
            animateProgress(progress);
        } else if (progress >= PROGRESS_BAR_MAX) {
@@ -319,6 +382,38 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
        super.onDestroy();
    }

    private UdfpsEnrollView addUdfpsEnrollView(LayoutInflater inflater,
            FingerprintSensorPropertiesInternal udfpsProps) {

        UdfpsEnrollView enrollView = (UdfpsEnrollView) inflater.inflate(R.layout.udfps_enroll_view,
                null, false);
        DisplayInfo displayInfo = new DisplayInfo();
        getActivity().getDisplay().getDisplayInfo(displayInfo);
        mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo);
        Rect udfpsBounds = udfpsProps.getLocation().getRect();
        udfpsBounds.scale(mScaleFactor);

        final Rect overlayBounds = new Rect(
                0, /* left */
                displayInfo.getNaturalHeight() / 2, /* top */
                displayInfo.getNaturalWidth(), /* right */
                displayInfo.getNaturalHeight() /* botom */);

        UdfpsOverlayParams params = new UdfpsOverlayParams(
                udfpsBounds,
                overlayBounds,
                displayInfo.getNaturalWidth(),
                displayInfo.getNaturalHeight(),
                mScaleFactor,
                displayInfo.rotation);

        enrollView.setOverlayParams(params);

        enrollView.setEnrollHelper(mUdfpsEnrollHelper);

        return enrollView;
    }

    private void animateProgress(int progress) {
        // UDFPS animations are owned by SystemUI
        if (progress >= PROGRESS_BAR_MAX) {
@@ -462,16 +557,10 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
    }

    private void startIconAnimation() {
        if (mIconAnimationDrawable != null) {
            mIconAnimationDrawable.start();
        }
    }

    private void stopIconAnimation() {
        mAnimationCancelled = true;
        if (mIconAnimationDrawable != null) {
            mIconAnimationDrawable.stop();
        }
    }

    private int getCurrentStage() {
@@ -545,6 +634,79 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
                });
    }

    private void setOnHoverListener(boolean isLandscape, GlifLayout enrollLayout,
            UdfpsEnrollView udfpsEnrollView) {
        if (!mIsAccessibilityEnabled) return;

        final Context context = getActivity();
        final View.OnHoverListener onHoverListener = (v, event) -> {
            // Map the touch to portrait mode if the device is in
            // landscape mode.
            final Point scaledTouch =
                    mUdfpsUtils.getTouchInNativeCoordinates(event.getPointerId(0),
                            event, udfpsEnrollView.getOverlayParams());

            final String theStr = mUdfpsUtils.onTouchOutsideOfSensorArea(
                    mEnrollingViewModel.isTouchExplorationEnabled(), context,
                    scaledTouch.x, scaledTouch.y, udfpsEnrollView.getOverlayParams());
            if (theStr != null) {
                v.announceForAccessibility(theStr);
            }
            return false;
        };

        enrollLayout.findManagedViewById(isLandscape ? R.id.sud_landscape_content_area
                : R.id.sud_layout_content).setOnHoverListener(onHoverListener);
    }

    private void onEnrollmentProgressChange(@NonNull EnrollmentProgress progress) {
        updateProgress(true /* animate */, progress);

        updateTitleAndDescription();

        if (mIsAccessibilityEnabled) {
            final int steps = progress.getSteps();
            final int remaining = progress.getRemaining();
            final int percent = (int) (((float) (steps - remaining) / (float) steps) * 100);
            CharSequence announcement = getActivity().getString(
                    R.string.security_settings_udfps_enroll_progress_a11y_message, percent);
            mEnrollingViewModel.sendAccessibilityEvent(announcement);
        }

    }

    private void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
        if (!TextUtils.isEmpty(helpString)) {
            showError(helpString);
            mUdfpsEnrollHelper.onEnrollmentHelp();
        }
    }

    private void onAcquired(boolean isAcquiredGood) {
        if (mUdfpsEnrollHelper != null) {
            mUdfpsEnrollHelper.onAcquired(isAcquiredGood);
        }
    }

    private void onPointerDown(int sensorId) {
        if (mUdfpsEnrollHelper != null) {
            mUdfpsEnrollHelper.onPointerDown(sensorId);
        }
    }

    private void onPointerUp(int sensorId) {
        if (mUdfpsEnrollHelper != null) {
            mUdfpsEnrollHelper.onPointerUp(sensorId);
        }
    }

    private void showError(CharSequence error) {
        mView.setHeaderText(error);
        mView.getHeaderTextView().setContentDescription(error);
        new GlifLayoutHelper(getActivity(), mView).setDescriptionText("");
    }


    private final Runnable mShowDialogRunnable = new Runnable() {
        @Override
        public void run() {
Loading