Bouncer visibility fixes

Test: go/sysui-bouncer-tests
Change-Id: Iaf6e0ded57eb3b737cfd074bbc750aa6977e36b2
Fixes: 77921840
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 52d458c..92dd37f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -97,10 +97,11 @@
     }
 
     public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
-            LockPatternUtils lockPatternUtils,
-            ViewGroup container, DismissCallbackRegistry dismissCallbackRegistry) {
+            LockPatternUtils lockPatternUtils,  ViewGroup container,
+            DismissCallbackRegistry dismissCallbackRegistry,
+            KeyguardBouncer.BouncerExpansionCallback expansionCallback) {
         return new KeyguardBouncer(context, callback, lockPatternUtils, container,
-                dismissCallbackRegistry, FalsingManager.getInstance(context));
+                dismissCallbackRegistry, FalsingManager.getInstance(context), expansionCallback);
     }
 
     public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 60a3474..3e01aec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -45,6 +45,8 @@
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 
+import java.io.PrintWriter;
+
 /**
  * A class which manages the bouncer on the lockscreen.
  */
@@ -60,6 +62,7 @@
     private final FalsingManager mFalsingManager;
     private final DismissCallbackRegistry mDismissCallbackRegistry;
     private final Handler mHandler;
+    private final BouncerExpansionCallback mExpansionCallback;
     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
                 @Override
@@ -79,7 +82,8 @@
 
     public KeyguardBouncer(Context context, ViewMediatorCallback callback,
             LockPatternUtils lockPatternUtils, ViewGroup container,
-            DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager) {
+            DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
+            BouncerExpansionCallback expansionCallback) {
         mContext = context;
         mCallback = callback;
         mLockPatternUtils = lockPatternUtils;
@@ -87,6 +91,7 @@
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
         mFalsingManager = falsingManager;
         mDismissCallbackRegistry = dismissCallbackRegistry;
+        mExpansionCallback = expansionCallback;
         mHandler = new Handler();
     }
 
@@ -157,7 +162,7 @@
      * the translation is performed manually by the user, otherwise FalsingManager
      * will never be notified and its internal state will be out of sync.
      */
-    public void onFullyShown() {
+    private void onFullyShown() {
         mFalsingManager.onBouncerShown();
         if (mKeyguardView == null) {
             Log.wtf(TAG, "onFullyShown when view was null");
@@ -167,11 +172,9 @@
     }
 
     /**
-     * This method must be called at the end of the bouncer animation when
-     * the translation is performed manually by the user, otherwise FalsingManager
-     * will never be notified and its internal state will be out of sync.
+     * @see #onFullyShown()
      */
-    public void onFullyHidden() {
+    private void onFullyHidden() {
         if (!mShowingSoon) {
             cancelShowRunnable();
             if (mRoot != null) {
@@ -326,12 +329,21 @@
      * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
      */
     public void setExpansion(float fraction) {
+        float oldExpansion = mExpansion;
         mExpansion = fraction;
         if (mKeyguardView != null && !mIsAnimatingAway) {
             float alpha = MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
             mKeyguardView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
             mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
         }
+
+        if (fraction == 0 && oldExpansion != 0) {
+            onFullyShown();
+            mExpansionCallback.onFullyShown();
+        } else if (fraction == 1 && oldExpansion != 0) {
+            onFullyHidden();
+            mExpansionCallback.onFullyHidden();
+        }
     }
 
     public boolean willDismissWithAction() {
@@ -437,4 +449,20 @@
         ensureView();
         mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
     }
+
+    public void dump(PrintWriter pw) {
+        pw.println("KeyguardBouncer");
+        pw.println("  isShowing(): " + isShowing());
+        pw.println("  mStatusBarHeight: " + mStatusBarHeight);
+        pw.println("  mExpansion: " + mExpansion);
+        pw.println("  mKeyguardView; " + mKeyguardView);
+        pw.println("  mShowingSoon: " + mKeyguardView);
+        pw.println("  mBouncerPromptReason: " + mBouncerPromptReason);
+        pw.println("  mIsAnimatingAway: " + mIsAnimatingAway);
+    }
+
+    public interface BouncerExpansionCallback {
+        void onFullyShown();
+        void onFullyHidden();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index a3da807..d4f7a4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2768,6 +2768,10 @@
             mScrimController.dump(fd, pw, args);
         }
 
+        if (mStatusBarKeyguardViewManager != null) {
+            mStatusBarKeyguardViewManager.dump(pw);
+        }
+
         if (DUMPTRUCK) {
             synchronized (mEntryManager.getNotificationData()) {
                 mEntryManager.getNotificationData().dump(pw, "  ");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 670c68f..e207eb0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -42,7 +42,9 @@
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /**
@@ -71,6 +73,17 @@
 
     protected final Context mContext;
     private final StatusBarWindowManager mStatusBarWindowManager;
+    private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
+        @Override
+        public void onFullyShown() {
+            updateStates();
+        }
+
+        @Override
+        public void onFullyHidden() {
+            updateStates();
+        }
+    };
 
     protected LockPatternUtils mLockPatternUtils;
     protected ViewMediatorCallback mViewMediatorCallback;
@@ -133,7 +146,8 @@
         mContainer = container;
         mFingerprintUnlockController = fingerprintUnlockController;
         mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
-                mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry);
+                mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
+                mExpansionCallback);
         mContainer.addOnLayoutChangeListener(this::onContainerLayout);
         mNotificationPanelView = notificationPanelView;
         notificationPanelView.setExpansionListener(this::onPanelExpansionChanged);
@@ -160,8 +174,6 @@
             if (expansion != 1 && tracking && !mBouncer.isShowing()
                     && !mBouncer.isAnimatingAway()) {
                 mBouncer.show(false /* resetSecuritySelection */, false /* animated */);
-            } else if (expansion == 0 || expansion == 1) {
-                updateStates();
             }
         }
     }
@@ -588,11 +600,6 @@
         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
             mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
             mStatusBar.setBouncerShowing(bouncerShowing);
-            if (bouncerShowing) {
-                mBouncer.onFullyShown();
-            } else {
-                mBouncer.onFullyHidden();
-            }
         }
 
         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
@@ -709,6 +716,22 @@
         return mBouncer.willDismissWithAction();
     }
 
+    public void dump(PrintWriter pw) {
+        pw.println("StatusBarKeyguardViewManager:");
+        pw.println("  mShowing: " + mShowing);
+        pw.println("  mOccluded: " + mOccluded);
+        pw.println("  mRemoteInputActive: " + mRemoteInputActive);
+        pw.println("  mDozing: " + mDozing);
+        pw.println("  mGoingToSleepVisibleNotOccluded: " + mGoingToSleepVisibleNotOccluded);
+        pw.println("  mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction);
+        pw.println("  mAfterKeyguardGoneRunnables: " + mAfterKeyguardGoneRunnables);
+        pw.println("  mPendingWakeupAction: " + mPendingWakeupAction);
+
+        if (mBouncer != null) {
+            mBouncer.dump(pw);
+        }
+    }
+
     private static class DismissWithActionRequest {
         final OnDismissAction dismissAction;
         final Runnable cancelAction;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index c6b6546..73f05c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -16,16 +16,11 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
@@ -33,7 +28,6 @@
 
 import android.graphics.Color;
 import android.support.test.filters.SmallTest;
-import android.test.UiThreadTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.ViewGroup;
@@ -73,6 +67,8 @@
     private KeyguardHostView mKeyguardHostView;
     @Mock
     private ViewTreeObserver mViewTreeObserver;
+    @Mock
+    private KeyguardBouncer.BouncerExpansionCallback mExpansionCallback;
 
     private KeyguardBouncer mBouncer;
 
@@ -84,7 +80,8 @@
         when(mKeyguardHostView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
         when(mKeyguardHostView.getHeight()).thenReturn(500);
         mBouncer = new KeyguardBouncer(getContext(), mViewMediatorCallback,
-                mLockPatternUtils, container, mDismissCallbackRegistry, mFalsingManager) {
+                mLockPatternUtils, container, mDismissCallbackRegistry, mFalsingManager,
+                mExpansionCallback) {
             @Override
             protected void inflateView() {
                 super.inflateView();
@@ -166,23 +163,26 @@
     }
 
     @Test
-    public void testOnFullyShown_notifiesFalsingManager() {
+    public void testSetExpansion_notifiesFalsingManager() {
         mBouncer.ensureView();
-        mBouncer.onFullyShown();
-        verify(mFalsingManager).onBouncerShown();
-    }
+        mBouncer.setExpansion(0.5f);
 
-    @Test
-    public void testOnFullyShown_notifiesKeyguardView() {
-        mBouncer.ensureView();
-        mBouncer.onFullyShown();
-        verify(mKeyguardHostView).onResume();
-    }
-
-    @Test
-    public void testOnFullyHidden_notifiesFalsingManager() {
-        mBouncer.onFullyHidden();
+        mBouncer.setExpansion(1);
         verify(mFalsingManager).onBouncerHidden();
+        verify(mExpansionCallback).onFullyHidden();
+
+        mBouncer.setExpansion(0);
+        verify(mFalsingManager).onBouncerShown();
+        verify(mExpansionCallback).onFullyShown();
+    }
+
+    @Test
+    public void testSetExpansion_notifiesKeyguardView() {
+        mBouncer.ensureView();
+        mBouncer.setExpansion(0.1f);
+
+        mBouncer.setExpansion(0);
+        verify(mKeyguardHostView).onResume();
     }
 
     @Test
@@ -207,6 +207,14 @@
     }
 
     @Test
+    public void testHide_notShowingAnymore() {
+        mBouncer.ensureView();
+        mBouncer.show(false /* resetSecuritySelection */);
+        mBouncer.hide(false /* destroyViews */);
+        Assert.assertFalse("Not showing", mBouncer.isShowing());
+    }
+
+    @Test
     public void testShowPromptReason_propagates() {
         mBouncer.ensureView();
         mBouncer.showPromptReason(1);