Merge changes I143f7e5d,I87fa7feb into tm-qpr-dev
* changes: Add ellipse detection to UdfpsController Extend UdfpsView to bottom half of screen
This commit is contained in:
committed by
Android (Google) Code Review
commit
8de20f9177
@@ -37,6 +37,9 @@ public abstract class UdfpsAnimationView extends FrameLayout {
|
||||
private float mDialogSuggestedAlpha = 1f;
|
||||
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
|
||||
private int mAlpha;
|
||||
boolean mPauseAuth;
|
||||
@@ -117,6 +120,24 @@ public abstract class UdfpsAnimationView extends FrameLayout {
|
||||
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.
|
||||
* @param dialogSuggestedAlpha value from 0f to 1f.
|
||||
|
||||
@@ -66,6 +66,7 @@ import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.doze.DozeReceiver;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.keyguard.ScreenLifecycle;
|
||||
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
|
||||
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.
|
||||
@Nullable private Runnable mAuthControllerUpdateUdfpsLocation;
|
||||
@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.
|
||||
@Nullable private VelocityTracker mVelocityTracker;
|
||||
@@ -164,6 +165,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
|
||||
// The current request from FingerprintService. Null if no current request.
|
||||
@Nullable UdfpsControllerOverlay mOverlay;
|
||||
@Nullable private UdfpsEllipseDetection mUdfpsEllipseDetection;
|
||||
|
||||
// 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
|
||||
@@ -320,6 +322,10 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
if (!mOverlayParams.equals(overlayParams)) {
|
||||
mOverlayParams = overlayParams;
|
||||
|
||||
if (mFeatureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
|
||||
mUdfpsEllipseDetection.updateOverlayParams(overlayParams);
|
||||
}
|
||||
|
||||
final boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateBouncer();
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (withinSensorArea) {
|
||||
Trace.beginAsyncSection("UdfpsController.e2e.onPointerDown", 0);
|
||||
Log.v(TAG, "onTouch | action down");
|
||||
@@ -491,9 +512,25 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
? event.getPointerId(0)
|
||||
: event.findPointerIndex(mActivePointerId);
|
||||
if (idx == event.getActionIndex()) {
|
||||
boolean actionMoveWithinSensorArea =
|
||||
isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx),
|
||||
fromUdfpsView);
|
||||
boolean actionMoveWithinSensorArea;
|
||||
if (mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
|
||||
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)
|
||||
&& shouldTryToDismissKeyguard()) {
|
||||
Log.v(TAG, "onTouch | dismiss keyguard ACTION_MOVE");
|
||||
@@ -691,6 +728,10 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
|
||||
udfpsHapticsSimulator.setUdfpsController(this);
|
||||
udfpsShell.setUdfpsOverlayController(mUdfpsOverlayController);
|
||||
|
||||
if (featureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
|
||||
mUdfpsEllipseDetection = new UdfpsEllipseDetection(mOverlayParams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.android.systemui.R
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.shade.ShadeExpansionStateManager
|
||||
@@ -103,6 +104,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
private set
|
||||
|
||||
private var overlayParams: UdfpsOverlayParams = UdfpsOverlayParams()
|
||||
private var sensorBounds: Rect = Rect()
|
||||
|
||||
private var overlayTouchListener: TouchExplorationStateChangeListener? = null
|
||||
|
||||
@@ -120,6 +122,10 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
|
||||
// Avoid announcing window title.
|
||||
accessibilityTitle = " "
|
||||
|
||||
if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
|
||||
inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_SPY
|
||||
}
|
||||
}
|
||||
|
||||
/** A helper if the [requestReason] was due to enrollment. */
|
||||
@@ -160,6 +166,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
fun show(controller: UdfpsController, params: UdfpsOverlayParams): Boolean {
|
||||
if (overlayView == null) {
|
||||
overlayParams = params
|
||||
sensorBounds = Rect(params.sensorBounds)
|
||||
try {
|
||||
overlayView = (inflater.inflate(
|
||||
R.layout.udfps_view, null, false
|
||||
@@ -178,6 +185,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
windowManager.addView(this, coreLayoutParams.updateDimensions(animation))
|
||||
sensorRect = sensorBounds
|
||||
touchExplorationEnabled = accessibilityManager.isTouchExplorationEnabled
|
||||
overlayTouchListener = TouchExplorationStateChangeListener {
|
||||
if (accessibilityManager.isTouchExplorationEnabled) {
|
||||
@@ -194,6 +202,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
overlayTouchListener!!
|
||||
)
|
||||
overlayTouchListener?.onTouchExplorationStateChanged(true)
|
||||
useExpandedOverlay = featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
|
||||
}
|
||||
} catch (e: RuntimeException) {
|
||||
Log.e(TAG, "showUdfpsOverlay | failed to add window", e)
|
||||
@@ -225,13 +234,14 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
REASON_ENROLL_ENROLLING -> {
|
||||
UdfpsEnrollViewController(
|
||||
view.addUdfpsView(R.layout.udfps_enroll_view) {
|
||||
updateSensorLocation(overlayParams.sensorBounds)
|
||||
updateSensorLocation(sensorBounds)
|
||||
},
|
||||
enrollHelper ?: throw IllegalStateException("no enrollment helper"),
|
||||
statusBarStateController,
|
||||
shadeExpansionStateManager,
|
||||
dialogManager,
|
||||
dumpManager,
|
||||
featureFlags,
|
||||
overlayParams.scaleFactor
|
||||
)
|
||||
}
|
||||
@@ -420,7 +430,12 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
// 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
|
||||
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
|
||||
@@ -434,18 +449,27 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
} else {
|
||||
Log.v(TAG, "Rotate UDFPS bounds " + Surface.rotationToString(rot))
|
||||
RotationUtils.rotateBounds(
|
||||
rotatedSensorBounds,
|
||||
rotatedBounds,
|
||||
overlayParams.naturalDisplayWidth,
|
||||
overlayParams.naturalDisplayHeight,
|
||||
rot
|
||||
)
|
||||
|
||||
if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
|
||||
RotationUtils.rotateBounds(
|
||||
sensorBounds,
|
||||
overlayParams.naturalDisplayWidth,
|
||||
overlayParams.naturalDisplayHeight,
|
||||
rot
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x = rotatedSensorBounds.left - paddingX
|
||||
y = rotatedSensorBounds.top - paddingY
|
||||
height = rotatedSensorBounds.height() + 2 * paddingX
|
||||
width = rotatedSensorBounds.width() + 2 * paddingY
|
||||
x = rotatedBounds.left - paddingX
|
||||
y = rotatedBounds.top - paddingY
|
||||
height = rotatedBounds.height() + 2 * paddingX
|
||||
width = rotatedBounds.width() + 2 * paddingY
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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)
|
||||
)
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.biometrics;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.AttributeSet;
|
||||
@@ -41,6 +42,9 @@ public class UdfpsEnrollView extends UdfpsAnimationView {
|
||||
@NonNull private ImageView mFingerprintView;
|
||||
@NonNull private ImageView mFingerprintProgressView;
|
||||
|
||||
private LayoutParams mProgressParams;
|
||||
private float mProgressBarRadius;
|
||||
|
||||
public UdfpsEnrollView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mFingerprintDrawable = new UdfpsEnrollDrawable(mContext, attrs);
|
||||
@@ -56,6 +60,32 @@ public class UdfpsEnrollView extends UdfpsAnimationView {
|
||||
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
|
||||
public UdfpsDrawable getDrawable() {
|
||||
return mFingerprintDrawable;
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.graphics.PointF;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shade.ShadeExpansionStateManager;
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialogManager;
|
||||
@@ -57,6 +59,7 @@ public class UdfpsEnrollViewController extends UdfpsAnimationViewController<Udfp
|
||||
@NonNull ShadeExpansionStateManager shadeExpansionStateManager,
|
||||
@NonNull SystemUIDialogManager systemUIDialogManager,
|
||||
@NonNull DumpManager dumpManager,
|
||||
@NonNull FeatureFlags featureFlags,
|
||||
float scaleFactor) {
|
||||
super(view, statusBarStateController, shadeExpansionStateManager, systemUIDialogManager,
|
||||
dumpManager);
|
||||
@@ -64,6 +67,11 @@ public class UdfpsEnrollViewController extends UdfpsAnimationViewController<Udfp
|
||||
R.integer.config_udfpsEnrollProgressBar));
|
||||
mEnrollHelper = enrollHelper;
|
||||
mView.setEnrollHelper(mEnrollHelper);
|
||||
mView.setProgressBarRadius(mEnrollProgressBarRadius);
|
||||
|
||||
if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
|
||||
mView.mUseExpandedOverlay = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.MathUtils;
|
||||
import android.view.View;
|
||||
@@ -75,6 +76,8 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
|
||||
private int mAnimationType = ANIMATION_NONE;
|
||||
private boolean mFullyInflated;
|
||||
|
||||
private LayoutParams mParams;
|
||||
|
||||
public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mFingerprintDrawable = new UdfpsFpDrawable(context);
|
||||
@@ -239,6 +242,22 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
|
||||
updateAlpha();
|
||||
}
|
||||
|
||||
@Override
|
||||
void onSensorRectUpdated(RectF bounds) {
|
||||
super.onSensorRectUpdated(bounds);
|
||||
|
||||
if (mUseExpandedOverlay) {
|
||||
mParams = new LayoutParams((int) bounds.width(), (int) bounds.height());
|
||||
RectF converted = getBoundsRelativeToView(bounds);
|
||||
mParams.setMargins(
|
||||
(int) converted.left,
|
||||
(int) converted.top,
|
||||
(int) converted.right,
|
||||
(int) converted.bottom
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates in the bg protection circle behind the fp icon to highlight the icon.
|
||||
*/
|
||||
@@ -277,6 +296,7 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
|
||||
pw.println(" mUdfpsRequested=" + mUdfpsRequested);
|
||||
pw.println(" mInterpolatedDarkAmount=" + mInterpolatedDarkAmount);
|
||||
pw.println(" mAnimationType=" + mAnimationType);
|
||||
pw.println(" mUseExpandedOverlay=" + mUseExpandedOverlay);
|
||||
}
|
||||
|
||||
private final AsyncLayoutInflater.OnInflateFinishedListener mLayoutInflaterFinishListener =
|
||||
@@ -291,7 +311,12 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
|
||||
updatePadding();
|
||||
updateColor();
|
||||
updateAlpha();
|
||||
parent.addView(view);
|
||||
|
||||
if (mUseExpandedOverlay) {
|
||||
parent.addView(view, mParams);
|
||||
} else {
|
||||
parent.addView(view);
|
||||
}
|
||||
|
||||
// requires call to invalidate to update the color
|
||||
mLockScreenFp.addValueCallback(
|
||||
|
||||
@@ -52,7 +52,6 @@ import com.android.systemui.util.time.SystemClock
|
||||
import java.io.PrintWriter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/** Class that coordinates non-HBM animations during keyguard authentication. */
|
||||
@@ -82,6 +81,8 @@ constructor(
|
||||
systemUIDialogManager,
|
||||
dumpManager
|
||||
) {
|
||||
private val useExpandedOverlay: Boolean =
|
||||
featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
|
||||
private val isModernBouncerEnabled: Boolean = featureFlags.isEnabled(Flags.MODERN_BOUNCER)
|
||||
private var showingUdfpsBouncer = false
|
||||
private var udfpsRequested = false
|
||||
@@ -233,7 +234,13 @@ constructor(
|
||||
if (transitionToFullShadeProgress != 0f) {
|
||||
return
|
||||
}
|
||||
udfpsController.onTouch(event)
|
||||
|
||||
// Forwarding touches not needed with expanded overlay
|
||||
if (useExpandedOverlay) {
|
||||
return
|
||||
} else {
|
||||
udfpsController.onTouch(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +329,7 @@ constructor(
|
||||
keyguardViewManager.setAlternateBouncer(mAlternateBouncer)
|
||||
lockScreenShadeTransitionController.udfpsKeyguardViewController = this
|
||||
activityLaunchAnimator.addListener(activityLaunchAnimatorListener)
|
||||
view.mUseExpandedOverlay = useExpandedOverlay
|
||||
}
|
||||
|
||||
override fun onViewDetached() {
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.PointF
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
@@ -38,9 +39,12 @@ class UdfpsView(
|
||||
attrs: AttributeSet?
|
||||
) : FrameLayout(context, attrs), DozeReceiver {
|
||||
|
||||
// Use expanded overlay when feature flag is true, set by UdfpsViewController
|
||||
var useExpandedOverlay: Boolean = false
|
||||
|
||||
// sensorRect may be bigger than the sensor. True sensor dimensions are defined in
|
||||
// overlayParams.sensorBounds
|
||||
private val sensorRect = RectF()
|
||||
var sensorRect = Rect()
|
||||
private var mUdfpsDisplayMode: UdfpsDisplayModeProvider? = null
|
||||
private val debugTextPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
@@ -92,13 +96,19 @@ class UdfpsView(
|
||||
val paddingX = animationViewController?.paddingX ?: 0
|
||||
val paddingY = animationViewController?.paddingY ?: 0
|
||||
|
||||
sensorRect.set(
|
||||
paddingX.toFloat(),
|
||||
paddingY.toFloat(),
|
||||
(overlayParams.sensorBounds.width() + paddingX).toFloat(),
|
||||
(overlayParams.sensorBounds.height() + paddingY).toFloat()
|
||||
)
|
||||
animationViewController?.onSensorRectUpdated(RectF(sensorRect))
|
||||
// Updates sensor rect in relation to the overlay view
|
||||
if (useExpandedOverlay) {
|
||||
animationViewController?.onSensorRectUpdated(RectF(sensorRect))
|
||||
} else {
|
||||
sensorRect.set(
|
||||
paddingX,
|
||||
paddingY,
|
||||
(overlayParams.sensorBounds.width() + paddingX),
|
||||
(overlayParams.sensorBounds.height() + paddingY)
|
||||
)
|
||||
|
||||
animationViewController?.onSensorRectUpdated(RectF(sensorRect))
|
||||
}
|
||||
}
|
||||
|
||||
fun onTouchOutsideView() {
|
||||
|
||||
@@ -405,4 +405,10 @@ object Flags {
|
||||
|
||||
// 2100 - Falsing Manager
|
||||
@JvmField val FALSING_FOR_LONG_TAPS = releasedFlag(2100, "falsing_for_long_taps")
|
||||
|
||||
// 2200 - udfps
|
||||
// TODO(b/259264861): Tracking Bug
|
||||
@JvmField val UDFPS_NEW_TOUCH_DETECTION = unreleasedFlag(2200, "udfps_new_touch_detection")
|
||||
@JvmField val UDFPS_ELLIPSE_DEBUG_UI = unreleasedFlag(2201, "udfps_ellipse_debug")
|
||||
@JvmField val UDFPS_ELLIPSE_DETECTION = unreleasedFlag(2202, "udfps_ellipse_detection")
|
||||
}
|
||||
|
||||
@@ -94,6 +94,11 @@ public class UdfpsKeyguardViewControllerBaseTest extends SysuiTestCase {
|
||||
mKeyguardStateControllerCallbackCaptor;
|
||||
protected KeyguardStateController.Callback mKeyguardStateControllerCallback;
|
||||
|
||||
private @Captor ArgumentCaptor<StatusBarKeyguardViewManager.KeyguardViewManagerCallback>
|
||||
mKeyguardViewManagerCallbackArgumentCaptor;
|
||||
protected StatusBarKeyguardViewManager.KeyguardViewManagerCallback mKeyguardViewManagerCallback;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -143,15 +148,22 @@ public class UdfpsKeyguardViewControllerBaseTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
public UdfpsKeyguardViewController createUdfpsKeyguardViewController() {
|
||||
return createUdfpsKeyguardViewController(false);
|
||||
return createUdfpsKeyguardViewController(false, false);
|
||||
}
|
||||
|
||||
public void captureKeyGuardViewManagerCallback() {
|
||||
verify(mStatusBarKeyguardViewManager).addCallback(
|
||||
mKeyguardViewManagerCallbackArgumentCaptor.capture());
|
||||
mKeyguardViewManagerCallback = mKeyguardViewManagerCallbackArgumentCaptor.getValue();
|
||||
}
|
||||
|
||||
protected UdfpsKeyguardViewController createUdfpsKeyguardViewController(
|
||||
boolean useModernBouncer) {
|
||||
boolean useModernBouncer, boolean useExpandedOverlay) {
|
||||
mFeatureFlags.set(Flags.MODERN_BOUNCER, useModernBouncer);
|
||||
mFeatureFlags.set(Flags.UDFPS_NEW_TOUCH_DETECTION, useExpandedOverlay);
|
||||
when(mStatusBarKeyguardViewManager.getPrimaryBouncer()).thenReturn(
|
||||
useModernBouncer ? null : mBouncer);
|
||||
return new UdfpsKeyguardViewController(
|
||||
UdfpsKeyguardViewController controller = new UdfpsKeyguardViewController(
|
||||
mView,
|
||||
mStatusBarStateController,
|
||||
mShadeExpansionStateManager,
|
||||
@@ -168,5 +180,6 @@ public class UdfpsKeyguardViewControllerBaseTest extends SysuiTestCase {
|
||||
mActivityLaunchAnimator,
|
||||
mFeatureFlags,
|
||||
mPrimaryBouncerInteractor);
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.biometrics;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
@@ -30,6 +31,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -52,7 +54,8 @@ public class UdfpsKeyguardViewControllerTest extends UdfpsKeyguardViewController
|
||||
|
||||
@Override
|
||||
public UdfpsKeyguardViewController createUdfpsKeyguardViewController() {
|
||||
return createUdfpsKeyguardViewController(/* useModernBouncer */ false);
|
||||
return createUdfpsKeyguardViewController(/* useModernBouncer */ false,
|
||||
/* useExpandedOverlay */ false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -422,4 +425,37 @@ public class UdfpsKeyguardViewControllerTest extends UdfpsKeyguardViewController
|
||||
verify(mBouncer).addBouncerExpansionCallback(mBouncerExpansionCallbackCaptor.capture());
|
||||
mBouncerExpansionCallback = mBouncerExpansionCallbackCaptor.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
// TODO(b/259264861): Tracking Bug
|
||||
public void testUdfpsExpandedOverlayOn() {
|
||||
// GIVEN view is attached and useExpandedOverlay is true
|
||||
mController = createUdfpsKeyguardViewController(false, true);
|
||||
mController.onViewAttached();
|
||||
captureKeyGuardViewManagerCallback();
|
||||
|
||||
// WHEN a touch is received
|
||||
mKeyguardViewManagerCallback.onTouch(
|
||||
MotionEvent.obtain(0, 0, 0, 0, 0, 0));
|
||||
|
||||
// THEN udfpsController onTouch is not called
|
||||
assertTrue(mView.mUseExpandedOverlay);
|
||||
verify(mUdfpsController, never()).onTouch(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
// TODO(b/259264861): Tracking Bug
|
||||
public void testUdfpsExpandedOverlayOff() {
|
||||
// GIVEN view is attached and useExpandedOverlay is false
|
||||
mController.onViewAttached();
|
||||
captureKeyGuardViewManagerCallback();
|
||||
|
||||
// WHEN a touch is received
|
||||
mKeyguardViewManagerCallback.onTouch(
|
||||
MotionEvent.obtain(0, 0, 0, 0, 0, 0));
|
||||
|
||||
// THEN udfpsController onTouch is called
|
||||
assertFalse(mView.mUseExpandedOverlay);
|
||||
verify(mUdfpsController).onTouch(any());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,10 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
|
||||
mock(KeyguardBypassController::class.java),
|
||||
mKeyguardUpdateMonitor
|
||||
)
|
||||
return createUdfpsKeyguardViewController(/* useModernBouncer */ true)
|
||||
return createUdfpsKeyguardViewController(
|
||||
/* useModernBouncer */ true, /* useExpandedOverlay */
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
/** After migration, replaces LockIconViewControllerTest version */
|
||||
|
||||
Reference in New Issue
Block a user