Merge "Don't include all frames in the face help message deferral logic" into udc-qpr-dev
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4aad6e7..0deee34 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -657,6 +657,14 @@
     <integer-array name="config_face_help_msgs_defer_until_timeout">
     </integer-array>
 
+    <!-- Which face help messages to ignore when determining the % of frames that meet
+         config_face_help_msgs_defer_until_timeout_threshold -->
+    <integer-array name="config_face_help_msgs_ignore">
+        <item>20</item> <!-- FACE_ACQUIRED_START -->
+        <item>23</item> <!-- FACE_ACQUIRED_UNKNOWN -->
+        <item>24</item> <!-- FACE_ACQUIRED_FIRST_FRAME_RECEIVED -->
+    </integer-array>
+
     <!-- Percentage of face auth frames received required to show a deferred message at
          FACE_ERROR_TIMEOUT. See config_face_help_msgs_defer_until_timeout for messages
          that are deferred.-->
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt
index 54738c6..2d854d9 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt
@@ -49,6 +49,12 @@
         )
     }
 
+    fun logFrameIgnored(
+        acquiredInfo: Int,
+    ) {
+        logBuffer.log(tag, DEBUG, { int1 = acquiredInfo }, { "frameIgnored acquiredInfo=$int1" })
+    }
+
     fun logFrameProcessed(
         acquiredInfo: Int,
         totalFrames: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
index e16121d..320e362 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
 import java.io.PrintWriter
-import java.util.*
+import java.util.Objects
 import javax.inject.Inject
 
 /**
@@ -42,6 +42,7 @@
 ) :
     BiometricMessageDeferral(
         resources.getIntArray(R.array.config_face_help_msgs_defer_until_timeout).toHashSet(),
+        resources.getIntArray(R.array.config_face_help_msgs_ignore).toHashSet(),
         resources.getFloat(R.dimen.config_face_help_msgs_defer_until_timeout_threshold),
         logBuffer,
         dumpManager
@@ -50,10 +51,11 @@
 /**
  * @property messagesToDefer messages that shouldn't show immediately when received, but may be
  *   shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
- *   percentage of all passed acquired frames.
+ *   percentage of all acquired frames, excluding [acquiredInfoToIgnore].
  */
 open class BiometricMessageDeferral(
     private val messagesToDefer: Set<Int>,
+    private val acquiredInfoToIgnore: Set<Int>,
     private val threshold: Float,
     private val logBuffer: BiometricMessageDeferralLogger,
     dumpManager: DumpManager
@@ -98,12 +100,20 @@
         return messagesToDefer.contains(acquiredMsgId)
     }
 
-    /** Adds the acquiredInfo frame to the counts. We account for all frames. */
+    /**
+     * Adds the acquiredInfo frame to the counts. We account for frames not included in
+     * acquiredInfoToIgnore.
+     */
     fun processFrame(acquiredInfo: Int) {
         if (messagesToDefer.isEmpty()) {
             return
         }
 
+        if (acquiredInfoToIgnore.contains(acquiredInfo)) {
+            logBuffer.logFrameIgnored(acquiredInfo)
+            return
+        }
+
         totalFrames++
 
         val newAcquiredInfoCount = acquiredInfoToFrequency.getOrDefault(acquiredInfo, 0) + 1
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt
index ad9fc95..ab5d8bea5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt
@@ -184,7 +184,43 @@
         assertFalse(biometricMessageDeferral.shouldDefer(4))
     }
 
-    private fun createMsgDeferral(messagesToDefer: Set<Int>): BiometricMessageDeferral {
-        return BiometricMessageDeferral(messagesToDefer, threshold, logger, dumpManager)
+    @Test
+    fun testDeferredMessage_meetThresholdWithIgnoredFrames() {
+        val biometricMessageDeferral =
+            createMsgDeferral(
+                messagesToDefer = setOf(1),
+                acquiredInfoToIgnore = setOf(4),
+            )
+
+        // WHEN more nonDeferredMessages are shown than the deferred message; HOWEVER the
+        // nonDeferredMessages are in acquiredInfoToIgnore
+        val totalMessages = 10
+        val nonDeferredMessagesCount = (totalMessages * threshold).toInt() + 1
+        for (i in 0 until nonDeferredMessagesCount) {
+            biometricMessageDeferral.processFrame(4)
+            biometricMessageDeferral.updateMessage(4, "non-deferred-msg")
+        }
+        for (i in nonDeferredMessagesCount until totalMessages) {
+            biometricMessageDeferral.processFrame(1)
+            biometricMessageDeferral.updateMessage(1, "msgId-1")
+        }
+
+        // THEN the deferred message met the threshold excluding the acquiredInfoToIgnore,
+        // so the message id deferred
+        assertTrue(biometricMessageDeferral.shouldDefer(1))
+        assertEquals("msgId-1", biometricMessageDeferral.getDeferredMessage())
+    }
+
+    private fun createMsgDeferral(
+        messagesToDefer: Set<Int>,
+        acquiredInfoToIgnore: Set<Int> = emptySet(),
+    ): BiometricMessageDeferral {
+        return BiometricMessageDeferral(
+            messagesToDefer,
+            acquiredInfoToIgnore,
+            threshold,
+            logger,
+            dumpManager,
+        )
     }
 }