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

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

Merge "Create new UdfpsOverlay and UdfpsOverlayView"

parents 26b50d8f 9b96b6f5
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -792,7 +792,11 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
            mUdfpsBounds = udfpsProp.getLocation().getRect();
            mUdfpsBounds.scale(mScaleFactor);
            mUdfpsController.updateOverlayParams(udfpsProp.sensorId,
                    new UdfpsOverlayParams(mUdfpsBounds, mCachedDisplayInfo.getNaturalWidth(),
                    new UdfpsOverlayParams(mUdfpsBounds, new Rect(
                            0, mCachedDisplayInfo.getNaturalHeight() / 2,
                            mCachedDisplayInfo.getNaturalWidth(),
                            mCachedDisplayInfo.getNaturalHeight()),
                            mCachedDisplayInfo.getNaturalWidth(),
                            mCachedDisplayInfo.getNaturalHeight(), mScaleFactor,
                            mCachedDisplayInfo.rotation));
            if (!Objects.equals(previousUdfpsBounds, mUdfpsBounds)) {
+206 −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 com.android.systemui.biometrics

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.PixelFormat
import android.graphics.Rect
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback
import android.os.Handler
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.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.Execution
import java.util.*
import java.util.concurrent.Executor
import javax.inject.Inject

private const val TAG = "UdfpsOverlay"

@SuppressLint("ClickableViewAccessibility")
@SysUISingleton
class UdfpsOverlay
@Inject
constructor(
    private val context: Context,
    private val execution: Execution,
    private val windowManager: WindowManager,
    private val fingerprintManager: FingerprintManager?,
    private val handler: Handler,
    private val biometricExecutor: Executor,
    private val alternateTouchProvider: Optional<AlternateUdfpsTouchProvider>,
    private val fgExecutor: DelayableExecutor,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val authController: AuthController,
    private val udfpsLogger: UdfpsLogger
) : CoreStartable {

    /** The view, when [isShowing], or null. */
    var overlayView: UdfpsOverlayView? = null
        private set

    private var requestId: Long = 0
    private var onFingerDown = false
    val size = windowManager.maximumWindowMetrics.bounds
    val udfpsProps: MutableList<FingerprintSensorPropertiesInternal> = mutableListOf()

    private var params: UdfpsOverlayParams = UdfpsOverlayParams()

    private val coreLayoutParams =
        WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
                0 /* flags set in computeLayoutParams() */,
                PixelFormat.TRANSLUCENT
            )
            .apply {
                title = TAG
                fitInsetsTypes = 0
                gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT
                layoutInDisplayCutoutMode =
                    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
                flags = Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS
                privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
                // Avoid announcing window title.
                accessibilityTitle = " "
                inputFeatures = INPUT_FEATURE_SPY
            }

    fun onTouch(v: View, event: MotionEvent): Boolean {
        val view = v as UdfpsOverlayView

        return when (event.action) {
            MotionEvent.ACTION_DOWN,
            MotionEvent.ACTION_MOVE -> {
                onFingerDown = true
                if (!view.isDisplayConfigured && alternateTouchProvider.isPresent) {
                    biometricExecutor.execute {
                        alternateTouchProvider
                            .get()
                            .onPointerDown(
                                requestId,
                                event.x.toInt(),
                                event.y.toInt(),
                                event.touchMinor,
                                event.touchMajor
                            )
                    }
                    fgExecutor.execute {
                        if (keyguardUpdateMonitor.isFingerprintDetectionRunning) {
                            keyguardUpdateMonitor.onUdfpsPointerDown(requestId.toInt())
                        }
                    }

                    view.configureDisplay {
                        biometricExecutor.execute { alternateTouchProvider.get().onUiReady() }
                    }
                }

                true
            }
            MotionEvent.ACTION_UP,
            MotionEvent.ACTION_CANCEL -> {
                if (onFingerDown && alternateTouchProvider.isPresent) {
                    biometricExecutor.execute {
                        alternateTouchProvider.get().onPointerUp(requestId)
                    }
                    fgExecutor.execute {
                        if (keyguardUpdateMonitor.isFingerprintDetectionRunning) {
                            keyguardUpdateMonitor.onUdfpsPointerUp(requestId.toInt())
                        }
                    }
                }
                onFingerDown = false
                if (view.isDisplayConfigured) {
                    view.unconfigureDisplay()
                }

                true
            }
            else -> false
        }
    }

    fun show(requestId: Long): Boolean {
        this.requestId = requestId
        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) }
                overlayView = it
            }
            windowManager.addView(overlayView, coreLayoutParams)
            return true
        }

        return false
    }

    fun hide() {
        overlayView?.apply {
            windowManager.removeView(this)
            setOnTouchListener(null)
        }

        overlayView = null
    }

    @Override
    override fun start() {
        fingerprintManager?.addAuthenticatorsRegisteredCallback(
            object : IFingerprintAuthenticatorsRegisteredCallback.Stub() {
                override fun onAllAuthenticatorsRegistered(
                    sensors: List<FingerprintSensorPropertiesInternal>
                ) {
                    handler.post { handleAllFingerprintAuthenticatorsRegistered(sensors) }
                }
            }
        )
    }

    private fun handleAllFingerprintAuthenticatorsRegistered(
        sensors: List<FingerprintSensorPropertiesInternal>
    ) {
        for (props in sensors) {
            if (props.isAnyUdfpsType) {
                udfpsProps.add(props)
            }
        }

        // Setup param size
        if (udfpsProps.isNotEmpty()) {
            params =
                UdfpsOverlayParams(
                    sensorBounds = udfpsProps[0].location.rect,
                    overlayBounds = Rect(0, size.height() / 2, size.width(), size.height()),
                    naturalDisplayWidth = size.width(),
                    naturalDisplayHeight = size.height(),
                    scaleFactor = 1f
                )
        }
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.view.Surface.Rotation

data class UdfpsOverlayParams(
    val sensorBounds: Rect = Rect(),
    val overlayBounds: Rect = Rect(),
    val naturalDisplayWidth: Int = 0,
    val naturalDisplayHeight: Int = 0,
    val scaleFactor: Float = 1f,
+83 −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 com.android.systemui.biometrics

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.widget.FrameLayout

private const val TAG = "UdfpsOverlayView"

class UdfpsOverlayView(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {

    private val sensorRect = RectF()
    var overlayParams = UdfpsOverlayParams()
    private var mUdfpsDisplayMode: UdfpsDisplayMode? = null

    var overlayPaint = Paint()
    var sensorPaint = Paint()
    val centerPaint = Paint()

    /** True after the call to [configureDisplay] and before the call to [unconfigureDisplay]. */
    var isDisplayConfigured: Boolean = false
        private set

    init {
        this.setWillNotDraw(false)
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()

        overlayPaint.color = Color.argb(120, 255, 0, 0)
        overlayPaint.style = Paint.Style.FILL

        sensorPaint.color = Color.argb(150, 134, 204, 255)
        sensorPaint.style = Paint.Style.FILL
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        canvas.drawRect(overlayParams.overlayBounds, overlayPaint)
        canvas.drawRect(overlayParams.sensorBounds, sensorPaint)
        canvas.drawCircle(
            overlayParams.sensorBounds.exactCenterX(),
            overlayParams.sensorBounds.exactCenterY(),
            overlayParams.sensorBounds.width().toFloat() / 2,
            centerPaint
        )
    }

    fun setUdfpsDisplayMode(udfpsDisplayMode: UdfpsDisplayMode?) {
        mUdfpsDisplayMode = udfpsDisplayMode
    }

    fun configureDisplay(onDisplayConfigured: Runnable) {
        isDisplayConfigured = true
        mUdfpsDisplayMode?.enable(onDisplayConfigured)
    }

    fun unconfigureDisplay() {
        isDisplayConfigured = false
        mUdfpsDisplayMode?.disable(null /* onDisabled */)
    }
}
+23 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.biometrics

import android.content.Context
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER
@@ -23,9 +24,9 @@ import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTING
import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING
import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR
import android.hardware.biometrics.BiometricOverlayConstants.REASON_UNKNOWN
import android.hardware.fingerprint.IUdfpsOverlayController
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
import android.util.Log
import android.view.LayoutInflater
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
@@ -41,14 +42,17 @@ private const val SENSOR_ID = 0
 */
@SysUISingleton
class UdfpsShell @Inject constructor(
    commandRegistry: CommandRegistry
    commandRegistry: CommandRegistry,
    private val udfpsOverlay: UdfpsOverlay
) : Command {

    /**
     * Set in [UdfpsController.java] constructor, used to show and hide the UDFPS overlay.
     * TODO: inject after b/229290039 is resolved
     */
    var udfpsOverlayController: IUdfpsOverlayController? = null
    var udfpsOverlayController: UdfpsController.UdfpsOverlayController? = null
    var context: Context? = null
    var inflater: LayoutInflater? = null

    init {
        commandRegistry.registerCommand("udfps") { this }
@@ -57,6 +61,11 @@ class UdfpsShell @Inject constructor(
    override fun execute(pw: PrintWriter, args: List<String>) {
        if (args.size == 1 && args[0] == "hide") {
            hideOverlay()
        } else if (args.size == 2 && args[0] == "udfpsOverlay" && args[1] == "show") {
            hideOverlay()
            showUdfpsOverlay()
        } else if (args.size == 2 && args[0] == "udfpsOverlay" && args[1] == "hide") {
            hideUdfpsOverlay()
        } else if (args.size == 2 && args[0] == "show") {
            showOverlay(getEnrollmentReason(args[1]))
        } else {
@@ -104,6 +113,16 @@ class UdfpsShell @Inject constructor(
        )
    }

    private fun showUdfpsOverlay() {
        Log.v(TAG, "showUdfpsOverlay")
        udfpsOverlay.show(REQUEST_ID)
    }

    private fun hideUdfpsOverlay() {
        Log.v(TAG, "hideUdfpsOverlay")
        udfpsOverlay.hide()
    }

    private fun hideOverlay() {
        udfpsOverlayController?.hideUdfpsOverlay(SENSOR_ID)
    }
Loading