Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +23 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUAR import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR import android.hardware.biometrics.BiometricRequestConstants.RequestReason import android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC import android.hardware.fingerprint.IUdfpsOverlayControllerCallback import android.os.Build import android.os.RemoteException Loading Loading @@ -148,6 +149,12 @@ constructor( return show(params, null) } private fun setHandleTouchesDisregardingUdfpsOverlayViewLifecycle(): Boolean { return requestReason == REASON_AUTH_KEYGUARD && com.android.systemui.Flags.newDozingKeyguardStates() && overlayParams.sensorType == TYPE_UDFPS_ULTRASONIC } /** Show the overlay or return false and do nothing if it is already showing. */ @SuppressLint("ClickableViewAccessibility") fun show(params: UdfpsOverlayParams, attachListener: OnAttachStateChangeListener?): Boolean { Loading @@ -155,6 +162,15 @@ constructor( overlayParams = params overlayAttachStateListener = attachListener sensorBounds = Rect(params.sensorBounds) val isSetHandleTouchesOutsideOfUdfpsViewLifecycle = setHandleTouchesDisregardingUdfpsOverlayViewLifecycle() if (isSetHandleTouchesOutsideOfUdfpsViewLifecycle) { // doesn't use the overlayTouchView to handle the lifecycle of forwarding // shouldHandleTouches to the HAL udfpsOverlayInteractor.updateSetHandleTouchesForKeyguard( deviceEntryUdfpsTouchOverlayViewModel.get() ) } try { overlayTouchView = (inflater.inflate(R.layout.udfps_touch_overlay, null, false) Loading @@ -173,7 +189,12 @@ constructor( UdfpsTouchOverlayBinder.bind( view = this, viewModel = deviceEntryUdfpsTouchOverlayViewModel.get(), udfpsOverlayInteractor = udfpsOverlayInteractor, udfpsOverlayInteractor = if (isSetHandleTouchesOutsideOfUdfpsViewLifecycle) { null } else { udfpsOverlayInteractor }, ) REASON_AUTH_BP -> UdfpsTouchOverlayBinder.bind( Loading Loading @@ -263,7 +284,7 @@ constructor( fun hide(): Boolean { val wasShowing = isShowing Log.d(TAG, "hideUdfpsControllerOverlay wasShowing=$wasShowing") udfpsOverlayInteractor.stopSetHandleTouchesForKeyguard() udfpsDisplayModeProvider.disable(null) getTouchOverlay()?.apply { if (this.parent != null) { Loading packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt +29 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.util.Log import android.view.MotionEvent import com.android.systemui.biometrics.AuthController import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton Loading @@ -31,6 +32,7 @@ import com.android.systemui.user.domain.interactor.SelectedUserInteractor import javax.inject.Inject import kotlin.math.max import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -40,6 +42,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** Encapsulates business logic for interacting with the UDFPS overlay. */ @SysUISingleton Loading @@ -50,7 +53,7 @@ constructor( private val authController: AuthController, private val selectedUserInteractor: SelectedUserInteractor, private val fingerprintManager: FingerprintManager?, @Application scope: CoroutineScope, @Application private val scope: CoroutineScope, ) { private fun calculateIconSize(): Int { val pixelPitch = context.resources.getFloat(R.dimen.pixel_pitch) Loading Loading @@ -131,6 +134,31 @@ constructor( } .distinctUntilChanged() private var isUpdatingSetHandleTouchesForKeyguard: Job? = null fun stopSetHandleTouchesForKeyguard() { isUpdatingSetHandleTouchesForKeyguard?.cancel() isUpdatingSetHandleTouchesForKeyguard = null } fun updateSetHandleTouchesForKeyguard( deviceEntryUdfpsTouchOverlayViewModel: DeviceEntryUdfpsTouchOverlayViewModel ) { if (isUpdatingSetHandleTouchesForKeyguard == null) { isUpdatingSetHandleTouchesForKeyguard = scope.launch { deviceEntryUdfpsTouchOverlayViewModel.shouldHandleTouches.collect { Log.d("UdfpsOverlayInteractor", "update shouldHandleTouches=$it") setHandleTouches(it) } } isUpdatingSetHandleTouchesForKeyguard?.invokeOnCompletion { Log.d("UdfpsOverlayInteractor", "invokeOnCompletion shouldHandleTouches=false") setHandleTouches(false) } } } companion object { private const val TAG = "UdfpsOverlayInteractor" } Loading packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/UdfpsTouchOverlayBinder.kt +24 −15 Original line number Diff line number Diff line Loading @@ -20,43 +20,52 @@ import android.util.Log import androidx.core.view.isInvisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor import com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay import com.android.systemui.biometrics.ui.viewmodel.UdfpsTouchOverlayViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.app.tracing.coroutines.launchTraced as launch object UdfpsTouchOverlayBinder { /** * Updates visibility for the UdfpsTouchOverlay which controls whether the view will receive * touches or not. For some devices, this is instead handled by UdfpsOverlayInteractor, so this * viewBinder will send the information to the interactor. * Updates visibility for the UdfpsTouchOverlay. This controls whether the view will receive * touches or not. This is important for optical-UDFPS to receive the fingerprint-sensor touch * events. */ @JvmStatic fun bind( view: UdfpsTouchOverlay, viewModel: UdfpsTouchOverlayViewModel, udfpsOverlayInteractor: UdfpsOverlayInteractor, udfpsOverlayInteractor: UdfpsOverlayInteractor? = null, ) { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { viewModel.shouldHandleTouches.collect { shouldHandleTouches -> if (udfpsOverlayInteractor != null) { Log.d( "UdfpsTouchOverlayBinder", "[$view]: update shouldHandleTouches=$shouldHandleTouches", ) } else { Log.d( "UdfpsTouchOverlayBinder", "[$view]: update isVisible=$shouldHandleTouches", ) } view.isInvisible = !shouldHandleTouches udfpsOverlayInteractor.setHandleTouches(shouldHandleTouches) udfpsOverlayInteractor?.setHandleTouches(shouldHandleTouches) } } .invokeOnCompletion { if (udfpsOverlayInteractor != null) { Log.d( "UdfpsTouchOverlayBinder", "[$view-detached]: update shouldHandleTouches=false", ) udfpsOverlayInteractor.setHandleTouches(false) udfpsOverlayInteractor?.setHandleTouches(false) } } } } Loading Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +23 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUAR import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR import android.hardware.biometrics.BiometricRequestConstants.RequestReason import android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC import android.hardware.fingerprint.IUdfpsOverlayControllerCallback import android.os.Build import android.os.RemoteException Loading Loading @@ -148,6 +149,12 @@ constructor( return show(params, null) } private fun setHandleTouchesDisregardingUdfpsOverlayViewLifecycle(): Boolean { return requestReason == REASON_AUTH_KEYGUARD && com.android.systemui.Flags.newDozingKeyguardStates() && overlayParams.sensorType == TYPE_UDFPS_ULTRASONIC } /** Show the overlay or return false and do nothing if it is already showing. */ @SuppressLint("ClickableViewAccessibility") fun show(params: UdfpsOverlayParams, attachListener: OnAttachStateChangeListener?): Boolean { Loading @@ -155,6 +162,15 @@ constructor( overlayParams = params overlayAttachStateListener = attachListener sensorBounds = Rect(params.sensorBounds) val isSetHandleTouchesOutsideOfUdfpsViewLifecycle = setHandleTouchesDisregardingUdfpsOverlayViewLifecycle() if (isSetHandleTouchesOutsideOfUdfpsViewLifecycle) { // doesn't use the overlayTouchView to handle the lifecycle of forwarding // shouldHandleTouches to the HAL udfpsOverlayInteractor.updateSetHandleTouchesForKeyguard( deviceEntryUdfpsTouchOverlayViewModel.get() ) } try { overlayTouchView = (inflater.inflate(R.layout.udfps_touch_overlay, null, false) Loading @@ -173,7 +189,12 @@ constructor( UdfpsTouchOverlayBinder.bind( view = this, viewModel = deviceEntryUdfpsTouchOverlayViewModel.get(), udfpsOverlayInteractor = udfpsOverlayInteractor, udfpsOverlayInteractor = if (isSetHandleTouchesOutsideOfUdfpsViewLifecycle) { null } else { udfpsOverlayInteractor }, ) REASON_AUTH_BP -> UdfpsTouchOverlayBinder.bind( Loading Loading @@ -263,7 +284,7 @@ constructor( fun hide(): Boolean { val wasShowing = isShowing Log.d(TAG, "hideUdfpsControllerOverlay wasShowing=$wasShowing") udfpsOverlayInteractor.stopSetHandleTouchesForKeyguard() udfpsDisplayModeProvider.disable(null) getTouchOverlay()?.apply { if (this.parent != null) { Loading
packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt +29 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.util.Log import android.view.MotionEvent import com.android.systemui.biometrics.AuthController import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton Loading @@ -31,6 +32,7 @@ import com.android.systemui.user.domain.interactor.SelectedUserInteractor import javax.inject.Inject import kotlin.math.max import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -40,6 +42,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** Encapsulates business logic for interacting with the UDFPS overlay. */ @SysUISingleton Loading @@ -50,7 +53,7 @@ constructor( private val authController: AuthController, private val selectedUserInteractor: SelectedUserInteractor, private val fingerprintManager: FingerprintManager?, @Application scope: CoroutineScope, @Application private val scope: CoroutineScope, ) { private fun calculateIconSize(): Int { val pixelPitch = context.resources.getFloat(R.dimen.pixel_pitch) Loading Loading @@ -131,6 +134,31 @@ constructor( } .distinctUntilChanged() private var isUpdatingSetHandleTouchesForKeyguard: Job? = null fun stopSetHandleTouchesForKeyguard() { isUpdatingSetHandleTouchesForKeyguard?.cancel() isUpdatingSetHandleTouchesForKeyguard = null } fun updateSetHandleTouchesForKeyguard( deviceEntryUdfpsTouchOverlayViewModel: DeviceEntryUdfpsTouchOverlayViewModel ) { if (isUpdatingSetHandleTouchesForKeyguard == null) { isUpdatingSetHandleTouchesForKeyguard = scope.launch { deviceEntryUdfpsTouchOverlayViewModel.shouldHandleTouches.collect { Log.d("UdfpsOverlayInteractor", "update shouldHandleTouches=$it") setHandleTouches(it) } } isUpdatingSetHandleTouchesForKeyguard?.invokeOnCompletion { Log.d("UdfpsOverlayInteractor", "invokeOnCompletion shouldHandleTouches=false") setHandleTouches(false) } } } companion object { private const val TAG = "UdfpsOverlayInteractor" } Loading
packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/UdfpsTouchOverlayBinder.kt +24 −15 Original line number Diff line number Diff line Loading @@ -20,43 +20,52 @@ import android.util.Log import androidx.core.view.isInvisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor import com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay import com.android.systemui.biometrics.ui.viewmodel.UdfpsTouchOverlayViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.app.tracing.coroutines.launchTraced as launch object UdfpsTouchOverlayBinder { /** * Updates visibility for the UdfpsTouchOverlay which controls whether the view will receive * touches or not. For some devices, this is instead handled by UdfpsOverlayInteractor, so this * viewBinder will send the information to the interactor. * Updates visibility for the UdfpsTouchOverlay. This controls whether the view will receive * touches or not. This is important for optical-UDFPS to receive the fingerprint-sensor touch * events. */ @JvmStatic fun bind( view: UdfpsTouchOverlay, viewModel: UdfpsTouchOverlayViewModel, udfpsOverlayInteractor: UdfpsOverlayInteractor, udfpsOverlayInteractor: UdfpsOverlayInteractor? = null, ) { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { viewModel.shouldHandleTouches.collect { shouldHandleTouches -> if (udfpsOverlayInteractor != null) { Log.d( "UdfpsTouchOverlayBinder", "[$view]: update shouldHandleTouches=$shouldHandleTouches", ) } else { Log.d( "UdfpsTouchOverlayBinder", "[$view]: update isVisible=$shouldHandleTouches", ) } view.isInvisible = !shouldHandleTouches udfpsOverlayInteractor.setHandleTouches(shouldHandleTouches) udfpsOverlayInteractor?.setHandleTouches(shouldHandleTouches) } } .invokeOnCompletion { if (udfpsOverlayInteractor != null) { Log.d( "UdfpsTouchOverlayBinder", "[$view-detached]: update shouldHandleTouches=false", ) udfpsOverlayInteractor.setHandleTouches(false) udfpsOverlayInteractor?.setHandleTouches(false) } } } } Loading