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

Commit 4482bbd7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Check orientation when retrieving FP location" into tm-qpr-dev am: 81b568b5

parents ec672423 81b568b5
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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;
+4 −3
Original line number Diff line number Diff line
@@ -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);
        }
    }
+135 −83
Original line number Diff line number Diff line
@@ -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 mScaleFactor;
    }
        return mUdfpsController.mOverlayParams.getScaleFactor();

    /**
     * Updates the current display info and cached scale factor & sensor locations.
     * Getting the display info is a relatively expensive call, so avoid superfluous calls.
     */
    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 portrait mode. devices without an
     * overridden value will use the default value even if they don't have a fingerprint sensor
     * @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 public PointF getFingerprintSensorLocation() {
    @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;
    }
        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);

    private void updateFingerprintLocation() {
        if (mFpProps == null) {
            mFingerprintSensorLocation = null;
        } else {
            mFingerprintSensorLocation = rotateToCurrentOrientation(
                    getFingerprintSensorLocationInNaturalOrientation(),
                    mCachedDisplayInfo);
        }
        return new PointF(mFaceAuthSensorLocation.x * scaleFactor,
                mFaceAuthSensorLocation.y * scaleFactor);
    }

    /**
     * @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
            );
        }
    }

    /**
     * @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);
+12 −13
Original line number Diff line number Diff line
@@ -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)
+10 −8
Original line number Diff line number Diff line
@@ -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)
        }
    }
}
Loading