Always send setIgnoreDisplayTouches from UdfpsOverlayInteractor

Previously, we ignored sending setIgnoreDisplayTouches when the state
tracked in UdfpsOverlayInteractor did not change. In rare cases, this
state becomes out of sync causing a setIgnoreDisplayTouches call to be
missed. Avoid this by always sending setIgnoreDisplayTouches.

Flag: EXEMPT bugfix
Bug: 379242441
Test: atest UdfpsOverlayInteractorTest
Change-Id: I01b7f8cba7f0bfc0de62511cc004fb66caa7eee1
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorTest.kt
index 4e64c50..297aee5c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorTest.kt
@@ -17,6 +17,8 @@
 package com.android.systemui.biometrics.domain.interactor
 
 import android.graphics.Rect
+import android.hardware.fingerprint.FingerprintManager
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
 import android.view.MotionEvent
 import android.view.Surface
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -24,6 +26,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.biometrics.authController
+import com.android.systemui.biometrics.fingerprintManager
 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.kosmos.testScope
@@ -39,6 +42,8 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyLong
+import org.mockito.ArgumentMatchers.eq
 import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito.verify
@@ -57,6 +62,8 @@
     private val testScope: TestScope = kosmos.testScope
 
     private val authController: AuthController = kosmos.authController
+    private val fingerprintManager: FingerprintManager = kosmos.fingerprintManager
+    @Mock private lateinit var fingerprintSensorProperties: FingerprintSensorPropertiesInternal
     @Captor private lateinit var authControllerCallback: ArgumentCaptor<AuthController.Callback>
 
     @Mock private lateinit var udfpsOverlayParams: UdfpsOverlayParams
@@ -122,6 +129,20 @@
             context.orCreateTestableResources.removeOverride(R.dimen.pixel_pitch)
         }
 
+    @Test
+    fun testSetIgnoreDisplayTouches() =
+        testScope.runTest {
+            createUdfpsOverlayInteractor()
+            whenever(authController.isUdfpsSupported).thenReturn(true)
+            whenever(authController.udfpsProps).thenReturn(listOf(fingerprintSensorProperties))
+
+            underTest.setHandleTouches(false)
+            verify(fingerprintManager).setIgnoreDisplayTouches(anyLong(), anyInt(), eq(true))
+
+            underTest.setHandleTouches(true)
+            verify(fingerprintManager).setIgnoreDisplayTouches(anyLong(), anyInt(), eq(false))
+        }
+
     private fun createUdfpsOverlayInteractor() {
         underTest = kosmos.udfpsOverlayInteractor
         testScope.runCurrent()
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt
index 9763295..8a5e011 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.res.R
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import javax.inject.Inject
+import kotlin.math.max
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
@@ -39,7 +40,6 @@
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
-import kotlin.math.max
 
 /** Encapsulates business logic for interacting with the UDFPS overlay. */
 @SysUISingleton
@@ -55,10 +55,7 @@
     private fun calculateIconSize(): Int {
         val pixelPitch = context.resources.getFloat(R.dimen.pixel_pitch)
         if (pixelPitch <= 0) {
-            Log.e(
-                "UdfpsOverlayInteractor",
-                "invalid pixelPitch: $pixelPitch. Pixel pitch must be updated per device.",
-            )
+            Log.e(TAG, "invalid pixelPitch: $pixelPitch. Pixel pitch must be updated per device.")
         }
         return (context.resources.getFloat(R.dimen.udfps_icon_size) / pixelPitch).toInt()
     }
@@ -84,13 +81,15 @@
     }
 
     /** Sets whether Udfps overlay should handle touches */
-    fun setHandleTouches(shouldHandle: Boolean = true) {
-        if (authController.isUdfpsSupported && shouldHandle != _shouldHandleTouches.value) {
+    fun setHandleTouches(shouldHandle: Boolean) {
+        if (authController.isUdfpsSupported) {
             fingerprintManager?.setIgnoreDisplayTouches(
                 requestId.value,
                 authController.udfpsProps!!.get(0).sensorId,
                 !shouldHandle,
             )
+        } else {
+            Log.d(TAG, "setIgnoreDisplayTouches not set, UDFPS not supported")
         }
         _shouldHandleTouches.value = shouldHandle
     }
@@ -123,12 +122,14 @@
 
     // Padding between the fingerprint icon and its bounding box in pixels.
     val iconPadding: Flow<Int> =
-        udfpsOverlayParams.map { params ->
-            val sensorWidth = params.nativeSensorBounds.right - params.nativeSensorBounds.left
-            val nativePadding = (sensorWidth - iconSize) / 2
-            // padding can be negative when udfpsOverlayParams has not been initialized yet.
-            max(0, (nativePadding * params.scaleFactor).toInt())
-        }.distinctUntilChanged()
+        udfpsOverlayParams
+            .map { params ->
+                val sensorWidth = params.nativeSensorBounds.right - params.nativeSensorBounds.left
+                val nativePadding = (sensorWidth - iconSize) / 2
+                // padding can be negative when udfpsOverlayParams has not been initialized yet.
+                max(0, (nativePadding * params.scaleFactor).toInt())
+            }
+            .distinctUntilChanged()
 
     companion object {
         private const val TAG = "UdfpsOverlayInteractor"
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/FingerprintManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/FingerprintManagerKosmos.kt
new file mode 100644
index 0000000..470a8e4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/FingerprintManagerKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 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.hardware.fingerprint.FingerprintManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+var Kosmos.fingerprintManager by Kosmos.Fixture { mock<FingerprintManager>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorKosmos.kt
index ae592b9..646c190 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorKosmos.kt
@@ -17,20 +17,19 @@
 package com.android.systemui.biometrics.domain.interactor
 
 import android.content.applicationContext
-import android.hardware.fingerprint.FingerprintManager
 import com.android.systemui.biometrics.authController
+import com.android.systemui.biometrics.fingerprintManager
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.user.domain.interactor.selectedUserInteractor
-import com.android.systemui.util.mockito.mock
 
 val Kosmos.udfpsOverlayInteractor by Fixture {
     UdfpsOverlayInteractor(
         context = applicationContext,
         authController = authController,
         selectedUserInteractor = selectedUserInteractor,
-        fingerprintManager = mock<FingerprintManager>(),
+        fingerprintManager = fingerprintManager,
         scope = applicationCoroutineScope,
     )
 }