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

Commit 1d45f7f6 authored by Hao Dong's avatar Hao Dong Committed by Android (Google) Code Review
Browse files

Merge "Add udfps/ and support a11y for the udfps enroll view."

parents 2d2db1f7 24f8463a
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -20,15 +20,6 @@
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- The layout height/width are placeholders, which will be overwritten by
         FingerprintSensorPropertiesInternal. -->
    <View
        android:id="@+id/udfps_enroll_accessibility_view"
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="@string/accessibility_fingerprint_label"/>

    <ImageView
        android:id="@+id/udfps_enroll_animation_fp_progress_view"
        android:layout_width="match_parent"
+40 −21
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
@@ -40,7 +41,6 @@ import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.Process;
@@ -48,10 +48,8 @@ import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.DisplayUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
@@ -77,6 +75,8 @@ import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
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;
@@ -200,6 +200,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
    private boolean mHaveShownSfpsLeftEdgeLottie;
    private boolean mHaveShownSfpsRightEdgeLottie;
    private boolean mShouldShowLottie;
    private UdfpsUtils mUdfpsUtils;

    private OrientationEventListener mOrientationEventListener;
    private int mPreviousRotation = 0;
@@ -254,6 +255,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {

        mAccessibilityManager = getSystemService(AccessibilityManager.class);
        mIsAccessibilityEnabled = mAccessibilityManager.isEnabled();
        mUdfpsUtils = new UdfpsUtils();

        final boolean isLayoutRtl = (TextUtils.getLayoutDirectionFromLocale(
                Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL);
@@ -280,7 +282,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
                    layoutContainer.setLayoutParams(lp);
                    if (FeatureFlagUtils.isEnabled(getApplicationContext(),
                            FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
                        layout.addView(addUdfpsEnrollView(props.get(0)));
                        final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(props.get(0));
                        layout.addView(udfpsEnrollView);
                        setOnHoverListener(true, layout, udfpsEnrollView);
                    }
                    setContentView(layout, lp);
                    break;
@@ -293,6 +297,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
                            R.layout.udfps_enroll_enrolling, null, false);
                    if (FeatureFlagUtils.isEnabled(getApplicationContext(),
                            FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
                        final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(props.get(0));
                        if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
                            // In the portrait mode, set layout_container's height 0, so it's
                            // always shown at the bottom of the screen.
@@ -307,9 +312,11 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
                            final ViewGroup.LayoutParams containerLp =
                                    portraitLayoutContainer.getLayoutParams();
                            containerLp.height = 0;
                            portraitLayoutContainer.addView(addUdfpsEnrollView(props.get(0)));
                            portraitLayoutContainer.addView(udfpsEnrollView);
                            setOnHoverListener(false, defaultLayout, udfpsEnrollView);
                        } else if (rotation == Surface.ROTATION_270) {
                            defaultLayout.addView(addUdfpsEnrollView(props.get(0)));
                            defaultLayout.addView(udfpsEnrollView);
                            setOnHoverListener(true, defaultLayout, udfpsEnrollView);
                        }
                    }

@@ -1197,17 +1204,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {

        DisplayInfo displayInfo = new DisplayInfo();
        getDisplay().getDisplayInfo(displayInfo);
        final Display.Mode maxDisplayMode =
                DisplayUtils.getMaximumResolutionDisplayMode(displayInfo.supportedModes);
        final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
                maxDisplayMode.getPhysicalWidth(), maxDisplayMode.getPhysicalHeight(),
                displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight());
        if (scaleFactor == Float.POSITIVE_INFINITY) {
            mScaleFactor = 1f;
        } else {
            mScaleFactor = scaleFactor;
        }

        mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo);
        Rect udfpsBounds = udfpsProps.getLocation().getRect();
        udfpsBounds.scale(mScaleFactor);

@@ -1217,16 +1214,13 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
                displayInfo.getNaturalWidth(), /* right */
                displayInfo.getNaturalHeight() /* botom */);

        // TODO(b/260617060): Extract this logic into a 3rd party library for both Settings and
        //  SysUI to depend on.
        UdfpsOverlayParams params = new UdfpsOverlayParams(
                udfpsBounds,
                overlayBounds,
                displayInfo.getNaturalWidth(),
                displayInfo.getNaturalHeight(),
                mScaleFactor,
                displayInfo.rotation,
                udfpsProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
                displayInfo.rotation);

        udfpsEnrollView.setOverlayParams(params);

@@ -1244,6 +1238,31 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
        return udfpsEnrollView;
    }

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

        final Context context = getApplicationContext();
        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(
                    mAccessibilityManager.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);
    }

    public static class IconTouchDialog extends InstrumentedDialogFragment {

        @Override
+11 −21
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.util.AttributeSet;
import android.util.RotationUtils;
import android.view.Gravity;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -34,11 +33,13 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.settings.R;
import com.android.settingslib.udfps.UdfpsOverlayParams;

/**
 * View corresponding with udfps_enroll_view.xml
 */
public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Listener {
    private static final String TAG = "UdfpsEnrollView";
    @NonNull
    private final UdfpsEnrollDrawable mFingerprintDrawable;
    @NonNull
@@ -98,12 +99,15 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
        onFingerDown();
    }


    @Override
    public void onPointerUp(int sensorId) {
        onFingerUp();
    }

    public UdfpsOverlayParams getOverlayParams() {
        return mOverlayParams;
    }

    void setOverlayParams(UdfpsOverlayParams params) {
        mOverlayParams = params;

@@ -124,7 +128,6 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li

    private void onSensorRectUpdated() {
        updateDimensions();
        updateAccessibilityViewLocation();

        // Updates sensor rect in relation to the overlay view
        mSensorRect.set(getPaddingX(), getPaddingY(),
@@ -135,7 +138,7 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li

    private void updateDimensions() {
        // Original sensorBounds assume portrait mode.
        final Rect rotatedBounds = mOverlayParams.getSensorBounds();
        final Rect rotatedBounds = new Rect(mOverlayParams.getSensorBounds());
        int rotation = mOverlayParams.getRotation();
        if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
            RotationUtils.rotateBounds(
@@ -192,28 +195,15 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
        setLayoutParams(params);
    }

    private void updateAccessibilityViewLocation() {
        View fingerprintAccessibilityView = findViewById(R.id.udfps_enroll_accessibility_view);
        ViewGroup.LayoutParams params = fingerprintAccessibilityView.getLayoutParams();
        params.width = mOverlayParams.getSensorBounds().width();
        params.height = mOverlayParams.getSensorBounds().height();
        fingerprintAccessibilityView.setLayoutParams(params);
        fingerprintAccessibilityView.requestLayout();
    }

    private void onFingerDown() {
        if (mOverlayParams.isOptical()) {
        mFingerprintDrawable.setShouldSkipDraw(true);
        mFingerprintDrawable.invalidateSelf();
    }
    }

    private void onFingerUp() {
        if (mOverlayParams.isOptical()) {
        mFingerprintDrawable.setShouldSkipDraw(false);
        mFingerprintDrawable.invalidateSelf();
    }
    }

    private int getPaddingX() {
        return mProgressBarRadius;
+0 −95
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.biometrics.fingerprint;

import android.graphics.Rect;

import androidx.annotation.NonNull;

/**
 * Collection of parameters that define an under-display fingerprint sensor (UDFPS) overlay.
 *
 * [sensorBounds] coordinates of the bounding box around the sensor in natural orientation, in
 * pixels, for the current resolution.
 *
 * [overlayBounds] coordinates of the UI overlay in natural orientation, in pixels, for the current
 * resolution.
 *
 * [naturalDisplayWidth] width of the physical display in natural orientation, in pixels, for the
 * current resolution.
 *
 * [naturalDisplayHeight] height of the physical display in natural orientation, in pixels, for the
 * current resolution.
 *
 * [scaleFactor] ratio of a dimension in the current resolution to the corresponding dimension in
 * the native resolution.
 *
 * [rotation] current rotation of the display.
 */
public final class UdfpsOverlayParams {
    @NonNull
    private final Rect mSensorBounds;
    @NonNull
    private final Rect mOverlayBounds;
    private final int mNaturalDisplayWidth;
    private final int mNaturalDisplayHeight;
    private final float mScaleFactor;
    private final int mRotation;
    private final boolean mIsOptical;

    public UdfpsOverlayParams(@NonNull Rect sensorBounds, @NonNull Rect overlayBounds,
            int naturalDisplayWidth, int naturalDisplayHeight, float scaleFactor, int rotation,
            boolean isOptical) {
        mSensorBounds = sensorBounds;
        mOverlayBounds = overlayBounds;
        mNaturalDisplayWidth = naturalDisplayWidth;
        mNaturalDisplayHeight = naturalDisplayHeight;
        mScaleFactor = scaleFactor;
        mRotation = rotation;
        mIsOptical = isOptical;
    }

    @NonNull
    public Rect getSensorBounds() {
        return mSensorBounds;
    }

    @NonNull
    public Rect getOverlayBounds() {
        return mOverlayBounds;
    }

    public int getNaturalDisplayWidth() {
        return mNaturalDisplayWidth;
    }

    public int getNaturalDisplayHeight() {
        return mNaturalDisplayHeight;
    }

    public float getScaleFactor() {
        return mScaleFactor;
    }

    public int getRotation() {
        return mRotation;
    }

    public boolean isOptical() {
        return mIsOptical;
    }
}