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

Commit 957309ae authored by Austin Delgado's avatar Austin Delgado
Browse files

Add new UdfpsOverlay to SensorOverlays

Test: N/A
Bug: 252897742
Change-Id: I8b652b4f28cf5e5802a3251e85a979472162d227
parent 3c84cada
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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);
+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);
}
+13 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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,
@@ -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
@@ -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,
@@ -625,6 +637,7 @@ public class UdfpsController implements DozeReceiver {
        mDumpManager = dumpManager;
        mDialogManager = dialogManager;
        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
        mFeatureFlags = featureFlags;
        mFalsingManager = falsingManager;
        mPowerManager = powerManager;
        mAccessibilityManager = accessibilityManager;
+98 −41
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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,
@@ -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()

@@ -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,
@@ -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
@@ -143,6 +151,7 @@ constructor(
                    }

                    view.invalidate()
                }
                true
            }
            MotionEvent.ACTION_UP,
@@ -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)
@@ -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
@@ -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(
@@ -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