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

Commit 3c34e335 authored by Austin Delgado's avatar Austin Delgado Committed by Automerger Merge Worker
Browse files

Merge changes I143f7e5d,I87fa7feb into tm-qpr-dev am: 8de20f91

parents 1b165f94 8de20f91
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,9 @@ public abstract class UdfpsAnimationView extends FrameLayout {
    private float mDialogSuggestedAlpha = 1f;
    private float mDialogSuggestedAlpha = 1f;
    private float mNotificationShadeExpansion = 0f;
    private float mNotificationShadeExpansion = 0f;


    // Used for Udfps ellipse detection when flag is true, set by AnimationViewController
    boolean mUseExpandedOverlay = false;

    // mAlpha takes into consideration the status bar expansion amount and dialog suggested alpha
    // mAlpha takes into consideration the status bar expansion amount and dialog suggested alpha
    private int mAlpha;
    private int mAlpha;
    boolean mPauseAuth;
    boolean mPauseAuth;
@@ -117,6 +120,24 @@ public abstract class UdfpsAnimationView extends FrameLayout {
        return (int) ((1 - percent) * 255);
        return (int) ((1 - percent) * 255);
    }
    }


    /**
     * Converts coordinates of RectF relative to the screen to coordinates relative to this view.
     *
     * @param bounds RectF based off screen coordinates in current orientation
     */
    RectF getBoundsRelativeToView(RectF bounds) {
        int[] pos = getLocationOnScreen();

        RectF output = new RectF(
                bounds.left - pos[0],
                bounds.top - pos[1],
                bounds.right - pos[0],
                bounds.bottom - pos[1]
        );

        return output;
    }

    /**
    /**
     * Set the suggested alpha based on whether a dialog was recently shown or hidden.
     * Set the suggested alpha based on whether a dialog was recently shown or hidden.
     * @param dialogSuggestedAlpha value from 0f to 1f.
     * @param dialogSuggestedAlpha value from 0f to 1f.
+46 −5
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.FalsingManager;
@@ -149,7 +150,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
    // TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this.
    // TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this.
    @Nullable private Runnable mAuthControllerUpdateUdfpsLocation;
    @Nullable private Runnable mAuthControllerUpdateUdfpsLocation;
    @Nullable private final AlternateUdfpsTouchProvider mAlternateTouchProvider;
    @Nullable private final AlternateUdfpsTouchProvider mAlternateTouchProvider;
    @Nullable private UdfpsDisplayMode mUdfpsDisplayMode;
    @Nullable private UdfpsDisplayModeProvider mUdfpsDisplayMode;


    // Tracks the velocity of a touch to help filter out the touches that move too fast.
    // Tracks the velocity of a touch to help filter out the touches that move too fast.
    @Nullable private VelocityTracker mVelocityTracker;
    @Nullable private VelocityTracker mVelocityTracker;
@@ -164,6 +165,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {


    // The current request from FingerprintService. Null if no current request.
    // The current request from FingerprintService. Null if no current request.
    @Nullable UdfpsControllerOverlay mOverlay;
    @Nullable UdfpsControllerOverlay mOverlay;
    @Nullable private UdfpsEllipseDetection mUdfpsEllipseDetection;


    // The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
    // The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
    // to turn off high brightness mode. To get around this limitation, the state of the AOD
    // to turn off high brightness mode. To get around this limitation, the state of the AOD
@@ -320,6 +322,10 @@ public class UdfpsController implements DozeReceiver, Dumpable {
        if (!mOverlayParams.equals(overlayParams)) {
        if (!mOverlayParams.equals(overlayParams)) {
            mOverlayParams = overlayParams;
            mOverlayParams = overlayParams;


            if (mFeatureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
                mUdfpsEllipseDetection.updateOverlayParams(overlayParams);
            }

            final boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateBouncer();
            final boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateBouncer();


            // When the bounds change it's always necessary to re-create the overlay's window with
            // When the bounds change it's always necessary to re-create the overlay's window with
@@ -459,8 +465,23 @@ public class UdfpsController implements DozeReceiver, Dumpable {
                    mVelocityTracker.clear();
                    mVelocityTracker.clear();
                }
                }


                boolean withinSensorArea =
                boolean withinSensorArea;
                if (mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
                    if (mFeatureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
                        // Ellipse detection
                        withinSensorArea = mUdfpsEllipseDetection.isGoodEllipseOverlap(event);
                    } else {
                        // Centroid with expanded overlay
                        withinSensorArea =
                            isWithinSensorArea(udfpsView, event.getRawX(),
                                        event.getRawY(), fromUdfpsView);
                    }
                } else {
                    // Centroid with sensor sized view
                    withinSensorArea =
                        isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView);
                        isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView);
                }

                if (withinSensorArea) {
                if (withinSensorArea) {
                    Trace.beginAsyncSection("UdfpsController.e2e.onPointerDown", 0);
                    Trace.beginAsyncSection("UdfpsController.e2e.onPointerDown", 0);
                    Log.v(TAG, "onTouch | action down");
                    Log.v(TAG, "onTouch | action down");
@@ -491,9 +512,25 @@ public class UdfpsController implements DozeReceiver, Dumpable {
                        ? event.getPointerId(0)
                        ? event.getPointerId(0)
                        : event.findPointerIndex(mActivePointerId);
                        : event.findPointerIndex(mActivePointerId);
                if (idx == event.getActionIndex()) {
                if (idx == event.getActionIndex()) {
                    boolean actionMoveWithinSensorArea =
                    boolean actionMoveWithinSensorArea;
                            isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx),
                    if (mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
                                    fromUdfpsView);
                        if (mFeatureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
                            // Ellipse detection
                            actionMoveWithinSensorArea =
                                    mUdfpsEllipseDetection.isGoodEllipseOverlap(event);
                        } else {
                            // Centroid with expanded overlay
                            actionMoveWithinSensorArea =
                                isWithinSensorArea(udfpsView, event.getRawX(idx),
                                        event.getRawY(idx), fromUdfpsView);
                        }
                    } else {
                        // Centroid with sensor sized view
                        actionMoveWithinSensorArea =
                            isWithinSensorArea(udfpsView, event.getX(idx),
                                    event.getY(idx), fromUdfpsView);
                    }

                    if ((fromUdfpsView || actionMoveWithinSensorArea)
                    if ((fromUdfpsView || actionMoveWithinSensorArea)
                            && shouldTryToDismissKeyguard()) {
                            && shouldTryToDismissKeyguard()) {
                        Log.v(TAG, "onTouch | dismiss keyguard ACTION_MOVE");
                        Log.v(TAG, "onTouch | dismiss keyguard ACTION_MOVE");
@@ -691,6 +728,10 @@ public class UdfpsController implements DozeReceiver, Dumpable {


        udfpsHapticsSimulator.setUdfpsController(this);
        udfpsHapticsSimulator.setUdfpsController(this);
        udfpsShell.setUdfpsOverlayController(mUdfpsOverlayController);
        udfpsShell.setUdfpsOverlayController(mUdfpsOverlayController);

        if (featureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
            mUdfpsEllipseDetection = new UdfpsEllipseDetection(mOverlayParams);
        }
    }
    }


    /**
    /**
+31 −7
Original line number Original line Diff line number Diff line
@@ -49,6 +49,7 @@ import com.android.systemui.R
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dump.DumpManager
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeExpansionStateManager
import com.android.systemui.shade.ShadeExpansionStateManager
@@ -103,6 +104,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
        private set
        private set


    private var overlayParams: UdfpsOverlayParams = UdfpsOverlayParams()
    private var overlayParams: UdfpsOverlayParams = UdfpsOverlayParams()
    private var sensorBounds: Rect = Rect()


    private var overlayTouchListener: TouchExplorationStateChangeListener? = null
    private var overlayTouchListener: TouchExplorationStateChangeListener? = null


@@ -120,6 +122,10 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
        privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
        privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
        // Avoid announcing window title.
        // Avoid announcing window title.
        accessibilityTitle = " "
        accessibilityTitle = " "

        if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
            inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_SPY
        }
    }
    }


    /** A helper if the [requestReason] was due to enrollment. */
    /** A helper if the [requestReason] was due to enrollment. */
@@ -160,6 +166,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
    fun show(controller: UdfpsController, params: UdfpsOverlayParams): Boolean {
    fun show(controller: UdfpsController, params: UdfpsOverlayParams): Boolean {
        if (overlayView == null) {
        if (overlayView == null) {
            overlayParams = params
            overlayParams = params
            sensorBounds = Rect(params.sensorBounds)
            try {
            try {
                overlayView = (inflater.inflate(
                overlayView = (inflater.inflate(
                    R.layout.udfps_view, null, false
                    R.layout.udfps_view, null, false
@@ -178,6 +185,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
                    }
                    }


                    windowManager.addView(this, coreLayoutParams.updateDimensions(animation))
                    windowManager.addView(this, coreLayoutParams.updateDimensions(animation))
                    sensorRect = sensorBounds
                    touchExplorationEnabled = accessibilityManager.isTouchExplorationEnabled
                    touchExplorationEnabled = accessibilityManager.isTouchExplorationEnabled
                    overlayTouchListener = TouchExplorationStateChangeListener {
                    overlayTouchListener = TouchExplorationStateChangeListener {
                        if (accessibilityManager.isTouchExplorationEnabled) {
                        if (accessibilityManager.isTouchExplorationEnabled) {
@@ -194,6 +202,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
                        overlayTouchListener!!
                        overlayTouchListener!!
                    )
                    )
                    overlayTouchListener?.onTouchExplorationStateChanged(true)
                    overlayTouchListener?.onTouchExplorationStateChanged(true)
                    useExpandedOverlay = featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
                }
                }
            } catch (e: RuntimeException) {
            } catch (e: RuntimeException) {
                Log.e(TAG, "showUdfpsOverlay | failed to add window", e)
                Log.e(TAG, "showUdfpsOverlay | failed to add window", e)
@@ -225,13 +234,14 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
            REASON_ENROLL_ENROLLING -> {
            REASON_ENROLL_ENROLLING -> {
                UdfpsEnrollViewController(
                UdfpsEnrollViewController(
                    view.addUdfpsView(R.layout.udfps_enroll_view) {
                    view.addUdfpsView(R.layout.udfps_enroll_view) {
                        updateSensorLocation(overlayParams.sensorBounds)
                        updateSensorLocation(sensorBounds)
                    },
                    },
                    enrollHelper ?: throw IllegalStateException("no enrollment helper"),
                    enrollHelper ?: throw IllegalStateException("no enrollment helper"),
                    statusBarStateController,
                    statusBarStateController,
                    shadeExpansionStateManager,
                    shadeExpansionStateManager,
                    dialogManager,
                    dialogManager,
                    dumpManager,
                    dumpManager,
                    featureFlags,
                    overlayParams.scaleFactor
                    overlayParams.scaleFactor
                )
                )
            }
            }
@@ -420,7 +430,12 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
        }
        }


        // Original sensorBounds assume portrait mode.
        // Original sensorBounds assume portrait mode.
        val rotatedSensorBounds = Rect(overlayParams.sensorBounds)
        var rotatedBounds =
            if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
                Rect(overlayParams.overlayBounds)
            } else {
                Rect(overlayParams.sensorBounds)
            }


        val rot = overlayParams.rotation
        val rot = overlayParams.rotation
        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
@@ -434,18 +449,27 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
            } else {
            } else {
                Log.v(TAG, "Rotate UDFPS bounds " + Surface.rotationToString(rot))
                Log.v(TAG, "Rotate UDFPS bounds " + Surface.rotationToString(rot))
                RotationUtils.rotateBounds(
                RotationUtils.rotateBounds(
                    rotatedSensorBounds,
                    rotatedBounds,
                    overlayParams.naturalDisplayWidth,
                    overlayParams.naturalDisplayHeight,
                    rot
                )

                if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
                    RotationUtils.rotateBounds(
                            sensorBounds,
                            overlayParams.naturalDisplayWidth,
                            overlayParams.naturalDisplayWidth,
                            overlayParams.naturalDisplayHeight,
                            overlayParams.naturalDisplayHeight,
                            rot
                            rot
                    )
                    )
                }
                }
            }
            }
        }


        x = rotatedSensorBounds.left - paddingX
        x = rotatedBounds.left - paddingX
        y = rotatedSensorBounds.top - paddingY
        y = rotatedBounds.top - paddingY
        height = rotatedSensorBounds.height() + 2 * paddingX
        height = rotatedBounds.height() + 2 * paddingX
        width = rotatedSensorBounds.width() + 2 * paddingY
        width = rotatedBounds.width() + 2 * paddingY


        return this
        return this
    }
    }
+92 −0
Original line number Original line 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.systemui.biometrics

import android.graphics.Point
import android.graphics.Rect
import android.util.RotationUtils
import android.view.MotionEvent
import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.sin

private const val TAG = "UdfpsEllipseDetection"

private const val NEEDED_POINTS = 2

class UdfpsEllipseDetection(overlayParams: UdfpsOverlayParams) {
    var sensorRect = Rect()
    var points: Array<Point> = emptyArray()

    init {
        sensorRect = Rect(overlayParams.sensorBounds)

        points = calculateSensorPoints(sensorRect)
    }

    fun updateOverlayParams(params: UdfpsOverlayParams) {
        sensorRect = Rect(params.sensorBounds)

        val rot = params.rotation
        RotationUtils.rotateBounds(
            sensorRect,
            params.naturalDisplayWidth,
            params.naturalDisplayHeight,
            rot
        )

        points = calculateSensorPoints(sensorRect)
    }

    fun isGoodEllipseOverlap(event: MotionEvent): Boolean {
        return points.count { checkPoint(event, it) } >= NEEDED_POINTS
    }

    private fun checkPoint(event: MotionEvent, point: Point): Boolean {
        // Calculate if sensor point is within ellipse
        // Formula: ((cos(o)(xE - xS) + sin(o)(yE - yS))^2 / a^2) + ((sin(o)(xE - xS) + cos(o)(yE -
        // yS))^2 / b^2) <= 1
        val a: Float = cos(event.orientation) * (point.x - event.rawX)
        val b: Float = sin(event.orientation) * (point.y - event.rawY)
        val c: Float = sin(event.orientation) * (point.x - event.rawX)
        val d: Float = cos(event.orientation) * (point.y - event.rawY)
        val result =
            (a + b).pow(2) / (event.touchMinor / 2).pow(2) +
                (c - d).pow(2) / (event.touchMajor / 2).pow(2)

        return result <= 1
    }
}

fun calculateSensorPoints(sensorRect: Rect): Array<Point> {
    val sensorX = sensorRect.centerX()
    val sensorY = sensorRect.centerY()
    val cornerOffset: Int = sensorRect.width() / 4
    val sideOffset: Int = sensorRect.width() / 3

    return arrayOf(
        Point(sensorX - cornerOffset, sensorY - cornerOffset),
        Point(sensorX, sensorY - sideOffset),
        Point(sensorX + cornerOffset, sensorY - cornerOffset),
        Point(sensorX - sideOffset, sensorY),
        Point(sensorX, sensorY),
        Point(sensorX + sideOffset, sensorY),
        Point(sensorX - cornerOffset, sensorY + cornerOffset),
        Point(sensorX, sensorY + sideOffset),
        Point(sensorX + cornerOffset, sensorY + cornerOffset)
    )
}
+30 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.biometrics;


import android.content.Context;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Handler;
import android.os.Looper;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.AttributeSet;
@@ -41,6 +42,9 @@ public class UdfpsEnrollView extends UdfpsAnimationView {
    @NonNull private ImageView mFingerprintView;
    @NonNull private ImageView mFingerprintView;
    @NonNull private ImageView mFingerprintProgressView;
    @NonNull private ImageView mFingerprintProgressView;


    private LayoutParams mProgressParams;
    private float mProgressBarRadius;

    public UdfpsEnrollView(Context context, @Nullable AttributeSet attrs) {
    public UdfpsEnrollView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        super(context, attrs);
        mFingerprintDrawable = new UdfpsEnrollDrawable(mContext, attrs);
        mFingerprintDrawable = new UdfpsEnrollDrawable(mContext, attrs);
@@ -56,6 +60,32 @@ public class UdfpsEnrollView extends UdfpsAnimationView {
        mFingerprintProgressView.setImageDrawable(mFingerprintProgressDrawable);
        mFingerprintProgressView.setImageDrawable(mFingerprintProgressDrawable);
    }
    }


    @Override
    void onSensorRectUpdated(RectF bounds) {
        if (mUseExpandedOverlay) {
            RectF converted = getBoundsRelativeToView(bounds);

            mProgressParams = new LayoutParams(
                    (int) (converted.width() + mProgressBarRadius * 2),
                    (int) (converted.height() + mProgressBarRadius * 2));
            mProgressParams.setMargins(
                    (int) (converted.left - mProgressBarRadius),
                    (int) (converted.top - mProgressBarRadius),
                    (int) (converted.right + mProgressBarRadius),
                    (int) (converted.bottom + mProgressBarRadius)
            );

            mFingerprintProgressView.setLayoutParams(mProgressParams);
            super.onSensorRectUpdated(converted);
        } else {
            super.onSensorRectUpdated(bounds);
        }
    }

    void setProgressBarRadius(float radius) {
        mProgressBarRadius = radius;
    }

    @Override
    @Override
    public UdfpsDrawable getDrawable() {
    public UdfpsDrawable getDrawable() {
        return mFingerprintDrawable;
        return mFingerprintDrawable;
Loading