From 7f6ff9092f2a4dd855bd9396953fcaa78d66fe98 Mon Sep 17 00:00:00 2001 From: Joe Bolinger Date: Fri, 29 Oct 2021 22:36:38 +0000 Subject: [PATCH] Do not show side fingerprint sensor overlay when used from settings. This is an alternative to ag/16124814 with the additional fix for udfps. Fix: 203789357 Test: atest SidefpsControllerTest Test: manual (open settings and verify no overlay shown with list of fingerprint) Test: manual (open settings and verify overlay shown during enrollment) Change-Id: Iee33cbb66d86d4f033d6acc9cf2284a3845f22de --- .../biometrics/BiometricOverlayConstants.java | 5 +- .../systemui/biometrics/SidefpsController.kt | 15 +++- .../systemui/biometrics/UdfpsController.java | 14 ++-- .../biometrics/SidefpsControllerTest.kt | 35 ++++++++-- .../biometrics/UdfpsControllerTest.java | 68 +++++++++++++++++-- .../sensors/AuthenticationClient.java | 6 ++ 6 files changed, 126 insertions(+), 17 deletions(-) diff --git a/core/java/android/hardware/biometrics/BiometricOverlayConstants.java b/core/java/android/hardware/biometrics/BiometricOverlayConstants.java index 603b06ddabaab..065ae64a92ad2 100644 --- a/core/java/android/hardware/biometrics/BiometricOverlayConstants.java +++ b/core/java/android/hardware/biometrics/BiometricOverlayConstants.java @@ -38,13 +38,16 @@ public interface BiometricOverlayConstants { int REASON_AUTH_KEYGUARD = 4; /** Non-specific usage (from FingerprintManager). */ int REASON_AUTH_OTHER = 5; + /** Usage from Settings. */ + int REASON_AUTH_SETTINGS = 6; @IntDef({REASON_UNKNOWN, REASON_ENROLL_FIND_SENSOR, REASON_ENROLL_ENROLLING, REASON_AUTH_BP, REASON_AUTH_KEYGUARD, - REASON_AUTH_OTHER}) + REASON_AUTH_OTHER, + REASON_AUTH_SETTINGS}) @Retention(RetentionPolicy.SOURCE) @interface ShowReason {} } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt index dacc169f85eeb..7bb4708443e93 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt @@ -17,6 +17,7 @@ package com.android.systemui.biometrics import android.animation.Animator import android.animation.AnimatorListenerAdapter +import android.app.ActivityTaskManager import android.content.Context import android.graphics.PixelFormat import android.graphics.PorterDuff @@ -24,6 +25,7 @@ import android.graphics.PorterDuffColorFilter import android.graphics.Rect import android.hardware.biometrics.BiometricOverlayConstants import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD +import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS import android.hardware.display.DisplayManager import android.hardware.fingerprint.FingerprintManager import android.hardware.fingerprint.FingerprintSensorPropertiesInternal @@ -61,6 +63,7 @@ class SidefpsController @Inject constructor( private val layoutInflater: LayoutInflater, fingerprintManager: FingerprintManager?, private val windowManager: WindowManager, + private val activityTaskManager: ActivityTaskManager, overviewProxyService: OverviewProxyService, displayManager: DisplayManager, @Main mainExecutor: DelayableExecutor, @@ -130,7 +133,7 @@ class SidefpsController @Inject constructor( override fun show( sensorId: Int, @BiometricOverlayConstants.ShowReason reason: Int - ) = if (reason.isReasonToShow()) doShow() else hide(sensorId) + ) = if (reason.isReasonToShow(activityTaskManager)) doShow() else hide(sensorId) private fun doShow() = mainExecutor.execute { if (overlayView == null) { @@ -228,11 +231,19 @@ class SidefpsController @Inject constructor( } @BiometricOverlayConstants.ShowReason -private fun Int.isReasonToShow(): Boolean = when (this) { +private fun Int.isReasonToShow(activityTaskManager: ActivityTaskManager): Boolean = when (this) { REASON_AUTH_KEYGUARD -> false + REASON_AUTH_SETTINGS -> when (activityTaskManager.topClass()) { + // TODO(b/186176653): exclude fingerprint overlays from this list view + "com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false + else -> true + } else -> true } +private fun ActivityTaskManager.topClass(): String = + getTasks(1).firstOrNull()?.topActivity?.className ?: "" + @RawRes private fun Display.asSideFpsAnimation(): Int = when (rotation) { Surface.ROTATION_0 -> R.raw.sfps_pulse diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 81a4d590aec6c..eb36915f97530 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -760,10 +760,12 @@ public class UdfpsController implements DozeReceiver { mOnFingerDown = false; mView.setSensorProperties(mSensorProps); mView.setHbmProvider(mHbmProvider); - UdfpsAnimationViewController animation = inflateUdfpsAnimation(reason); + UdfpsAnimationViewController animation = inflateUdfpsAnimation(reason); mAttemptedToDismissKeyguard = false; - animation.init(); - mView.setAnimationViewController(animation); + if (animation != null) { + animation.init(); + mView.setAnimationViewController(animation); + } mOrientationListener.enable(); // This view overlaps the sensor area, so prevent it from being selectable @@ -786,7 +788,8 @@ public class UdfpsController implements DozeReceiver { } } - private UdfpsAnimationViewController inflateUdfpsAnimation(int reason) { + @Nullable + private UdfpsAnimationViewController inflateUdfpsAnimation(int reason) { switch (reason) { case BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR: case BiometricOverlayConstants.REASON_ENROLL_ENROLLING: @@ -830,6 +833,7 @@ public class UdfpsController implements DozeReceiver { mDumpManager ); case BiometricOverlayConstants.REASON_AUTH_OTHER: + case BiometricOverlayConstants.REASON_AUTH_SETTINGS: UdfpsFpmOtherView authOtherView = (UdfpsFpmOtherView) mInflater.inflate(R.layout.udfps_fpm_other_view, null); mView.addView(authOtherView); @@ -840,7 +844,7 @@ public class UdfpsController implements DozeReceiver { mDumpManager ); default: - Log.d(TAG, "Animation for reason " + reason + " not supported yet"); + Log.e(TAG, "Animation for reason " + reason + " not supported yet"); return null; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt index c98a504b87848..2d510923b942a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt @@ -18,8 +18,12 @@ package com.android.systemui.biometrics import android.animation.Animator import android.graphics.Insets +import android.app.ActivityManager +import android.app.ActivityTaskManager +import android.content.ComponentName import android.graphics.Rect import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD +import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS import android.hardware.biometrics.BiometricOverlayConstants.REASON_UNKNOWN import android.hardware.biometrics.SensorProperties import android.hardware.display.DisplayManager @@ -60,9 +64,11 @@ import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.anyFloat import org.mockito.Mockito.anyLong +import org.mockito.Mockito.anyInt import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.reset +import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit @@ -84,6 +90,8 @@ class SidefpsControllerTest : SysuiTestCase() { @Mock lateinit var windowManager: WindowManager @Mock + lateinit var activityTaskManager: ActivityTaskManager + @Mock lateinit var sidefpsView: View @Mock lateinit var displayManager: DisplayManager @@ -144,7 +152,8 @@ class SidefpsControllerTest : SysuiTestCase() { sideFpsController = SidefpsController( context.createDisplayContext(display), layoutInflater, fingerprintManager, - windowManager, overviewProxyService, displayManager, executor, handler + windowManager, activityTaskManager, overviewProxyService, displayManager, executor, + handler ) overlayController = ArgumentCaptor.forClass(ISidefpsController::class.java).apply { @@ -211,12 +220,23 @@ class SidefpsControllerTest : SysuiTestCase() { testIgnoredFor(REASON_AUTH_KEYGUARD) } - private fun testIgnoredFor(reason: Int) { - overlayController.show(SENSOR_ID, reason) + @Test + fun testShowsForMostSettings() = testWithDisplay { + `when`(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpEnrollTask())) + testIgnoredFor(REASON_AUTH_SETTINGS, ignored = false) + } + @Test + fun testIgnoredForVerySpecificSettings() = testWithDisplay { + `when`(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpSettingsTask())) + testIgnoredFor(REASON_AUTH_SETTINGS) + } + + private fun testIgnoredFor(reason: Int, ignored: Boolean = true) { + overlayController.show(SENSOR_ID, reason) executor.runAllReady() - verify(windowManager, never()).addView(any(), any()) + verify(windowManager, if (ignored) never() else times(1)).addView(any(), any()) } @Test @@ -267,4 +287,9 @@ private fun insetsForSmallNavbar() = insetsWithBottom(60) private fun insetsForLargeNavbar() = insetsWithBottom(100) private fun insetsWithBottom(bottom: Int) = WindowInsets.Builder() .setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom)) - .build() \ No newline at end of file + .build() +private fun fpEnrollTask() = settingsTask(".biometrics.fingerprint.FingerprintEnrollEnrolling") +private fun fpSettingsTask() = settingsTask(".biometrics.fingerprint.FingerprintSettings") +private fun settingsTask(cls: String) = ActivityManager.RunningTaskInfo().apply { + topActivity = ComponentName.createRelative("com.android.settings", cls) +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index cfac9cb592a07..d90eb73a1595f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -405,15 +405,75 @@ public class UdfpsControllerTest extends SysuiTestCase { } @Test - public void showUdfpsOverlay_addsViewToWindow() throws RemoteException { - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, - BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); + public void showUdfpsOverlay_addsViewToWindow_bp() throws RemoteException { + showUdfpsOverlay_addsViewToWindow(BiometricOverlayConstants.REASON_AUTH_BP); + } + + @Test + public void showUdfpsOverlay_addsViewToWindow_keyguard() throws RemoteException { + showUdfpsOverlay_addsViewToWindow(BiometricOverlayConstants.REASON_AUTH_KEYGUARD); + } + + @Test + public void showUdfpsOverlay_addsViewToWindow_settings() throws RemoteException { + showUdfpsOverlay_addsViewToWindow(BiometricOverlayConstants.REASON_AUTH_SETTINGS); + } + + @Test + public void showUdfpsOverlay_addsViewToWindow_enroll_locate() throws RemoteException { + showUdfpsOverlay_addsViewToWindow(BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR); + } + + @Test + public void showUdfpsOverlay_addsViewToWindow_enroll() throws RemoteException { + showUdfpsOverlay_addsViewToWindow(BiometricOverlayConstants.REASON_ENROLL_ENROLLING); + } + + @Test + public void showUdfpsOverlay_addsViewToWindow_other() throws RemoteException { + showUdfpsOverlay_addsViewToWindow(BiometricOverlayConstants.REASON_AUTH_OTHER); + } + + private void showUdfpsOverlay_addsViewToWindow( + @BiometricOverlayConstants.ShowReason int reason) throws RemoteException { + mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, reason, + mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); verify(mWindowManager).addView(eq(mUdfpsView), any()); } @Test - public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException { + public void hideUdfpsOverlay_removesViewFromWindow_bp() throws RemoteException { + hideUdfpsOverlay_removesViewFromWindow(BiometricOverlayConstants.REASON_AUTH_BP); + } + + @Test + public void hideUdfpsOverlay_removesViewFromWindow_keyguard() throws RemoteException { + hideUdfpsOverlay_removesViewFromWindow(BiometricOverlayConstants.REASON_AUTH_KEYGUARD); + } + + @Test + public void hideUdfpsOverlay_removesViewFromWindow_settings() throws RemoteException { + hideUdfpsOverlay_removesViewFromWindow(BiometricOverlayConstants.REASON_AUTH_SETTINGS); + } + + @Test + public void hideUdfpsOverlay_removesViewFromWindow_enroll_locate() throws RemoteException { + hideUdfpsOverlay_removesViewFromWindow(BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR); + } + + @Test + public void hideUdfpsOverlay_removesViewFromWindow_enroll() throws RemoteException { + hideUdfpsOverlay_removesViewFromWindow(BiometricOverlayConstants.REASON_ENROLL_ENROLLING); + } + + @Test + public void hideUdfpsOverlay_removesViewFromWindow_other() throws RemoteException { + hideUdfpsOverlay_removesViewFromWindow(BiometricOverlayConstants.REASON_AUTH_OTHER); + } + + private void hideUdfpsOverlay_removesViewFromWindow( + @BiometricOverlayConstants.ShowReason int reason) throws RemoteException { mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID); diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java index 031f6eeeca5fa..61b8ded60db72 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -168,6 +168,10 @@ public abstract class AuthenticationClient extends AcquisitionClient return Utils.isKeyguard(getContext(), getOwnerString()); } + private boolean isSettings() { + return Utils.isSettings(getContext(), getOwnerString()); + } + @Override protected boolean isCryptoOperation() { return mOperationId != 0; @@ -499,6 +503,8 @@ public abstract class AuthenticationClient extends AcquisitionClient protected int getShowOverlayReason() { if (isKeyguard()) { return BiometricOverlayConstants.REASON_AUTH_KEYGUARD; + } else if (isSettings()) { + return BiometricOverlayConstants.REASON_AUTH_SETTINGS; } else if (isBiometricPrompt()) { return BiometricOverlayConstants.REASON_AUTH_BP; } else {