/* * 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 androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.logging.BiometricMessageDeferralLogger import com.android.systemui.RoboPilotTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest @RoboPilotTest @RunWith(AndroidJUnit4::class) class FaceHelpMessageDeferralTest : SysuiTestCase() { val threshold = .75f @Mock lateinit var logger: BiometricMessageDeferralLogger @Mock lateinit var dumpManager: DumpManager @Before fun setUp() { MockitoAnnotations.initMocks(this) } @Test fun testProcessFrame_logs() { val biometricMessageDeferral = createMsgDeferral(setOf(1)) biometricMessageDeferral.processFrame(1) verify(logger).logFrameProcessed(1, 1, "1") } @Test fun testUpdateMessage_logs() { val biometricMessageDeferral = createMsgDeferral(setOf(1)) biometricMessageDeferral.updateMessage(1, "hi") verify(logger).logUpdateMessage(1, "hi") } @Test fun testReset_logs() { val biometricMessageDeferral = createMsgDeferral(setOf(1)) biometricMessageDeferral.reset() verify(logger).reset() } @Test fun testProcessNoMessages_noDeferredMessage() { val biometricMessageDeferral = createMsgDeferral(emptySet()) assertNull(biometricMessageDeferral.getDeferredMessage()) } @Test fun testProcessNonDeferredMessages_noDeferredMessage() { val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) // WHEN there are no deferred messages processed for (i in 0..3) { biometricMessageDeferral.processFrame(4) biometricMessageDeferral.updateMessage(4, "test") } // THEN getDeferredMessage is null assertNull(biometricMessageDeferral.getDeferredMessage()) } @Test fun testProcessMessagesWithDeferredMessage_deferredMessageWasNeverGivenAString() { val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) biometricMessageDeferral.processFrame(1) assertNull(biometricMessageDeferral.getDeferredMessage()) } @Test fun testAllProcessedMessagesWereDeferred() { val biometricMessageDeferral = createMsgDeferral(setOf(1)) // WHEN all the processed messages are a deferred message for (i in 0..3) { biometricMessageDeferral.processFrame(1) biometricMessageDeferral.updateMessage(1, "test") } // THEN deferredMessage will return the string associated with the deferred msgId assertEquals("test", biometricMessageDeferral.getDeferredMessage()) } @Test fun testReturnsMostFrequentDeferredMessage() { val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) // WHEN there's 80%of the messages are msgId=1 and 20% is msgId=2 biometricMessageDeferral.processFrame(1) biometricMessageDeferral.processFrame(1) biometricMessageDeferral.processFrame(1) biometricMessageDeferral.processFrame(1) biometricMessageDeferral.updateMessage(1, "msgId-1") biometricMessageDeferral.processFrame(2) biometricMessageDeferral.updateMessage(2, "msgId-2") // THEN the most frequent deferred message is that meets the threshold is returned assertEquals("msgId-1", biometricMessageDeferral.getDeferredMessage()) } @Test fun testDeferredMessage_mustMeetThreshold() { val biometricMessageDeferral = createMsgDeferral(setOf(1)) // WHEN more nonDeferredMessages are shown than the deferred message 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 there's no deferred message because it didn't meet the threshold assertNull(biometricMessageDeferral.getDeferredMessage()) } @Test fun testResetClearsOutCounts() { val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) // GIVEN two msgId=1 events processed biometricMessageDeferral.processFrame( 1, ) biometricMessageDeferral.updateMessage(1, "msgId-1") biometricMessageDeferral.processFrame(1) biometricMessageDeferral.updateMessage(1, "msgId-1") // WHEN counts are reset and then a single deferred message is processed (msgId=2) biometricMessageDeferral.reset() biometricMessageDeferral.processFrame(2) biometricMessageDeferral.updateMessage(2, "msgId-2") // THEN msgId-2 is the deferred message since the two msgId=1 events were reset assertEquals("msgId-2", biometricMessageDeferral.getDeferredMessage()) } @Test fun testShouldDefer() { // GIVEN should defer msgIds 1 and 2 val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) // THEN shouldDefer returns true for ids 1 & 2 assertTrue(biometricMessageDeferral.shouldDefer(1)) assertTrue(biometricMessageDeferral.shouldDefer(2)) // THEN should defer returns false for ids 3 & 4 assertFalse(biometricMessageDeferral.shouldDefer(3)) assertFalse(biometricMessageDeferral.shouldDefer(4)) } @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, acquiredInfoToIgnore: Set = emptySet(), ): BiometricMessageDeferral { return BiometricMessageDeferral( messagesToDefer, acquiredInfoToIgnore, threshold, logger, dumpManager, ) } }