From 402c296f8c916194b275ce0273ba2039165a4153 Mon Sep 17 00:00:00 2001 From: Bill Lin Date: Thu, 9 Jun 2022 01:18:01 +0000 Subject: [PATCH] Revert "Revert "Dismiss Auth Biometric Prompt when expanding shade"" This reverts commit 8a2faaff8cc76abfdce6dc8252d9add5238b745d. Reason for revert: We should keep mBroadcastReceiver which is not belong to b/233820283 in previous revert Change-Id: I7ce226f6ba61f952a42bf336ac46004b5427ff5b --- .../biometrics/UdfpsBpViewController.kt | 28 +++++ .../systemui/biometrics/UdfpsController.java | 28 ++++- .../biometrics/UdfpsControllerOverlay.kt | 9 +- .../biometrics/UdfpsBpViewControllerTest.kt | 118 ++++++++++++++++++ .../biometrics/UdfpsControllerOverlayTest.kt | 5 +- .../biometrics/UdfpsControllerTest.java | 4 + 6 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt index 4cd40d2f186b3..2035781239994 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt @@ -15,9 +15,11 @@ */ package com.android.systemui.biometrics +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.phone.SystemUIDialogManager +import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager /** @@ -28,6 +30,7 @@ class UdfpsBpViewController( statusBarStateController: StatusBarStateController, panelExpansionStateManager: PanelExpansionStateManager, systemUIDialogManager: SystemUIDialogManager, + val broadcastSender: BroadcastSender, dumpManager: DumpManager ) : UdfpsAnimationViewController( view, @@ -37,4 +40,29 @@ class UdfpsBpViewController( dumpManager ) { override val tag = "UdfpsBpViewController" + private val bpPanelExpansionListener = PanelExpansionListener { event -> + // Notification shade can be expanded but not visible (fraction: 0.0), for example + // when a heads-up notification (HUN) is showing. + notificationShadeVisible = event.expanded && event.fraction > 0f + view.onExpansionChanged(event.fraction) + cancelAuth() + } + + fun cancelAuth() { + if (shouldPauseAuth()) { + broadcastSender.closeSystemDialogs() + } + } + + override fun onViewAttached() { + super.onViewAttached() + + panelExpansionStateManager.addExpansionListener(bpPanelExpansionListener) + } + + override fun onViewDetached() { + super.onViewDetached() + + panelExpansionStateManager.removeExpansionListener(bpPanelExpansionListener) + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 6fa71640ca5ac..903b3de0f4443 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -24,7 +24,10 @@ import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.graphics.Point; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.display.DisplayManager; @@ -51,6 +54,7 @@ import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.biometrics.dagger.BiometricsBackground; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeReceiver; @@ -124,6 +128,7 @@ public class UdfpsController implements DozeReceiver { @NonNull private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; @NonNull private final LatencyTracker mLatencyTracker; + @NonNull private final BroadcastSender mBroadcastSender; @VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener; @NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator; @@ -204,7 +209,7 @@ public class UdfpsController implements DozeReceiver { mUnlockedScreenOffAnimationController, mHalControlsIllumination, mHbmProvider, requestId, reason, callback, (view, event, fromUdfpsView) -> onTouch(requestId, event, - fromUdfpsView), mActivityLaunchAnimator))); + fromUdfpsView), mActivityLaunchAnimator, mBroadcastSender))); } @Override @@ -333,6 +338,20 @@ public class UdfpsController implements DozeReceiver { return velocity > 750f; } + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (mOverlay != null + && mOverlay.getRequestReason() != REASON_AUTH_KEYGUARD + && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { + Log.d(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received, mRequestReason: " + + mOverlay.getRequestReason()); + mOverlay.cancel(); + hideUdfpsOverlay(); + } + } + }; + /** * Forwards touches to the udfps controller / view */ @@ -587,6 +606,7 @@ public class UdfpsController implements DozeReceiver { @NonNull LatencyTracker latencyTracker, @NonNull ActivityLaunchAnimator activityLaunchAnimator, @NonNull Optional aternateTouchProvider, + @NonNull BroadcastSender broadcastSender, @BiometricsBackground Executor biometricsExecutor) { mContext = context; mExecution = execution; @@ -617,6 +637,7 @@ public class UdfpsController implements DozeReceiver { mLatencyTracker = latencyTracker; mActivityLaunchAnimator = activityLaunchAnimator; mAlternateTouchProvider = aternateTouchProvider.orElse(null); + mBroadcastSender = broadcastSender; mBiometricExecutor = biometricsExecutor; mOrientationListener = new BiometricDisplayListener( @@ -634,6 +655,11 @@ public class UdfpsController implements DozeReceiver { final UdfpsOverlayController mUdfpsOverlayController = new UdfpsOverlayController(); mFingerprintManager.setUdfpsOverlayController(mUdfpsOverlayController); + final IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + context.registerReceiver(mBroadcastReceiver, filter, + Context.RECEIVER_EXPORTED_UNAUDITED); + udfpsHapticsSimulator.setUdfpsController(this); udfpsShell.setUdfpsOverlayController(mUdfpsOverlayController); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt index ec720579fbee1..37db2bd51238c 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt @@ -41,6 +41,7 @@ import androidx.annotation.LayoutRes import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.LockscreenShadeTransitionController @@ -83,7 +84,8 @@ class UdfpsControllerOverlay( @ShowReason val requestReason: Int, private val controllerCallback: IUdfpsOverlayControllerCallback, private val onTouch: (View, MotionEvent, Boolean) -> Boolean, - private val activityLaunchAnimator: ActivityLaunchAnimator + private val activityLaunchAnimator: ActivityLaunchAnimator, + private val broadcastSender: BroadcastSender ) { /** The view, when [isShowing], or null. */ var overlayView: UdfpsView? = null @@ -102,8 +104,8 @@ class UdfpsControllerOverlay( fitInsetsTypes = 0 gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS - flags = - (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS or WindowManager.LayoutParams.FLAG_SPLIT_TOUCH) + flags = (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS + or WindowManager.LayoutParams.FLAG_SPLIT_TOUCH) privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY // Avoid announcing window title. accessibilityTitle = " " @@ -225,6 +227,7 @@ class UdfpsControllerOverlay( statusBarStateController, panelExpansionStateManager, dialogManager, + broadcastSender, dumpManager ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt new file mode 100644 index 0000000000000..a52c4a3978b44 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt @@ -0,0 +1,118 @@ +/* + * 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 android.app.Instrumentation +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.testing.ViewUtils +import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation +import com.android.internal.jank.InteractionJankMonitor +import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastSender +import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.StatusBarStateControllerImpl +import com.android.systemui.statusbar.phone.SystemUIDialogManager +import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager +import com.android.systemui.util.mockito.any +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.spy +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.junit.MockitoJUnit + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class UdfpsBpViewControllerTest : SysuiTestCase() { + + @JvmField @Rule var rule = MockitoJUnit.rule() + + @Mock lateinit var dumpManager: DumpManager + @Mock lateinit var systemUIDialogManager: SystemUIDialogManager + @Mock lateinit var broadcastSender: BroadcastSender + @Mock lateinit var interactionJankMonitor: InteractionJankMonitor + @Mock lateinit var panelExpansionStateManager: PanelExpansionStateManager + + private lateinit var instrumentation: Instrumentation + private lateinit var uiEventLogger: UiEventLoggerFake + private lateinit var udfpsBpView: UdfpsBpView + private lateinit var statusBarStateController: StatusBarStateControllerImpl + private lateinit var udfpsBpViewController: UdfpsBpViewController + + @Before + fun setup() { + instrumentation = getInstrumentation() + instrumentation.runOnMainSync { createUdfpsView() } + instrumentation.waitForIdleSync() + + uiEventLogger = UiEventLoggerFake() + statusBarStateController = + StatusBarStateControllerImpl(uiEventLogger, dumpManager, interactionJankMonitor) + udfpsBpViewController = UdfpsBpViewController( + udfpsBpView, + statusBarStateController, + panelExpansionStateManager, + systemUIDialogManager, + broadcastSender, + dumpManager) + udfpsBpViewController.init() + } + + @After + fun tearDown() { + if (udfpsBpViewController.isAttachedToWindow) { + instrumentation.runOnMainSync { ViewUtils.detachView(udfpsBpView) } + instrumentation.waitForIdleSync() + } + } + + private fun createUdfpsView() { + context.setTheme(R.style.Theme_AppCompat) + context.orCreateTestableResources.addOverride( + com.android.internal.R.integer.config_udfps_illumination_transition_ms, 0) + udfpsBpView = UdfpsBpView(context, null) + } + + @Test + fun addExpansionListener() { + instrumentation.runOnMainSync { ViewUtils.attachView(udfpsBpView) } + instrumentation.waitForIdleSync() + + // Both UdfpsBpViewController & UdfpsAnimationViewController add listener + verify(panelExpansionStateManager, times(2)).addExpansionListener(any()) + } + + @Test + fun removeExpansionListener() { + instrumentation.runOnMainSync { ViewUtils.attachView(udfpsBpView) } + instrumentation.waitForIdleSync() + instrumentation.runOnMainSync { ViewUtils.detachView(udfpsBpView) } + instrumentation.waitForIdleSync() + + // Both UdfpsBpViewController & UdfpsAnimationViewController remove listener + verify(panelExpansionStateManager, times(2)).removeExpansionListener(any()) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt index cb8358dd22ccf..431739b6187ab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt @@ -40,6 +40,7 @@ import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityLaunchAnimator +import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.LockscreenShadeTransitionController @@ -102,6 +103,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { @Mock private lateinit var udfpsView: UdfpsView @Mock private lateinit var udfpsEnrollView: UdfpsEnrollView @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator + @Mock private lateinit var broadcastSender: BroadcastSender @Captor private lateinit var layoutParamsCaptor: ArgumentCaptor private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true } @@ -131,7 +133,8 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { keyguardUpdateMonitor, dialogManager, dumpManager, transitionController, configurationController, systemClock, keyguardStateController, unlockedScreenOffAnimationController, HAL_CONTROLS_ILLUMINATION, hbmProvider, - REQUEST_ID, reason, controllerCallback, onTouch, activityLaunchAnimator) + REQUEST_ID, reason, controllerCallback, onTouch, activityLaunchAnimator, + broadcastSender) block() } 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 946c52e8ee5b8..e7e8e73c3bc1d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -66,6 +66,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.ActivityLaunchAnimator; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.plugins.FalsingManager; @@ -187,6 +188,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private ActivityLaunchAnimator mActivityLaunchAnimator; @Mock private AlternateUdfpsTouchProvider mAlternateTouchProvider; + @Mock + private BroadcastSender mBroadcastSender; // Capture listeners so that they can be used to send events @Captor private ArgumentCaptor mOverlayCaptor; @@ -267,6 +270,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mLatencyTracker, mActivityLaunchAnimator, Optional.of(mAlternateTouchProvider), + mBroadcastSender, mBiometricsExecutor); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue();