Merge "Revert "Revert "Dismiss Auth Biometric Prompt when expanding shade""" into tm-dev
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
index 4cd40d2..2035781 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 @@
     statusBarStateController: StatusBarStateController,
     panelExpansionStateManager: PanelExpansionStateManager,
     systemUIDialogManager: SystemUIDialogManager,
+    val broadcastSender: BroadcastSender,
     dumpManager: DumpManager
 ) : UdfpsAnimationViewController<UdfpsBpView>(
     view,
@@ -37,4 +40,29 @@
     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 6fa7164..903b3de 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 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.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 @@
     @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 @@
                             mUnlockedScreenOffAnimationController, mHalControlsIllumination,
                             mHbmProvider, requestId, reason, callback,
                             (view, event, fromUdfpsView) -> onTouch(requestId, event,
-                                    fromUdfpsView), mActivityLaunchAnimator)));
+                                    fromUdfpsView), mActivityLaunchAnimator, mBroadcastSender)));
         }
 
         @Override
@@ -333,6 +338,20 @@
         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 @@
             @NonNull LatencyTracker latencyTracker,
             @NonNull ActivityLaunchAnimator activityLaunchAnimator,
             @NonNull Optional<AlternateUdfpsTouchProvider> aternateTouchProvider,
+            @NonNull BroadcastSender broadcastSender,
             @BiometricsBackground Executor biometricsExecutor) {
         mContext = context;
         mExecution = execution;
@@ -617,6 +637,7 @@
         mLatencyTracker = latencyTracker;
         mActivityLaunchAnimator = activityLaunchAnimator;
         mAlternateTouchProvider = aternateTouchProvider.orElse(null);
+        mBroadcastSender = broadcastSender;
         mBiometricExecutor = biometricsExecutor;
 
         mOrientationListener = new BiometricDisplayListener(
@@ -634,6 +655,11 @@
         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 ec72057..37db2bd 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 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 @@
     @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 @@
         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 @@
                     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 0000000..a52c4a3
--- /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 cb8358d..431739b 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.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 @@
     @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<WindowManager.LayoutParams>
 
     private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true }
@@ -131,7 +133,8 @@
             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 946c52e..e7e8e73 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.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 @@
     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<IUdfpsOverlayController> mOverlayCaptor;
@@ -267,6 +270,7 @@
                 mLatencyTracker,
                 mActivityLaunchAnimator,
                 Optional.of(mAlternateTouchProvider),
+                mBroadcastSender,
                 mBiometricsExecutor);
         verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
         mOverlayController = mOverlayCaptor.getValue();