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

Commit 0b55b6f3 authored by Austin Delgado's avatar Austin Delgado Committed by Android (Google) Code Review
Browse files

Merge "Add new UdfpsOverlay to SensorOverlays"

parents 66a14232 957309ae
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