1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.biometrics 18 19 import androidx.test.ext.junit.runners.AndroidJUnit4 20 import androidx.test.filters.SmallTest 21 import com.android.keyguard.logging.BiometricMessageDeferralLogger 22 import com.android.systemui.RoboPilotTest 23 import com.android.systemui.SysuiTestCase 24 import com.android.systemui.dump.DumpManager 25 import org.junit.Assert.assertEquals 26 import org.junit.Assert.assertFalse 27 import org.junit.Assert.assertNull 28 import org.junit.Assert.assertTrue 29 import org.junit.Before 30 import org.junit.Test 31 import org.junit.runner.RunWith 32 import org.mockito.Mock 33 import org.mockito.Mockito.verify 34 import org.mockito.MockitoAnnotations 35 36 @SmallTest 37 @RoboPilotTest 38 @RunWith(AndroidJUnit4::class) 39 class FaceHelpMessageDeferralTest : SysuiTestCase() { 40 val threshold = .75f 41 @Mock lateinit var logger: BiometricMessageDeferralLogger 42 @Mock lateinit var dumpManager: DumpManager 43 44 @Before 45 fun setUp() { 46 MockitoAnnotations.initMocks(this) 47 } 48 49 @Test 50 fun testProcessFrame_logs() { 51 val biometricMessageDeferral = createMsgDeferral(setOf(1)) 52 biometricMessageDeferral.processFrame(1) 53 verify(logger).logFrameProcessed(1, 1, "1") 54 } 55 56 @Test 57 fun testUpdateMessage_logs() { 58 val biometricMessageDeferral = createMsgDeferral(setOf(1)) 59 biometricMessageDeferral.updateMessage(1, "hi") 60 verify(logger).logUpdateMessage(1, "hi") 61 } 62 63 @Test 64 fun testReset_logs() { 65 val biometricMessageDeferral = createMsgDeferral(setOf(1)) 66 biometricMessageDeferral.reset() 67 verify(logger).reset() 68 } 69 70 @Test 71 fun testProcessNoMessages_noDeferredMessage() { 72 val biometricMessageDeferral = createMsgDeferral(emptySet()) 73 74 assertNull(biometricMessageDeferral.getDeferredMessage()) 75 } 76 77 @Test 78 fun testProcessNonDeferredMessages_noDeferredMessage() { 79 val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) 80 81 // WHEN there are no deferred messages processed 82 for (i in 0..3) { 83 biometricMessageDeferral.processFrame(4) 84 biometricMessageDeferral.updateMessage(4, "test") 85 } 86 87 // THEN getDeferredMessage is null 88 assertNull(biometricMessageDeferral.getDeferredMessage()) 89 } 90 91 @Test 92 fun testProcessMessagesWithDeferredMessage_deferredMessageWasNeverGivenAString() { 93 val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) 94 95 biometricMessageDeferral.processFrame(1) 96 97 assertNull(biometricMessageDeferral.getDeferredMessage()) 98 } 99 100 @Test 101 fun testAllProcessedMessagesWereDeferred() { 102 val biometricMessageDeferral = createMsgDeferral(setOf(1)) 103 104 // WHEN all the processed messages are a deferred message 105 for (i in 0..3) { 106 biometricMessageDeferral.processFrame(1) 107 biometricMessageDeferral.updateMessage(1, "test") 108 } 109 110 // THEN deferredMessage will return the string associated with the deferred msgId 111 assertEquals("test", biometricMessageDeferral.getDeferredMessage()) 112 } 113 114 @Test 115 fun testReturnsMostFrequentDeferredMessage() { 116 val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) 117 118 // WHEN there's 80%of the messages are msgId=1 and 20% is msgId=2 119 biometricMessageDeferral.processFrame(1) 120 biometricMessageDeferral.processFrame(1) 121 biometricMessageDeferral.processFrame(1) 122 biometricMessageDeferral.processFrame(1) 123 biometricMessageDeferral.updateMessage(1, "msgId-1") 124 125 biometricMessageDeferral.processFrame(2) 126 biometricMessageDeferral.updateMessage(2, "msgId-2") 127 128 // THEN the most frequent deferred message is that meets the threshold is returned 129 assertEquals("msgId-1", biometricMessageDeferral.getDeferredMessage()) 130 } 131 132 @Test 133 fun testDeferredMessage_mustMeetThreshold() { 134 val biometricMessageDeferral = createMsgDeferral(setOf(1)) 135 136 // WHEN more nonDeferredMessages are shown than the deferred message 137 val totalMessages = 10 138 val nonDeferredMessagesCount = (totalMessages * threshold).toInt() + 1 139 for (i in 0 until nonDeferredMessagesCount) { 140 biometricMessageDeferral.processFrame(4) 141 biometricMessageDeferral.updateMessage(4, "non-deferred-msg") 142 } 143 for (i in nonDeferredMessagesCount until totalMessages) { 144 biometricMessageDeferral.processFrame(1) 145 biometricMessageDeferral.updateMessage(1, "msgId-1") 146 } 147 148 // THEN there's no deferred message because it didn't meet the threshold 149 assertNull(biometricMessageDeferral.getDeferredMessage()) 150 } 151 152 @Test 153 fun testResetClearsOutCounts() { 154 val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) 155 156 // GIVEN two msgId=1 events processed 157 biometricMessageDeferral.processFrame( 158 1, 159 ) 160 biometricMessageDeferral.updateMessage(1, "msgId-1") 161 biometricMessageDeferral.processFrame(1) 162 biometricMessageDeferral.updateMessage(1, "msgId-1") 163 164 // WHEN counts are reset and then a single deferred message is processed (msgId=2) 165 biometricMessageDeferral.reset() 166 biometricMessageDeferral.processFrame(2) 167 biometricMessageDeferral.updateMessage(2, "msgId-2") 168 169 // THEN msgId-2 is the deferred message since the two msgId=1 events were reset 170 assertEquals("msgId-2", biometricMessageDeferral.getDeferredMessage()) 171 } 172 173 @Test 174 fun testShouldDefer() { 175 // GIVEN should defer msgIds 1 and 2 176 val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) 177 178 // THEN shouldDefer returns true for ids 1 & 2 179 assertTrue(biometricMessageDeferral.shouldDefer(1)) 180 assertTrue(biometricMessageDeferral.shouldDefer(2)) 181 182 // THEN should defer returns false for ids 3 & 4 183 assertFalse(biometricMessageDeferral.shouldDefer(3)) 184 assertFalse(biometricMessageDeferral.shouldDefer(4)) 185 } 186 187 @Test 188 fun testDeferredMessage_meetThresholdWithIgnoredFrames() { 189 val biometricMessageDeferral = 190 createMsgDeferral( 191 messagesToDefer = setOf(1), 192 acquiredInfoToIgnore = setOf(4), 193 ) 194 195 // WHEN more nonDeferredMessages are shown than the deferred message; HOWEVER the 196 // nonDeferredMessages are in acquiredInfoToIgnore 197 val totalMessages = 10 198 val nonDeferredMessagesCount = (totalMessages * threshold).toInt() + 1 199 for (i in 0 until nonDeferredMessagesCount) { 200 biometricMessageDeferral.processFrame(4) 201 biometricMessageDeferral.updateMessage(4, "non-deferred-msg") 202 } 203 for (i in nonDeferredMessagesCount until totalMessages) { 204 biometricMessageDeferral.processFrame(1) 205 biometricMessageDeferral.updateMessage(1, "msgId-1") 206 } 207 208 // THEN the deferred message met the threshold excluding the acquiredInfoToIgnore, 209 // so the message id deferred 210 assertTrue(biometricMessageDeferral.shouldDefer(1)) 211 assertEquals("msgId-1", biometricMessageDeferral.getDeferredMessage()) 212 } 213 214 private fun createMsgDeferral( 215 messagesToDefer: Set<Int>, 216 acquiredInfoToIgnore: Set<Int> = emptySet(), 217 ): BiometricMessageDeferral { 218 return BiometricMessageDeferral( 219 messagesToDefer, 220 acquiredInfoToIgnore, 221 threshold, 222 logger, 223 dumpManager, 224 ) 225 } 226 } 227