Don't wakeup from the pickup gesture when kg is occluded

Also finish() wallet activity onStopped.
Consequently, the activity will always close on screen off.
For example, this includes when the activities are launched via
their lock screen affordances + qs tiles.

Fixes: 194925434
Test: manual, atest DozeTriggersTest
Test: atest UdfpsControllerTest UdfpsKeyguardViewControllerTest
Change-Id: I9856571e104ef05aec93d32056cd2097c2d2a1da
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index f22483a..b2f32bb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -39,7 +39,6 @@
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
 import android.media.AudioAttributes;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
@@ -63,7 +62,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.doze.DozeReceiver;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -71,6 +69,7 @@
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -115,9 +114,7 @@
     @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
     @NonNull private final DumpManager mDumpManager;
     @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    @NonNull private final KeyguardViewMediator mKeyguardViewMediator;
     @Nullable private final Vibrator mVibrator;
-    @NonNull private final Handler mMainHandler;
     @NonNull private final FalsingManager mFalsingManager;
     @NonNull private final PowerManager mPowerManager;
     @NonNull private final AccessibilityManager mAccessibilityManager;
@@ -126,6 +123,8 @@
     @NonNull private final KeyguardBypassController mKeyguardBypassController;
     @NonNull private final ConfigurationController mConfigurationController;
     @NonNull private final SystemClock mSystemClock;
+    @NonNull private final UnlockedScreenOffAnimationController
+            mUnlockedScreenOffAnimationController;
     @VisibleForTesting @NonNull final BiometricOrientationEventListener mOrientationListener;
     // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
     // sensors, this, in addition to a lot of the code here, will be updated.
@@ -514,7 +513,6 @@
             @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             @NonNull DumpManager dumpManager,
             @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
-            @NonNull KeyguardViewMediator keyguardViewMediator,
             @NonNull FalsingManager falsingManager,
             @NonNull PowerManager powerManager,
             @NonNull AccessibilityManager accessibilityManager,
@@ -528,11 +526,11 @@
             @NonNull DisplayManager displayManager,
             @Main Handler mainHandler,
             @NonNull ConfigurationController configurationController,
-            @NonNull SystemClock systemClock) {
+            @NonNull SystemClock systemClock,
+            @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
         mContext = context;
         mExecution = execution;
         // TODO (b/185124905): inject main handler and vibrator once done prototyping
-        mMainHandler = new Handler(Looper.getMainLooper());
         mVibrator = vibrator;
         mInflater = inflater;
         // The fingerprint manager is queried for UDFPS before this class is constructed, so the
@@ -546,7 +544,6 @@
         mKeyguardViewManager = statusBarKeyguardViewManager;
         mDumpManager = dumpManager;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mKeyguardViewMediator = keyguardViewMediator;
         mFalsingManager = falsingManager;
         mPowerManager = powerManager;
         mAccessibilityManager = accessibilityManager;
@@ -565,6 +562,7 @@
         mKeyguardBypassController = keyguardBypassController;
         mConfigurationController = configurationController;
         mSystemClock = systemClock;
+        mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
 
         mSensorProps = findFirstUdfps();
         // At least one UDFPS sensor exists
@@ -786,13 +784,12 @@
                         mStatusBar,
                         mKeyguardViewManager,
                         mKeyguardUpdateMonitor,
-                        mFgExecutor,
                         mDumpManager,
-                        mKeyguardViewMediator,
                         mLockscreenShadeTransitionController,
                         mConfigurationController,
                         mSystemClock,
                         mKeyguardStateController,
+                        mUnlockedScreenOffAnimationController,
                         this
                 );
             case IUdfpsOverlayController.REASON_AUTH_BP:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 679e27f4..376fd5c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -26,16 +26,15 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.R;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.time.SystemClock;
 
 import java.io.FileDescriptor;
@@ -48,13 +47,13 @@
 public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> {
     @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
     @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    @NonNull private final DelayableExecutor mExecutor;
-    @NonNull private final KeyguardViewMediator mKeyguardViewMediator;
     @NonNull private final LockscreenShadeTransitionController mLockScreenShadeTransitionController;
     @NonNull private final ConfigurationController mConfigurationController;
     @NonNull private final SystemClock mSystemClock;
     @NonNull private final KeyguardStateController mKeyguardStateController;
     @NonNull private final UdfpsController mUdfpsController;
+    @NonNull private final UnlockedScreenOffAnimationController
+            mUnlockedScreenOffAnimationController;
 
     private boolean mShowingUdfpsBouncer;
     private boolean mUdfpsRequested;
@@ -81,24 +80,22 @@
             @NonNull StatusBar statusBar,
             @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
-            @NonNull DelayableExecutor mainDelayableExecutor,
             @NonNull DumpManager dumpManager,
-            @NonNull KeyguardViewMediator keyguardViewMediator,
             @NonNull LockscreenShadeTransitionController transitionController,
             @NonNull ConfigurationController configurationController,
             @NonNull SystemClock systemClock,
             @NonNull KeyguardStateController keyguardStateController,
+            @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
             @NonNull UdfpsController udfpsController) {
         super(view, statusBarStateController, statusBar, dumpManager);
         mKeyguardViewManager = statusBarKeyguardViewManager;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mExecutor = mainDelayableExecutor;
-        mKeyguardViewMediator = keyguardViewMediator;
         mLockScreenShadeTransitionController = transitionController;
         mConfigurationController = configurationController;
         mSystemClock = systemClock;
         mKeyguardStateController = keyguardStateController;
         mUdfpsController = udfpsController;
+        mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
     }
 
     @Override
@@ -135,6 +132,7 @@
 
         mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
         mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(this);
+        mUnlockedScreenOffAnimationController.addCallback(mUnlockedScreenOffCallback);
     }
 
     @Override
@@ -151,6 +149,7 @@
         if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) {
             mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
         }
+        mUnlockedScreenOffAnimationController.removeCallback(mUnlockedScreenOffCallback);
     }
 
     @Override
@@ -421,4 +420,7 @@
                     updatePauseAuth();
                 }
             };
+
+    private final UnlockedScreenOffAnimationController.Callback mUnlockedScreenOffCallback =
+            (linear, eased) -> mStateListener.onDozeAmountChanged(linear, eased);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 4196465..4aae1ad 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -267,6 +267,13 @@
     }
 
     /**
+     * Appends sensor event dropped event to logs
+     */
+    public void traceSensorEventDropped(int sensorEvent, String reason) {
+        mLogger.logSensorEventDropped(sensorEvent, reason);
+    }
+
+    /**
      * Appends pulse dropped event to logs
      * @param reason why the pulse was dropped
      */
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
index 9bc74be..23c5fa0 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
@@ -197,6 +197,15 @@
         })
     }
 
+    fun logSensorEventDropped(sensorEvent: Int, reason: String) {
+        buffer.log(TAG, INFO, {
+            int1 = sensorEvent
+            str1 = reason
+        }, {
+            "SensorEvent [$int1] dropped, reason=$str1"
+        })
+    }
+
     fun logPulseDropped(reason: String) {
         buffer.log(TAG, INFO, {
             str1 = reason
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 455f3c0..756adca 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -41,6 +41,7 @@
 import com.android.systemui.doze.DozeMachine.State;
 import com.android.systemui.doze.dagger.DozeScope;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -92,6 +93,7 @@
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final AuthController mAuthController;
     private final DelayableExecutor mMainExecutor;
+    private final KeyguardStateController mKeyguardStateController;
     private final UiEventLogger mUiEventLogger;
 
     private long mNotificationPulseTime;
@@ -179,7 +181,8 @@
             DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher,
             SecureSettings secureSettings, AuthController authController,
             @Main DelayableExecutor mainExecutor,
-            UiEventLogger uiEventLogger) {
+            UiEventLogger uiEventLogger,
+            KeyguardStateController keyguardStateController) {
         mContext = context;
         mDozeHost = dozeHost;
         mConfig = config;
@@ -198,6 +201,7 @@
         mAuthController = authController;
         mMainExecutor = mainExecutor;
         mUiEventLogger = uiEventLogger;
+        mKeyguardStateController = keyguardStateController;
     }
 
     @Override
@@ -294,6 +298,7 @@
             proximityCheckThenCall((result) -> {
                 if (result != null && result) {
                     // In pocket, drop event.
+                    mDozeLog.traceSensorEventDropped(pulseReason, "prox reporting near");
                     return;
                 }
                 if (isDoubleTap || isTap) {
@@ -302,6 +307,10 @@
                     }
                     gentleWakeUp(pulseReason);
                 } else if (isPickup) {
+                    if (shouldDropPickupEvent())  {
+                        mDozeLog.traceSensorEventDropped(pulseReason, "keyguard occluded");
+                        return;
+                    }
                     gentleWakeUp(pulseReason);
                 } else if (isUdfpsLongPress) {
                     final State state = mMachine.getState();
@@ -320,7 +329,7 @@
             }, true /* alreadyPerformedProxCheck */, pulseReason);
         }
 
-        if (isPickup) {
+        if (isPickup && !shouldDropPickupEvent()) {
             final long timeSinceNotification =
                     SystemClock.elapsedRealtime() - mNotificationPulseTime;
             final boolean withinVibrationThreshold =
@@ -329,6 +338,10 @@
         }
     }
 
+    private boolean shouldDropPickupEvent() {
+        return mKeyguardStateController.isOccluded();
+    }
+
     private void gentleWakeUp(int reason) {
         // Log screen wake up reason (lift/pickup, tap, double-tap)
         Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index f8120a8..143aaba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -8,13 +8,13 @@
 import android.database.ContentObserver
 import android.os.Handler
 import android.provider.Settings
-import com.android.systemui.statusbar.StatusBarState
 import android.view.View
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.KeyguardViewMediator
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.statusbar.LightRevealScrim
+import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.StatusBarStateControllerImpl
 import com.android.systemui.statusbar.notification.AnimatableProperty
 import com.android.systemui.statusbar.notification.PropertyAnimator
@@ -61,6 +61,7 @@
     private var shouldAnimateInKeyguard = false
     private var lightRevealAnimationPlaying = false
     private var aodUiAnimationPlaying = false
+    private var callbacks = HashSet<Callback>()
 
     /**
      * The result of our decision whether to play the screen off animation in
@@ -72,11 +73,17 @@
     private val lightRevealAnimator = ValueAnimator.ofFloat(1f, 0f).apply {
         duration = LIGHT_REVEAL_ANIMATION_DURATION
         interpolator = Interpolators.LINEAR
-        addUpdateListener { lightRevealScrim.revealAmount = it.animatedValue as Float }
+        addUpdateListener {
+            lightRevealScrim.revealAmount = it.animatedValue as Float
+            sendUnlockedScreenOffProgressUpdate(
+                    1f - (it.animatedFraction as Float),
+                    1f - (it.animatedValue as Float))
+        }
         addListener(object : AnimatorListenerAdapter() {
             override fun onAnimationCancel(animation: Animator?) {
                 lightRevealScrim.revealAmount = 1f
                 lightRevealAnimationPlaying = false
+                sendUnlockedScreenOffProgressUpdate(0f, 0f)
             }
 
             override fun onAnimationEnd(animation: Animator?) {
@@ -243,7 +250,21 @@
         return true
     }
 
-    /**
+    fun addCallback(callback: Callback) {
+        callbacks.add(callback)
+    }
+
+    fun removeCallback(callback: Callback) {
+        callbacks.remove(callback)
+    }
+
+    fun sendUnlockedScreenOffProgressUpdate(linear: Float, eased: Float) {
+        callbacks.forEach {
+            it.onUnlockedScreenOffProgressUpdate(linear, eased)
+        }
+    }
+
+/**
      * Whether we're doing the light reveal animation or we're done with that and animating in the
      * AOD UI.
      */
@@ -262,4 +283,8 @@
     fun isScreenOffLightRevealAnimationPlaying(): Boolean {
         return lightRevealAnimationPlaying
     }
+
+    interface Callback {
+        fun onUnlockedScreenOffProgressUpdate(linear: Float, eased: Float)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
index 2b4b49b..d44fb76 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
@@ -220,6 +220,12 @@
     }
 
     @Override
+    protected void onStop() {
+        super.onStop();
+        finish();
+    }
+
+    @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.wallet_activity_options_menu, menu);
         return super.onCreateOptionsMenu(menu);
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 cff2aed..f3819cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -57,7 +57,6 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -65,6 +64,7 @@
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.Execution;
@@ -123,8 +123,6 @@
     @Mock
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @Mock
-    private KeyguardViewMediator mKeyguardViewMediator;
-    @Mock
     private IUdfpsOverlayControllerCallback mUdfpsOverlayControllerCallback;
     @Mock
     private FalsingManager mFalsingManager;
@@ -152,6 +150,8 @@
     private ConfigurationController mConfigurationController;
     @Mock
     private SystemClock mSystemClock;
+    @Mock
+    private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
 
     private FakeExecutor mFgExecutor;
 
@@ -221,7 +221,6 @@
                 mStatusBarKeyguardViewManager,
                 mDumpManager,
                 mKeyguardUpdateMonitor,
-                mKeyguardViewMediator,
                 mFalsingManager,
                 mPowerManager,
                 mAccessibilityManager,
@@ -235,7 +234,8 @@
                 mDisplayManager,
                 mHandler,
                 mConfigurationController,
-                mSystemClock);
+                mSystemClock,
+                mUnlockedScreenOffAnimationController);
         verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
         mOverlayController = mOverlayCaptor.getValue();
         verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 79e1cf4..de4bc58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -89,6 +90,8 @@
     @Mock
     private ConfigurationController mConfigurationController;
     @Mock
+    private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+    @Mock
     private UdfpsController mUdfpsController;
     private FakeSystemClock mSystemClock = new FakeSystemClock();
 
@@ -121,13 +124,12 @@
                 mStatusBar,
                 mStatusBarKeyguardViewManager,
                 mKeyguardUpdateMonitor,
-                mExecutor,
                 mDumpManager,
-                mKeyguardViewMediator,
                 mLockscreenShadeTransitionController,
                 mConfigurationController,
                 mSystemClock,
                 mKeyguardStateController,
+                mUnlockedScreenOffAnimationController,
                 mUdfpsController);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 10997fa..9577c7a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -45,6 +45,7 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.doze.DozeTriggers.DozingUpdateUiEvent;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.concurrency.FakeThreadFactory;
 import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -83,6 +84,8 @@
     private AuthController mAuthController;
     @Mock
     private UiEventLogger mUiEventLogger;
+    @Mock
+    private KeyguardStateController mKeyguardStateController;
 
     private DozeTriggers mTriggers;
     private FakeSensorManager mSensors;
@@ -114,7 +117,7 @@
         mTriggers = new DozeTriggers(mContext, mHost, config, dozeParameters,
                 asyncSensorManager, wakeLock, mDockManager, mProximitySensor,
                 mProximityCheck, mock(DozeLog.class), mBroadcastDispatcher, new FakeSettings(),
-                mAuthController, mExecutor, mUiEventLogger);
+                mAuthController, mExecutor, mUiEventLogger, mKeyguardStateController);
         mTriggers.setDozeMachine(mMachine);
         waitForSensorManager();
     }
@@ -217,6 +220,32 @@
     }
 
     @Test
+    public void testPickupGesture() {
+        // GIVEN device is in doze (screen blank, but running doze sensors)
+        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+
+        // WHEN the pick up gesture is triggered and keyguard isn't occluded
+        when(mKeyguardStateController.isOccluded()).thenReturn(false);
+        mTriggers.onSensor(DozeLog.REASON_SENSOR_PICKUP, 100, 100, null);
+
+        // THEN wakeup
+        verify(mMachine).wakeUp();
+    }
+
+    @Test
+    public void testPickupGestureDroppedKeyguardOccluded() {
+        // GIVEN device is in doze (screen blank, but running doze sensors)
+        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+
+        // WHEN the pick up gesture is triggered and keyguard IS occluded
+        when(mKeyguardStateController.isOccluded()).thenReturn(true);
+        mTriggers.onSensor(DozeLog.REASON_SENSOR_PICKUP, 100, 100, null);
+
+        // THEN never wakeup
+        verify(mMachine, never()).wakeUp();
+    }
+
+    @Test
     public void testOnSensor_Fingerprint() {
         // GIVEN dozing state
         when(mMachine.getState()).thenReturn(DOZE_AOD);