Loading core/java/android/hardware/fingerprint/FingerprintManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -918,6 +918,22 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } /** * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) public void setUdfpsOverlay(@NonNull IUdfpsOverlay controller) { if (mService == null) { Slog.w(TAG, "setUdfpsOverlay: no fingerprint service"); return; } try { mService.setUdfpsOverlay(controller); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Forwards BiometricStateListener to FingerprintService Loading core/java/android/hardware/fingerprint/IFingerprintService.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IUdfpsOverlayController; import android.hardware.fingerprint.ISidefpsController; import android.hardware.fingerprint.IUdfpsOverlay; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import java.util.List; Loading Loading @@ -201,6 +202,10 @@ interface IFingerprintService { @EnforcePermission("USE_BIOMETRIC_INTERNAL") void setSidefpsController(in ISidefpsController controller); // Sets the controller for managing the UDFPS overlay. @EnforcePermission("USE_BIOMETRIC_INTERNAL") void setUdfpsOverlay(in IUdfpsOverlay controller); // Registers BiometricStateListener. @EnforcePermission("USE_BIOMETRIC_INTERNAL") void registerBiometricStateListener(IBiometricStateListener listener); Loading core/java/android/hardware/fingerprint/IUdfpsOverlay.aidl 0 → 100644 +29 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.fingerprint; /** * Interface for interacting with the under-display fingerprint sensor (UDFPS) overlay. * @hide */ oneway interface IUdfpsOverlay { // Shows the overlay. void show(long requestId, int sensorId, int reason); // Hides the overlay. void hide(int sensorId); } packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +13 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ import com.android.systemui.dagger.SysUISingleton; 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.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; Loading Loading @@ -119,6 +121,7 @@ public class UdfpsController implements DozeReceiver { @NonNull private final SystemUIDialogManager mDialogManager; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @NonNull private final VibratorHelper mVibrator; @NonNull private final FeatureFlags mFeatureFlags; @NonNull private final FalsingManager mFalsingManager; @NonNull private final PowerManager mPowerManager; @NonNull private final AccessibilityManager mAccessibilityManager; Loading Loading @@ -202,6 +205,10 @@ public class UdfpsController implements DozeReceiver { @Override public void showUdfpsOverlay(long requestId, int sensorId, int reason, @NonNull IUdfpsOverlayControllerCallback callback) { if (mFeatureFlags.isEnabled(Flags.NEW_UDFPS_OVERLAY)) { return; } mFgExecutor.execute(() -> UdfpsController.this.showUdfpsOverlay( new UdfpsControllerOverlay(mContext, mFingerprintManager, mInflater, mWindowManager, mAccessibilityManager, mStatusBarStateController, Loading @@ -217,6 +224,10 @@ public class UdfpsController implements DozeReceiver { @Override public void hideUdfpsOverlay(int sensorId) { if (mFeatureFlags.isEnabled(Flags.NEW_UDFPS_OVERLAY)) { return; } mFgExecutor.execute(() -> { if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { // if we get here, we expect keyguardUpdateMonitor's fingerprintRunningState Loading Loading @@ -590,6 +601,7 @@ public class UdfpsController implements DozeReceiver { @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @NonNull DumpManager dumpManager, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, @NonNull FeatureFlags featureFlags, @NonNull FalsingManager falsingManager, @NonNull PowerManager powerManager, @NonNull AccessibilityManager accessibilityManager, Loading Loading @@ -625,6 +637,7 @@ public class UdfpsController implements DozeReceiver { mDumpManager = dumpManager; mDialogManager = dialogManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mFeatureFlags = featureFlags; mFalsingManager = falsingManager; mPowerManager = powerManager; mAccessibilityManager = accessibilityManager; Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlay.kt +98 −41 Original line number Diff line number Diff line Loading @@ -21,22 +21,25 @@ import android.content.Context import android.graphics.PixelFormat import android.graphics.Point import android.graphics.Rect import android.hardware.biometrics.BiometricOverlayConstants import android.hardware.fingerprint.FingerprintManager import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback import android.hardware.fingerprint.IUdfpsOverlay import android.os.Handler import android.provider.Settings import android.view.MotionEvent import android.view.View import android.view.WindowManager import android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.CoreStartable 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.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.Execution import java.util.* import java.util.Optional import java.util.concurrent.Executor import javax.inject.Inject import kotlin.math.cos Loading @@ -45,8 +48,10 @@ import kotlin.math.sin private const val TAG = "UdfpsOverlay" const val SETTING_OVERLAY_DEBUG = "udfps_overlay_debug" // Number of sensor points needed inside ellipse for good overlap private const val NEEDED_POINTS = 3 private const val NEEDED_POINTS = 2 @SuppressLint("ClickableViewAccessibility") @SysUISingleton Loading @@ -60,7 +65,7 @@ constructor( private val handler: Handler, private val biometricExecutor: Executor, private val alternateTouchProvider: Optional<AlternateUdfpsTouchProvider>, private val fgExecutor: DelayableExecutor, @Main private val fgExecutor: DelayableExecutor, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val authController: AuthController, private val udfpsLogger: UdfpsLogger, Loading @@ -74,9 +79,11 @@ constructor( private var requestId: Long = 0 private var onFingerDown = false val size = windowManager.maximumWindowMetrics.bounds val udfpsProps: MutableList<FingerprintSensorPropertiesInternal> = mutableListOf() var points: Array<Point> = emptyArray() var processedMotionEvent = false var isShowing = false private var params: UdfpsOverlayParams = UdfpsOverlayParams() Loading @@ -99,8 +106,8 @@ constructor( inputFeatures = INPUT_FEATURE_SPY } fun onTouch(v: View, event: MotionEvent): Boolean { val view = v as UdfpsOverlayView fun onTouch(event: MotionEvent): Boolean { val view = overlayView!! return when (event.action) { MotionEvent.ACTION_DOWN, Loading Loading @@ -132,10 +139,11 @@ constructor( if (keyguardUpdateMonitor.isFingerprintDetectionRunning) { keyguardUpdateMonitor.onUdfpsPointerDown(requestId.toInt()) } } view.configureDisplay { biometricExecutor.execute { alternateTouchProvider.get().onUiReady() } biometricExecutor.execute { alternateTouchProvider.get().onUiReady() } } processedMotionEvent = true Loading @@ -143,6 +151,7 @@ constructor( } view.invalidate() } true } MotionEvent.ACTION_UP, Loading Loading @@ -181,7 +190,7 @@ constructor( 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(0)(yE - // 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) Loading @@ -194,32 +203,67 @@ constructor( return result <= 1 } fun show(requestId: Long): Boolean { fun show(requestId: Long) { if (!featureFlags.isEnabled(Flags.NEW_UDFPS_OVERLAY)) { return } this.requestId = requestId fgExecutor.execute { if (overlayView == null && alternateTouchProvider.isPresent) { UdfpsOverlayView(context, null).let { it.overlayParams = params it.setUdfpsDisplayMode( UdfpsDisplayMode(context, execution, authController, udfpsLogger) ) it.setOnTouchListener { v, event -> onTouch(v, event) } it.setOnTouchListener { _, event -> onTouch(event) } it.sensorPoints = points it.debugOverlay = Settings.Global.getInt( context.contentResolver, SETTING_OVERLAY_DEBUG, 0 /* def */ ) != 0 overlayView = it } windowManager.addView(overlayView, coreLayoutParams) return true isShowing = true } } return false } fun hide() { if (!featureFlags.isEnabled(Flags.NEW_UDFPS_OVERLAY)) { return } fgExecutor.execute { if (overlayView != null && isShowing && alternateTouchProvider.isPresent) { if (processedMotionEvent) { biometricExecutor.execute { alternateTouchProvider.get().onPointerUp(requestId) } fgExecutor.execute { if (keyguardUpdateMonitor.isFingerprintDetectionRunning) { keyguardUpdateMonitor.onUdfpsPointerUp(requestId.toInt()) } } } if (overlayView!!.isDisplayConfigured) { overlayView!!.unconfigureDisplay() } overlayView?.apply { windowManager.removeView(this) setOnTouchListener(null) } isShowing = false overlayView = null processedMotionEvent = false } } } @Override Loading @@ -233,6 +277,18 @@ constructor( } } ) fingerprintManager?.setUdfpsOverlay( object : IUdfpsOverlay.Stub() { override fun show( requestId: Long, sensorId: Int, @BiometricOverlayConstants.ShowReason reason: Int ) = show(requestId) override fun hide(sensorId: Int) = hide() } ) } private fun handleAllFingerprintAuthenticatorsRegistered( Loading @@ -257,19 +313,20 @@ constructor( val sensorX = params.sensorBounds.centerX() val sensorY = params.sensorBounds.centerY() val gridOffset: Int = params.sensorBounds.width() / 3 val cornerOffset: Int = params.sensorBounds.width() / 4 val sideOffset: Int = params.sensorBounds.width() / 3 points = arrayOf( Point(sensorX - gridOffset, sensorY - gridOffset), Point(sensorX, sensorY - gridOffset), Point(sensorX + gridOffset, sensorY - gridOffset), Point(sensorX - gridOffset, sensorY), Point(sensorX - cornerOffset, sensorY - cornerOffset), Point(sensorX, sensorY - sideOffset), Point(sensorX + cornerOffset, sensorY - cornerOffset), Point(sensorX - sideOffset, sensorY), Point(sensorX, sensorY), Point(sensorX + gridOffset, sensorY), Point(sensorX - gridOffset, sensorY + gridOffset), Point(sensorX, sensorY + gridOffset), Point(sensorX + gridOffset, sensorY + gridOffset) Point(sensorX + sideOffset, sensorY), Point(sensorX - cornerOffset, sensorY + cornerOffset), Point(sensorX, sensorY + sideOffset), Point(sensorX + cornerOffset, sensorY + cornerOffset) ) } } Loading Loading
core/java/android/hardware/fingerprint/FingerprintManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -918,6 +918,22 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } /** * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) public void setUdfpsOverlay(@NonNull IUdfpsOverlay controller) { if (mService == null) { Slog.w(TAG, "setUdfpsOverlay: no fingerprint service"); return; } try { mService.setUdfpsOverlay(controller); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Forwards BiometricStateListener to FingerprintService Loading
core/java/android/hardware/fingerprint/IFingerprintService.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IUdfpsOverlayController; import android.hardware.fingerprint.ISidefpsController; import android.hardware.fingerprint.IUdfpsOverlay; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import java.util.List; Loading Loading @@ -201,6 +202,10 @@ interface IFingerprintService { @EnforcePermission("USE_BIOMETRIC_INTERNAL") void setSidefpsController(in ISidefpsController controller); // Sets the controller for managing the UDFPS overlay. @EnforcePermission("USE_BIOMETRIC_INTERNAL") void setUdfpsOverlay(in IUdfpsOverlay controller); // Registers BiometricStateListener. @EnforcePermission("USE_BIOMETRIC_INTERNAL") void registerBiometricStateListener(IBiometricStateListener listener); Loading
core/java/android/hardware/fingerprint/IUdfpsOverlay.aidl 0 → 100644 +29 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.fingerprint; /** * Interface for interacting with the under-display fingerprint sensor (UDFPS) overlay. * @hide */ oneway interface IUdfpsOverlay { // Shows the overlay. void show(long requestId, int sensorId, int reason); // Hides the overlay. void hide(int sensorId); }
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +13 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ import com.android.systemui.dagger.SysUISingleton; 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.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; Loading Loading @@ -119,6 +121,7 @@ public class UdfpsController implements DozeReceiver { @NonNull private final SystemUIDialogManager mDialogManager; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @NonNull private final VibratorHelper mVibrator; @NonNull private final FeatureFlags mFeatureFlags; @NonNull private final FalsingManager mFalsingManager; @NonNull private final PowerManager mPowerManager; @NonNull private final AccessibilityManager mAccessibilityManager; Loading Loading @@ -202,6 +205,10 @@ public class UdfpsController implements DozeReceiver { @Override public void showUdfpsOverlay(long requestId, int sensorId, int reason, @NonNull IUdfpsOverlayControllerCallback callback) { if (mFeatureFlags.isEnabled(Flags.NEW_UDFPS_OVERLAY)) { return; } mFgExecutor.execute(() -> UdfpsController.this.showUdfpsOverlay( new UdfpsControllerOverlay(mContext, mFingerprintManager, mInflater, mWindowManager, mAccessibilityManager, mStatusBarStateController, Loading @@ -217,6 +224,10 @@ public class UdfpsController implements DozeReceiver { @Override public void hideUdfpsOverlay(int sensorId) { if (mFeatureFlags.isEnabled(Flags.NEW_UDFPS_OVERLAY)) { return; } mFgExecutor.execute(() -> { if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { // if we get here, we expect keyguardUpdateMonitor's fingerprintRunningState Loading Loading @@ -590,6 +601,7 @@ public class UdfpsController implements DozeReceiver { @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @NonNull DumpManager dumpManager, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, @NonNull FeatureFlags featureFlags, @NonNull FalsingManager falsingManager, @NonNull PowerManager powerManager, @NonNull AccessibilityManager accessibilityManager, Loading Loading @@ -625,6 +637,7 @@ public class UdfpsController implements DozeReceiver { mDumpManager = dumpManager; mDialogManager = dialogManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mFeatureFlags = featureFlags; mFalsingManager = falsingManager; mPowerManager = powerManager; mAccessibilityManager = accessibilityManager; Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlay.kt +98 −41 Original line number Diff line number Diff line Loading @@ -21,22 +21,25 @@ import android.content.Context import android.graphics.PixelFormat import android.graphics.Point import android.graphics.Rect import android.hardware.biometrics.BiometricOverlayConstants import android.hardware.fingerprint.FingerprintManager import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback import android.hardware.fingerprint.IUdfpsOverlay import android.os.Handler import android.provider.Settings import android.view.MotionEvent import android.view.View import android.view.WindowManager import android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.CoreStartable 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.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.Execution import java.util.* import java.util.Optional import java.util.concurrent.Executor import javax.inject.Inject import kotlin.math.cos Loading @@ -45,8 +48,10 @@ import kotlin.math.sin private const val TAG = "UdfpsOverlay" const val SETTING_OVERLAY_DEBUG = "udfps_overlay_debug" // Number of sensor points needed inside ellipse for good overlap private const val NEEDED_POINTS = 3 private const val NEEDED_POINTS = 2 @SuppressLint("ClickableViewAccessibility") @SysUISingleton Loading @@ -60,7 +65,7 @@ constructor( private val handler: Handler, private val biometricExecutor: Executor, private val alternateTouchProvider: Optional<AlternateUdfpsTouchProvider>, private val fgExecutor: DelayableExecutor, @Main private val fgExecutor: DelayableExecutor, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val authController: AuthController, private val udfpsLogger: UdfpsLogger, Loading @@ -74,9 +79,11 @@ constructor( private var requestId: Long = 0 private var onFingerDown = false val size = windowManager.maximumWindowMetrics.bounds val udfpsProps: MutableList<FingerprintSensorPropertiesInternal> = mutableListOf() var points: Array<Point> = emptyArray() var processedMotionEvent = false var isShowing = false private var params: UdfpsOverlayParams = UdfpsOverlayParams() Loading @@ -99,8 +106,8 @@ constructor( inputFeatures = INPUT_FEATURE_SPY } fun onTouch(v: View, event: MotionEvent): Boolean { val view = v as UdfpsOverlayView fun onTouch(event: MotionEvent): Boolean { val view = overlayView!! return when (event.action) { MotionEvent.ACTION_DOWN, Loading Loading @@ -132,10 +139,11 @@ constructor( if (keyguardUpdateMonitor.isFingerprintDetectionRunning) { keyguardUpdateMonitor.onUdfpsPointerDown(requestId.toInt()) } } view.configureDisplay { biometricExecutor.execute { alternateTouchProvider.get().onUiReady() } biometricExecutor.execute { alternateTouchProvider.get().onUiReady() } } processedMotionEvent = true Loading @@ -143,6 +151,7 @@ constructor( } view.invalidate() } true } MotionEvent.ACTION_UP, Loading Loading @@ -181,7 +190,7 @@ constructor( 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(0)(yE - // 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) Loading @@ -194,32 +203,67 @@ constructor( return result <= 1 } fun show(requestId: Long): Boolean { fun show(requestId: Long) { if (!featureFlags.isEnabled(Flags.NEW_UDFPS_OVERLAY)) { return } this.requestId = requestId fgExecutor.execute { if (overlayView == null && alternateTouchProvider.isPresent) { UdfpsOverlayView(context, null).let { it.overlayParams = params it.setUdfpsDisplayMode( UdfpsDisplayMode(context, execution, authController, udfpsLogger) ) it.setOnTouchListener { v, event -> onTouch(v, event) } it.setOnTouchListener { _, event -> onTouch(event) } it.sensorPoints = points it.debugOverlay = Settings.Global.getInt( context.contentResolver, SETTING_OVERLAY_DEBUG, 0 /* def */ ) != 0 overlayView = it } windowManager.addView(overlayView, coreLayoutParams) return true isShowing = true } } return false } fun hide() { if (!featureFlags.isEnabled(Flags.NEW_UDFPS_OVERLAY)) { return } fgExecutor.execute { if (overlayView != null && isShowing && alternateTouchProvider.isPresent) { if (processedMotionEvent) { biometricExecutor.execute { alternateTouchProvider.get().onPointerUp(requestId) } fgExecutor.execute { if (keyguardUpdateMonitor.isFingerprintDetectionRunning) { keyguardUpdateMonitor.onUdfpsPointerUp(requestId.toInt()) } } } if (overlayView!!.isDisplayConfigured) { overlayView!!.unconfigureDisplay() } overlayView?.apply { windowManager.removeView(this) setOnTouchListener(null) } isShowing = false overlayView = null processedMotionEvent = false } } } @Override Loading @@ -233,6 +277,18 @@ constructor( } } ) fingerprintManager?.setUdfpsOverlay( object : IUdfpsOverlay.Stub() { override fun show( requestId: Long, sensorId: Int, @BiometricOverlayConstants.ShowReason reason: Int ) = show(requestId) override fun hide(sensorId: Int) = hide() } ) } private fun handleAllFingerprintAuthenticatorsRegistered( Loading @@ -257,19 +313,20 @@ constructor( val sensorX = params.sensorBounds.centerX() val sensorY = params.sensorBounds.centerY() val gridOffset: Int = params.sensorBounds.width() / 3 val cornerOffset: Int = params.sensorBounds.width() / 4 val sideOffset: Int = params.sensorBounds.width() / 3 points = arrayOf( Point(sensorX - gridOffset, sensorY - gridOffset), Point(sensorX, sensorY - gridOffset), Point(sensorX + gridOffset, sensorY - gridOffset), Point(sensorX - gridOffset, sensorY), Point(sensorX - cornerOffset, sensorY - cornerOffset), Point(sensorX, sensorY - sideOffset), Point(sensorX + cornerOffset, sensorY - cornerOffset), Point(sensorX - sideOffset, sensorY), Point(sensorX, sensorY), Point(sensorX + gridOffset, sensorY), Point(sensorX - gridOffset, sensorY + gridOffset), Point(sensorX, sensorY + gridOffset), Point(sensorX + gridOffset, sensorY + gridOffset) Point(sensorX + sideOffset, sensorY), Point(sensorX - cornerOffset, sensorY + cornerOffset), Point(sensorX, sensorY + sideOffset), Point(sensorX + cornerOffset, sensorY + cornerOffset) ) } } Loading