Merge "Check orientation when retrieving FP location" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2022-09-01 16:44:54 +00:00
committed by Android (Google) Code Review
11 changed files with 313 additions and 154 deletions

View File

@@ -19,7 +19,7 @@ package com.android.keyguard;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -54,7 +54,7 @@ public class LockIconView extends FrameLayout implements Dumpable {
private boolean mAod;
@NonNull private final RectF mSensorRect;
@NonNull private PointF mLockIconCenter = new PointF(0f, 0f);
@NonNull private Point mLockIconCenter = new Point(0, 0);
private float mRadius;
private int mLockIconPadding;
@@ -126,7 +126,7 @@ public class LockIconView extends FrameLayout implements Dumpable {
* Set the location of the lock icon.
*/
@VisibleForTesting
public void setCenterLocation(@NonNull PointF center, float radius, int drawablePadding) {
public void setCenterLocation(@NonNull Point center, float radius, int drawablePadding) {
mLockIconCenter = center;
mRadius = radius;
mLockIconPadding = drawablePadding;

View File

@@ -26,7 +26,7 @@ import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedStateListDrawable;
import android.hardware.biometrics.BiometricSourceType;
@@ -357,8 +357,9 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mAuthController.getUdfpsRadius(), scaledPadding);
} else {
mView.setCenterLocation(
new PointF(mWidthPixels / 2,
mHeightPixels - ((mBottomPaddingPx + sLockIconRadiusPx) * scaleFactor)),
new Point((int) mWidthPixels / 2,
(int) (mHeightPixels
- ((mBottomPaddingPx + sLockIconRadiusPx) * scaleFactor))),
sLockIconRadiusPx * scaleFactor, scaledPadding);
}
}

View File

@@ -31,7 +31,6 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
@@ -55,7 +54,9 @@ import android.os.Handler;
import android.os.RemoteException;
import android.os.UserManager;
import android.util.Log;
import android.util.RotationUtils;
import android.util.SparseBooleanArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.MotionEvent;
import android.view.WindowManager;
@@ -116,8 +117,14 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@NonNull private Point mStableDisplaySize = new Point();
@Nullable private final PointF mFaceAuthSensorLocation;
@Nullable private PointF mFingerprintLocation;
private final Display mDisplay;
private float mScaleFactor = 1f;
// sensor locations without any resolution scaling nor rotation adjustments:
@Nullable private final Point mFaceSensorLocationDefault;
@Nullable private final Point mFingerprintSensorLocationDefault;
// cached sensor locations:
@Nullable private Point mFaceSensorLocation;
@Nullable private Point mFingerprintSensorLocation;
@Nullable private Rect mUdfpsBounds;
private final Set<Callback> mCallbacks = new HashSet<>();
@@ -147,6 +154,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@NonNull private final LockPatternUtils mLockPatternUtils;
@NonNull private final InteractionJankMonitor mInteractionJankMonitor;
private final @Background DelayableExecutor mBackgroundExecutor;
private final DisplayInfo mCachedDisplayInfo = new DisplayInfo();
@VisibleForTesting
final TaskStackListener mTaskStackListener = new TaskStackListener() {
@@ -184,7 +192,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
Log.w(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
mCurrentDialog.dismissWithoutCallback(true /* animate */);
mCurrentDialog = null;
mOrientationListener.disable();
for (Callback cb : mCallbacks) {
cb.onBiometricPromptDismissed();
@@ -218,7 +225,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
Log.e(TAG, "Evicting client due to: " + topPackage);
mCurrentDialog.dismissWithoutCallback(true /* animate */);
mCurrentDialog = null;
mOrientationListener.disable();
for (Callback cb : mCallbacks) {
cb.onBiometricPromptDismissed();
@@ -284,7 +290,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mUdfpsController.setAuthControllerUpdateUdfpsLocation(this::updateUdfpsLocation);
mUdfpsController.setHalControlsIllumination(mUdfpsProps.get(0).halControlsIllumination);
mUdfpsBounds = mUdfpsProps.get(0).getLocation().getRect();
updateUdfpsLocation();
}
mSidefpsProps = !sidefpsProps.isEmpty() ? sidefpsProps : null;
@@ -292,8 +297,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mSidefpsController = mSidefpsControllerFactory.get();
}
updateSensorLocations();
mFingerprintManager.registerBiometricStateListener(mBiometricStateListener);
updateFingerprintLocation();
for (Callback cb : mCallbacks) {
cb.onAllAuthenticatorsRegistered();
@@ -470,11 +475,11 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
/**
* @return where the UDFPS exists on the screen in pixels in portrait mode.
*/
@Nullable public PointF getUdfpsLocation() {
@Nullable public Point getUdfpsLocation() {
if (mUdfpsController == null || mUdfpsBounds == null) {
return null;
}
return new PointF(mUdfpsBounds.centerX(), mUdfpsBounds.centerY());
return new Point(mUdfpsBounds.centerX(), mUdfpsBounds.centerY());
}
/**
@@ -488,45 +493,105 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
}
/**
* @return the scale factor representing the user's current resolution / the stable
* (default) resolution
* Gets the cached scale factor representing the user's current resolution / the stable
* (default) resolution.
*/
public float getScaleFactor() {
if (mUdfpsController == null || mUdfpsController.mOverlayParams == null) {
return 1f;
}
return mUdfpsController.mOverlayParams.getScaleFactor();
return mScaleFactor;
}
/**
* @return where the fingerprint sensor exists in pixels in portrait mode. devices without an
* overridden value will use the default value even if they don't have a fingerprint sensor
* Updates the current display info and cached scale factor & sensor locations.
* Getting the display info is a relatively expensive call, so avoid superfluous calls.
*/
@Nullable public PointF getFingerprintSensorLocation() {
private void updateSensorLocations() {
mDisplay.getDisplayInfo(mCachedDisplayInfo);
final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
mStableDisplaySize.x, mStableDisplaySize.y, mCachedDisplayInfo.getNaturalWidth(),
mCachedDisplayInfo.getNaturalHeight());
if (scaleFactor == Float.POSITIVE_INFINITY) {
mScaleFactor = 1f;
} else {
mScaleFactor = scaleFactor;
}
updateUdfpsLocation();
updateFingerprintLocation();
updateFaceLocation();
}
/**
* @return where the fingerprint sensor exists in pixels in its natural orientation.
* Devices without location configs will use the default value even if they don't have a
* fingerprint sensor.
*
* May return null if the fingerprint sensor isn't available yet.
*/
@Nullable private Point getFingerprintSensorLocationInNaturalOrientation() {
if (getUdfpsLocation() != null) {
return getUdfpsLocation();
}
return mFingerprintLocation;
return new Point(
(int) (mFingerprintSensorLocationDefault.x * mScaleFactor),
(int) (mFingerprintSensorLocationDefault.y * mScaleFactor)
);
}
/**
* @return where the face authentication sensor exists relative to the screen in pixels in
* portrait mode.
* @return where the fingerprint sensor exists in pixels exists the current device orientation.
* Devices without location configs will use the default value even if they don't have a
* fingerprint sensor.
*/
@Nullable public PointF getFaceAuthSensorLocation() {
if (mFaceProps == null || mFaceAuthSensorLocation == null) {
return null;
@Nullable public Point getFingerprintSensorLocation() {
return mFingerprintSensorLocation;
}
private void updateFingerprintLocation() {
if (mFpProps == null) {
mFingerprintSensorLocation = null;
} else {
mFingerprintSensorLocation = rotateToCurrentOrientation(
getFingerprintSensorLocationInNaturalOrientation(),
mCachedDisplayInfo);
}
DisplayInfo displayInfo = new DisplayInfo();
mContext.getDisplay().getDisplayInfo(displayInfo);
final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
mStableDisplaySize.x, mStableDisplaySize.y, displayInfo.getNaturalWidth(),
displayInfo.getNaturalHeight());
if (scaleFactor == Float.POSITIVE_INFINITY) {
return new PointF(mFaceAuthSensorLocation.x, mFaceAuthSensorLocation.y);
}
/**
* @return where the face sensor exists in pixels in the current device orientation. Returns
* null if no face sensor exists.
*/
@Nullable public Point getFaceSensorLocation() {
return mFaceSensorLocation;
}
private void updateFaceLocation() {
if (mFaceProps == null || mFaceSensorLocationDefault == null) {
mFaceSensorLocation = null;
} else {
mFaceSensorLocation = rotateToCurrentOrientation(
new Point(
(int) (mFaceSensorLocationDefault.x * mScaleFactor),
(int) (mFaceSensorLocationDefault.y * mScaleFactor)),
mCachedDisplayInfo
);
}
return new PointF(mFaceAuthSensorLocation.x * scaleFactor,
mFaceAuthSensorLocation.y * scaleFactor);
}
/**
* @param inOutPoint point on the display in pixels. Going in, represents the point
* in the device's natural orientation. Going out, represents
* the point in the display's current orientation.
* @param displayInfo currently display information to use to rotate the point
*/
@VisibleForTesting
protected Point rotateToCurrentOrientation(Point inOutPoint, DisplayInfo displayInfo) {
RotationUtils.rotatePoint(
inOutPoint,
displayInfo.rotation,
displayInfo.getNaturalWidth(),
displayInfo.getNaturalHeight()
);
return inOutPoint;
}
/**
@@ -625,45 +690,36 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
});
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
int[] faceAuthLocation = context.getResources().getIntArray(
com.android.systemui.R.array.config_face_auth_props);
if (faceAuthLocation == null || faceAuthLocation.length < 2) {
mFaceAuthSensorLocation = null;
mFaceSensorLocationDefault = null;
} else {
mFaceAuthSensorLocation = new PointF(
(float) faceAuthLocation[0],
(float) faceAuthLocation[1]);
mFaceSensorLocationDefault = new Point(
faceAuthLocation[0],
faceAuthLocation[1]);
}
updateFingerprintLocation();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED);
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
}
private int getDisplayWidth() {
DisplayInfo displayInfo = new DisplayInfo();
mContext.getDisplay().getDisplayInfo(displayInfo);
return displayInfo.getNaturalWidth();
}
private void updateFingerprintLocation() {
int xLocation = getDisplayWidth() / 2;
mDisplay = mContext.getDisplay();
mDisplay.getDisplayInfo(mCachedDisplayInfo);
int xFpLocation = mCachedDisplayInfo.getNaturalWidth() / 2;
try {
xLocation = mContext.getResources().getDimensionPixelSize(
xFpLocation = mContext.getResources().getDimensionPixelSize(
com.android.systemui.R.dimen
.physical_fingerprint_sensor_center_screen_location_x);
} catch (Resources.NotFoundException e) {
}
int yLocation = mContext.getResources().getDimensionPixelSize(
com.android.systemui.R.dimen.physical_fingerprint_sensor_center_screen_location_y);
mFingerprintLocation = new PointF(
xLocation,
yLocation);
mFingerprintSensorLocationDefault = new Point(
xFpLocation,
mContext.getResources().getDimensionPixelSize(com.android.systemui.R.dimen
.physical_fingerprint_sensor_center_screen_location_y)
);
updateSensorLocations();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED);
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
}
// TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this.
@@ -672,19 +728,14 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
// updateFingerprintLocation in such a case are unclear.
private void updateUdfpsLocation() {
if (mUdfpsController != null) {
final DisplayInfo displayInfo = new DisplayInfo();
mContext.getDisplay().getDisplayInfo(displayInfo);
final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
mStableDisplaySize.x, mStableDisplaySize.y, displayInfo.getNaturalWidth(),
displayInfo.getNaturalHeight());
final FingerprintSensorPropertiesInternal udfpsProp = mUdfpsProps.get(0);
final Rect previousUdfpsBounds = mUdfpsBounds;
mUdfpsBounds = udfpsProp.getLocation().getRect();
mUdfpsBounds.scale(scaleFactor);
mUdfpsBounds.scale(mScaleFactor);
mUdfpsController.updateOverlayParams(udfpsProp.sensorId,
new UdfpsOverlayParams(mUdfpsBounds, displayInfo.getNaturalWidth(),
displayInfo.getNaturalHeight(), scaleFactor, displayInfo.rotation));
new UdfpsOverlayParams(mUdfpsBounds, mCachedDisplayInfo.getNaturalWidth(),
mCachedDisplayInfo.getNaturalHeight(), mScaleFactor,
mCachedDisplayInfo.rotation));
if (!Objects.equals(previousUdfpsBounds, mUdfpsBounds)) {
for (Callback cb : mCallbacks) {
cb.onUdfpsLocationChanged();
@@ -705,6 +756,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mStableDisplaySize = mDisplayManager.getStableDisplaySize();
mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
mOrientationListener.enable();
updateSensorLocations();
}
@Override
@@ -905,7 +958,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
// BiometricService will have already sent the callback to the client in this case.
// This avoids a round trip to SystemUI. So, just dismiss the dialog and we're done.
mCurrentDialog = null;
mOrientationListener.disable();
}
/**
@@ -996,7 +1048,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
}
mCurrentDialog = newDialog;
mCurrentDialog.show(mWindowManager, savedState);
mOrientationListener.enable();
if (!promptInfo.isAllowBackgroundAuthentication()) {
mHandler.post(this::cancelIfOwnerIsNotInForeground);
@@ -1015,14 +1066,12 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mReceiver = null;
mCurrentDialog = null;
mOrientationListener.disable();
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateFingerprintLocation();
updateUdfpsLocation();
updateSensorLocations();
// Save the state of the current dialog (buttons showing, etc)
if (mCurrentDialog != null) {
@@ -1030,7 +1079,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mCurrentDialog.onSaveState(savedState);
mCurrentDialog.dismissWithoutCallback(false /* animate */);
mCurrentDialog = null;
mOrientationListener.disable();
// Only show the dialog if necessary. If it was animating out, the dialog is supposed
// to send its pending callback immediately.
@@ -1051,8 +1099,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
}
private void onOrientationChanged() {
updateFingerprintLocation();
updateUdfpsLocation();
updateSensorLocations();
if (mCurrentDialog != null) {
mCurrentDialog.onOrientationChanged();
}
@@ -1062,6 +1109,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
PromptInfo promptInfo, boolean requireConfirmation, int userId, int[] sensorIds,
String opPackageName, boolean skipIntro, long operationId, long requestId,
@BiometricMultiSensorMode int multiSensorConfig,
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
@NonNull UserManager userManager,
@NonNull LockPatternUtils lockPatternUtils) {
@@ -1075,9 +1123,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
.setOperationId(operationId)
.setRequestId(requestId)
.setMultiSensorConfig(multiSensorConfig)
.setScaleFactorProvider(() -> {
return getScaleFactor();
})
.setScaleFactorProvider(() -> getScaleFactor())
.build(bgExecutor, sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle,
userManager, lockPatternUtils, mInteractionJankMonitor);
}
@@ -1086,8 +1132,14 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
final AuthDialog dialog = mCurrentDialog;
pw.println(" stableDisplaySize=" + mStableDisplaySize);
pw.println(" faceAuthSensorLocation=" + mFaceAuthSensorLocation);
pw.println(" fingerprintLocation=" + mFingerprintLocation);
pw.println(" mCachedDisplayInfo=" + mCachedDisplayInfo);
pw.println(" mScaleFactor=" + mScaleFactor);
pw.println(" faceAuthSensorLocationDefault=" + mFaceSensorLocationDefault);
pw.println(" faceAuthSensorLocation=" + getFaceSensorLocation());
pw.println(" fingerprintSensorLocationDefault=" + mFingerprintSensorLocationDefault);
pw.println(" fingerprintSensorLocationInNaturalOrientation="
+ getFingerprintSensorLocationInNaturalOrientation());
pw.println(" fingerprintSensorLocation=" + getFingerprintSensorLocation());
pw.println(" udfpsBounds=" + mUdfpsBounds);
pw.println(" allFingerprintAuthenticatorsRegistered="
+ mAllFingerprintAuthenticatorsRegistered);

View File

@@ -20,7 +20,7 @@ import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.PointF
import android.graphics.Point
import android.hardware.biometrics.BiometricFingerprintConstants
import android.hardware.biometrics.BiometricSourceType
import android.util.Log
@@ -79,8 +79,8 @@ class AuthRippleController @Inject constructor(
@VisibleForTesting
internal var startLightRevealScrimOnKeyguardFadingAway = false
var lightRevealScrimAnimator: ValueAnimator? = null
var fingerprintSensorLocation: PointF? = null
private var faceSensorLocation: PointF? = null
var fingerprintSensorLocation: Point? = null
private var faceSensorLocation: Point? = null
private var circleReveal: LightRevealEffect? = null
private var udfpsController: UdfpsController? = null
@@ -131,10 +131,10 @@ class AuthRippleController @Inject constructor(
circleReveal = CircleReveal(
it.x,
it.y,
0f,
0,
Math.max(
Math.max(it.x, centralSurfaces.displayWidth - it.x),
Math.max(it.y, centralSurfaces.displayHeight - it.y)
Math.max(it.x, centralSurfaces.displayWidth.toInt() - it.x),
Math.max(it.y, centralSurfaces.displayHeight.toInt() - it.y)
)
)
showUnlockedRipple()
@@ -148,10 +148,10 @@ class AuthRippleController @Inject constructor(
circleReveal = CircleReveal(
it.x,
it.y,
0f,
0,
Math.max(
Math.max(it.x, centralSurfaces.displayWidth - it.x),
Math.max(it.y, centralSurfaces.displayHeight - it.y)
Math.max(it.x, centralSurfaces.displayWidth.toInt() - it.x),
Math.max(it.y, centralSurfaces.displayHeight.toInt() - it.y)
)
)
showUnlockedRipple()
@@ -228,7 +228,7 @@ class AuthRippleController @Inject constructor(
fun updateSensorLocation() {
fingerprintSensorLocation = authController.fingerprintSensorLocation
faceSensorLocation = authController.faceAuthSensorLocation
faceSensorLocation = authController.faceSensorLocation
}
private fun updateRippleColor() {
@@ -362,9 +362,8 @@ class AuthRippleController @Inject constructor(
invalidCommand(pw)
return
}
pw.println("custom ripple sensorLocation=" + args[1].toFloat() + ", " +
args[2].toFloat())
mView.setSensorLocation(PointF(args[1].toFloat(), args[2].toFloat()))
pw.println("custom ripple sensorLocation=" + args[1] + ", " + args[2])
mView.setSensorLocation(Point(args[1].toInt(), args[2].toInt()))
showUnlockedRipple()
}
else -> invalidCommand(pw)

View File

@@ -23,7 +23,7 @@ import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import android.graphics.Point
import android.util.AttributeSet
import android.view.View
import android.view.animation.PathInterpolator
@@ -68,7 +68,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
dwellShader.maxRadius = value
field = value
}
private var dwellOrigin: PointF = PointF()
private var dwellOrigin: Point = Point()
set(value) {
dwellShader.origin = value
field = value
@@ -78,9 +78,9 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
rippleShader.setMaxSize(value * 2f, value * 2f)
field = value
}
private var origin: PointF = PointF()
private var origin: Point = Point()
set(value) {
rippleShader.setCenter(value.x, value.y)
rippleShader.setCenter(value.x.toFloat(), value.y.toFloat())
field = value
}
@@ -97,12 +97,12 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
visibility = GONE
}
fun setSensorLocation(location: PointF) {
fun setSensorLocation(location: Point) {
origin = location
radius = maxOf(location.x, location.y, width - location.x, height - location.y).toFloat()
}
fun setFingerprintSensorLocation(location: PointF, sensorRadius: Float) {
fun setFingerprintSensorLocation(location: Point, sensorRadius: Float) {
origin = location
radius = maxOf(location.x, location.y, width - location.x, height - location.y).toFloat()
dwellOrigin = location
@@ -349,13 +349,15 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
if (drawDwell) {
val maskRadius = (1 - (1 - dwellShader.progress) * (1 - dwellShader.progress) *
(1 - dwellShader.progress)) * dwellRadius * 2f
canvas?.drawCircle(dwellOrigin.x, dwellOrigin.y, maskRadius, dwellPaint)
canvas?.drawCircle(dwellOrigin.x.toFloat(), dwellOrigin.y.toFloat(),
maskRadius, dwellPaint)
}
if (drawRipple) {
val mask = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) *
(1 - rippleShader.progress)) * radius * 2f
canvas?.drawCircle(origin.x, origin.y, mask, ripplePaint)
canvas?.drawCircle(origin.x.toFloat(), origin.y.toFloat(),
mask, ripplePaint)
}
}
}

View File

@@ -16,7 +16,7 @@
package com.android.systemui.biometrics
import android.graphics.PointF
import android.graphics.Point
import android.graphics.RuntimeShader
import android.util.MathUtils
@@ -94,10 +94,10 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER) {
/**
* Origin coordinate of the ripple.
*/
var origin: PointF = PointF()
var origin: Point = Point()
set(value) {
field = value
setFloatUniform("in_origin", value.x, value.y)
setFloatUniform("in_origin", value.x.toFloat(), value.y.toFloat())
}
/**
@@ -107,7 +107,7 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER) {
set(value) {
field = value
setFloatUniform("in_radius",
(1 - (1 - value) * (1 - value) * (1 - value))* maxRadius)
(1 - (1 - value) * (1 - value) * (1 - value)) * maxRadius)
setFloatUniform("in_blur", MathUtils.lerp(1f, 0.7f, value))
}

View File

@@ -32,8 +32,8 @@ import android.widget.FrameLayout
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.FaceScanningOverlay
import com.android.systemui.biometrics.AuthController
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -55,7 +55,7 @@ class FaceScanningProviderFactory @Inject constructor(
override val hasProviders: Boolean
get() {
if (!featureFlags.isEnabled(Flags.FACE_SCANNING_ANIM) ||
authController.faceAuthSensorLocation == null) {
authController.faceSensorLocation == null) {
return false
}
@@ -159,7 +159,7 @@ class FaceScanningOverlayProviderImpl(
layoutParams.let { lp ->
lp.width = ViewGroup.LayoutParams.MATCH_PARENT
lp.height = ViewGroup.LayoutParams.MATCH_PARENT
authController.faceAuthSensorLocation?.y?.let { faceAuthSensorHeight ->
authController.faceSensorLocation?.y?.let { faceAuthSensorHeight ->
val faceScanningHeight = (faceAuthSensorHeight * 2).toInt()
when (rotation) {
Surface.ROTATION_0, Surface.ROTATION_180 ->

View File

@@ -143,13 +143,13 @@ class LinearLightRevealEffect(private val isVertical: Boolean) : LightRevealEffe
class CircleReveal(
/** X-value of the circle center of the reveal. */
val centerX: Float,
val centerX: Int,
/** Y-value of the circle center of the reveal. */
val centerY: Float,
val centerY: Int,
/** Radius of initial state of circle reveal */
val startRadius: Float,
val startRadius: Int,
/** Radius of end state of circle reveal */
val endRadius: Float
val endRadius: Int
) : LightRevealEffect {
override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
// reveal amount updates already have an interpolator, so we intentionally use the
@@ -350,7 +350,7 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context,
* This method does not call [invalidate] - you should do so once you're done changing
* properties.
*/
public fun setRevealGradientBounds(left: Float, top: Float, right: Float, bottom: Float) {
fun setRevealGradientBounds(left: Float, top: Float, right: Float, bottom: Float) {
revealGradientWidth = right - left
revealGradientHeight = bottom - top
@@ -387,4 +387,4 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context,
getColorWithAlpha(revealGradientEndColor, revealGradientEndColorAlpha),
PorterDuff.Mode.MULTIPLY)
}
}
}

View File

@@ -72,6 +72,8 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -685,13 +687,8 @@ public class AuthControllerTest extends SysuiTestCase {
}
@Test
public void testSubscribesToOrientationChangesWhenShowingDialog() {
showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
public void testSubscribesToOrientationChangesOnStart() {
verify(mDisplayManager).registerDisplayListener(any(), eq(mHandler), anyLong());
mAuthController.hideAuthenticationDialog(REQUEST_ID);
verify(mDisplayManager).unregisterDisplayListener(any());
}
@Test
@@ -736,7 +733,115 @@ public class AuthControllerTest extends SysuiTestCase {
order.verify(mContextListener).onDozeChanged(eq(true));
}
// Helpers
@Test
public void testGetFingerprintSensorLocationChanges_differentRotations() {
// GIVEN fp default location and mocked device dimensions
// Rotation 0, where "o" is the location of the FP sensor, if x or y = 0, it's the edge of
// the screen which is why a 1x1 width and height is represented by a 2x2 grid below:
// [* o]
// [* *]
Point fpDefaultLocation = new Point(1, 0);
final DisplayInfo displayInfo = new DisplayInfo();
displayInfo.logicalWidth = 1;
displayInfo.logicalHeight = 1;
// WHEN the rotation is 0, THEN no rotation applied
displayInfo.rotation = Surface.ROTATION_0;
assertEquals(
fpDefaultLocation,
mAuthController.rotateToCurrentOrientation(
new Point(fpDefaultLocation), displayInfo)
);
// WHEN the rotation is 270, THEN rotation is applied
// [* *]
// [* o]
displayInfo.rotation = Surface.ROTATION_270;
assertEquals(
new Point(1, 1),
mAuthController.rotateToCurrentOrientation(
new Point(fpDefaultLocation), displayInfo)
);
// WHEN the rotation is 180, THEN rotation is applied
// [* *]
// [o *]
displayInfo.rotation = Surface.ROTATION_180;
assertEquals(
new Point(0, 1),
mAuthController.rotateToCurrentOrientation(
new Point(fpDefaultLocation), displayInfo)
);
// WHEN the rotation is 90, THEN rotation is applied
// [o *]
// [* *]
displayInfo.rotation = Surface.ROTATION_90;
assertEquals(
new Point(0, 0),
mAuthController.rotateToCurrentOrientation(
new Point(fpDefaultLocation), displayInfo)
);
}
@Test
public void testGetFingerprintSensorLocationChanges_rotateRectangle() {
// GIVEN fp default location and mocked device dimensions
// Rotation 0, where "o" is the location of the FP sensor, if x or y = 0, it's the edge of
// the screen.
// [* * o *]
// [* * * *]
Point fpDefaultLocation = new Point(2, 0);
final DisplayInfo displayInfo = new DisplayInfo();
displayInfo.logicalWidth = 3;
displayInfo.logicalHeight = 1;
// WHEN the rotation is 0, THEN no rotation applied
displayInfo.rotation = Surface.ROTATION_0;
assertEquals(
fpDefaultLocation,
mAuthController.rotateToCurrentOrientation(
new Point(fpDefaultLocation), displayInfo)
);
// WHEN the rotation is 180, THEN rotation is applied
// [* * * *]
// [* o * *]
displayInfo.rotation = Surface.ROTATION_180;
assertEquals(
new Point(1, 1),
mAuthController.rotateToCurrentOrientation(
new Point(fpDefaultLocation), displayInfo)
);
// Rotation 270 & 90 have swapped logical width and heights
displayInfo.logicalWidth = 1;
displayInfo.logicalHeight = 3;
// WHEN the rotation is 270, THEN rotation is applied
// [* *]
// [* *]
// [* o]
// [* *]
displayInfo.rotation = Surface.ROTATION_270;
assertEquals(
new Point(1, 2),
mAuthController.rotateToCurrentOrientation(
new Point(fpDefaultLocation), displayInfo)
);
// WHEN the rotation is 90, THEN rotation is applied
// [* *]
// [o *]
// [* *]
// [* *]
displayInfo.rotation = Surface.ROTATION_90;
assertEquals(
new Point(0, 1),
mAuthController.rotateToCurrentOrientation(
new Point(fpDefaultLocation), displayInfo)
);
}
private void showDialog(int[] sensorIds, boolean credentialAllowed) {
mAuthController.showAuthenticationDialog(createTestPromptInfo(),

View File

@@ -16,7 +16,7 @@
package com.android.systemui.biometrics
import android.graphics.PointF
import android.graphics.Point
import android.hardware.biometrics.BiometricSourceType
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -31,11 +31,12 @@ import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.leak.RotationUtils
import javax.inject.Provider
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -45,15 +46,14 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.any
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
import javax.inject.Provider
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -116,7 +116,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFingerprintTrigger_KeyguardVisible_Ripple() {
// GIVEN fp exists, keyguard is visible, user doesn't need strong auth
val fpsLocation = PointF(5f, 5f)
val fpsLocation = Point(5, 5)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
@@ -139,7 +139,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFingerprintTrigger_Dreaming_Ripple() {
// GIVEN fp exists, keyguard is visible, user doesn't need strong auth
val fpsLocation = PointF(5f, 5f)
val fpsLocation = Point(5, 5)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(false)
@@ -162,7 +162,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFingerprintTrigger_KeyguardNotVisible_NotDreaming_NoRipple() {
// GIVEN fp exists & user doesn't need strong auth
val fpsLocation = PointF(5f, 5f)
val fpsLocation = Point(5, 5)
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
@@ -184,7 +184,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFingerprintTrigger_StrongAuthRequired_NoRipple() {
// GIVEN fp exists & keyguard is visible
val fpsLocation = PointF(5f, 5f)
val fpsLocation = Point(5, 5)
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
@@ -205,8 +205,8 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFaceTriggerBypassEnabled_Ripple() {
// GIVEN face auth sensor exists, keyguard is visible & strong auth isn't required
val faceLocation = PointF(5f, 5f)
`when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
val faceLocation = Point(5, 5)
`when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
@@ -229,8 +229,8 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFaceTriggerNonBypass_NoRipple() {
// GIVEN face auth sensor exists
val faceLocation = PointF(5f, 5f)
`when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
val faceLocation = Point(5, 5)
`when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
// WHEN bypass isn't enabled & face authenticated
@@ -248,7 +248,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testNullFaceSensorLocationDoesNothing() {
`when`(authController.faceAuthSensorLocation).thenReturn(null)
`when`(authController.faceSensorLocation).thenReturn(null)
controller.onViewAttached()
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
@@ -293,7 +293,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
@RunWithLooper(setAsMainLooper = true)
fun testAnimatorRunWhenWakeAndUnlock_fingerprint() {
val fpsLocation = PointF(5f, 5f)
val fpsLocation = Point(5, 5)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
@@ -311,8 +311,8 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
@RunWithLooper(setAsMainLooper = true)
fun testAnimatorRunWhenWakeAndUnlock_faceUdfpsFingerDown() {
val faceLocation = PointF(5f, 5f)
`when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
val faceLocation = Point(5, 5)
`when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)

View File

@@ -30,7 +30,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedStateListDrawable;
import android.hardware.biometrics.BiometricSourceType;
@@ -125,7 +125,7 @@ public class LockIconViewControllerTest extends SysuiTestCase {
ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
@Captor private ArgumentCaptor<PointF> mPointCaptor;
@Captor private ArgumentCaptor<Point> mPointCaptor;
@Before
public void setUp() throws Exception {
@@ -176,7 +176,7 @@ public class LockIconViewControllerTest extends SysuiTestCase {
@Test
public void testUpdateFingerprintLocationOnInit() {
// GIVEN fp sensor location is available pre-attached
Pair<Float, PointF> udfps = setupUdfps(); // first = radius, second = udfps location
Pair<Float, Point> udfps = setupUdfps(); // first = radius, second = udfps location
// WHEN lock icon view controller is initialized and attached
mLockIconViewController.init();
@@ -191,7 +191,7 @@ public class LockIconViewControllerTest extends SysuiTestCase {
@Test
public void testUpdatePaddingBasedOnResolutionScale() {
// GIVEN fp sensor location is available pre-attached & scaled resolution factor is 5
Pair<Float, PointF> udfps = setupUdfps(); // first = radius, second = udfps location
Pair<Float, Point> udfps = setupUdfps(); // first = radius, second = udfps location
when(mAuthController.getScaleFactor()).thenReturn(5f);
// WHEN lock icon view controller is initialized and attached
@@ -216,7 +216,7 @@ public class LockIconViewControllerTest extends SysuiTestCase {
// GIVEN fp sensor location is available post-attached
captureAuthControllerCallback();
Pair<Float, PointF> udfps = setupUdfps();
Pair<Float, Point> udfps = setupUdfps();
// WHEN all authenticators are registered
mAuthControllerCallback.onAllAuthenticatorsRegistered();
@@ -239,7 +239,7 @@ public class LockIconViewControllerTest extends SysuiTestCase {
// GIVEN fp sensor location is available post-attached
captureAuthControllerCallback();
Pair<Float, PointF> udfps = setupUdfps();
Pair<Float, Point> udfps = setupUdfps();
// WHEN udfps location changes
mAuthControllerCallback.onUdfpsLocationChanged();
@@ -419,9 +419,9 @@ public class LockIconViewControllerTest extends SysuiTestCase {
verify(mLockIconView).setTranslationX(0);
}
private Pair<Float, PointF> setupUdfps() {
private Pair<Float, Point> setupUdfps() {
when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true);
final PointF udfpsLocation = new PointF(50, 75);
final Point udfpsLocation = new Point(50, 75);
final float radius = 33f;
when(mAuthController.getUdfpsLocation()).thenReturn(udfpsLocation);
when(mAuthController.getUdfpsRadius()).thenReturn(radius);