From 84c804e63cd60816260996dcffecf6aaf9a51c3d Mon Sep 17 00:00:00 2001 From: Chandru S Date: Thu, 30 Mar 2023 06:53:24 +0000 Subject: [PATCH] Enable face scanning animation when the biometric prompt is being shown Fixes: 272555697 Test: manually, Patched change enabling face strong auth and triggered biometric prompt Change-Id: Iebeb43d47956c5b0e70cb900392dc3b26da149b0 --- .../android/systemui/FaceScanningOverlay.kt | 6 +- .../decor/FaceScanningProviderFactory.kt | 4 +- .../FaceScanningProviderFactoryTest.kt | 119 ++++++++++++++++++ 3 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt index 179eb391af4ec..a3e7d71a92f6d 100644 --- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt @@ -35,6 +35,7 @@ import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.settingslib.Utils import com.android.systemui.animation.Interpolators +import com.android.systemui.biometrics.AuthController import com.android.systemui.log.ScreenDecorationsLogger import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.util.asIndenting @@ -52,6 +53,7 @@ class FaceScanningOverlay( val keyguardUpdateMonitor: KeyguardUpdateMonitor, val mainExecutor: Executor, val logger: ScreenDecorationsLogger, + val authController: AuthController, ) : ScreenDecorations.DisplayCutoutView(context, pos) { private var showScanningAnim = false private val rimPaint = Paint() @@ -102,7 +104,9 @@ class FaceScanningOverlay( } override fun enableShowProtection(show: Boolean) { - val showScanningAnimNow = keyguardUpdateMonitor.isFaceDetectionRunning && show + val animationRequired = + keyguardUpdateMonitor.isFaceDetectionRunning || authController.isShowing + val showScanningAnimNow = animationRequired && show if (showScanningAnimNow == showScanningAnim) { return } diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt index 88c0c50d09a53..4e62104034ee5 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt @@ -98,7 +98,8 @@ class FaceScanningProviderFactory @Inject constructor( } fun shouldShowFaceScanningAnim(): Boolean { - return canShowFaceScanningAnim() && keyguardUpdateMonitor.isFaceDetectionRunning + return canShowFaceScanningAnim() && + (keyguardUpdateMonitor.isFaceDetectionRunning || authController.isShowing) } } @@ -142,6 +143,7 @@ class FaceScanningOverlayProviderImpl( keyguardUpdateMonitor, mainExecutor, logger, + authController, ) view.id = viewId view.setColor(tintColor) diff --git a/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt new file mode 100644 index 0000000000000..01d3a39310522 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2023 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 + +import android.graphics.Point +import android.hardware.display.DisplayManagerGlobal +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import android.view.Display +import android.view.DisplayAdjustments +import android.view.DisplayInfo +import androidx.test.filters.SmallTest +import com.android.internal.R +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.biometrics.AuthController +import com.android.systemui.decor.FaceScanningProviderFactory +import com.android.systemui.dump.logcatLogBuffer +import com.android.systemui.log.ScreenDecorationsLogger +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import java.util.concurrent.Executor +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.mock +import org.mockito.MockitoAnnotations + +@RunWithLooper +@RunWith(AndroidTestingRunner::class) +@SmallTest +class FaceScanningProviderFactoryTest : SysuiTestCase() { + + private lateinit var underTest: FaceScanningProviderFactory + + @Mock private lateinit var authController: AuthController + + @Mock private lateinit var statusBarStateController: StatusBarStateController + + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor + + @Mock private lateinit var display: Display + + private val displayId = 2 + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + + val displayInfo = DisplayInfo() + val dmGlobal = mock(DisplayManagerGlobal::class.java) + val display = + Display( + dmGlobal, + displayId, + displayInfo, + DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS + ) + whenever(dmGlobal.getDisplayInfo(eq(displayId))).thenReturn(displayInfo) + val displayContext = context.createDisplayContext(display) as SysuiTestableContext + displayContext.orCreateTestableResources.addOverride( + R.array.config_displayUniqueIdArray, + arrayOf(displayId) + ) + displayContext.orCreateTestableResources.addOverride( + R.bool.config_fillMainBuiltInDisplayCutout, + true + ) + underTest = + FaceScanningProviderFactory( + authController, + displayContext, + statusBarStateController, + keyguardUpdateMonitor, + mock(Executor::class.java), + ScreenDecorationsLogger(logcatLogBuffer("FaceScanningProviderFactoryTest")) + ) + + whenever(authController.faceSensorLocation).thenReturn(Point(10, 10)) + } + + @Test + fun shouldNotShowFaceScanningAnimationIfFaceIsNotEnrolled() { + whenever(keyguardUpdateMonitor.isFaceEnrolled).thenReturn(false) + whenever(authController.isShowing).thenReturn(true) + + assertThat(underTest.shouldShowFaceScanningAnim()).isFalse() + } + + @Test + fun shouldShowFaceScanningAnimationIfBiometricPromptIsShowing() { + whenever(keyguardUpdateMonitor.isFaceEnrolled).thenReturn(true) + whenever(authController.isShowing).thenReturn(true) + + assertThat(underTest.shouldShowFaceScanningAnim()).isTrue() + } + + @Test + fun shouldShowFaceScanningAnimationIfKeyguardFaceDetectionIsShowing() { + whenever(keyguardUpdateMonitor.isFaceEnrolled).thenReturn(true) + whenever(keyguardUpdateMonitor.isFaceDetectionRunning).thenReturn(true) + + assertThat(underTest.shouldShowFaceScanningAnim()).isTrue() + } +}