OSDN Git Service

Dismiss bouncer if auth happens during gesture
authorLucas Dupin <dupin@google.com>
Fri, 29 Mar 2019 23:09:26 +0000 (16:09 -0700)
committerLucas Dupin <dupin@google.com>
Tue, 2 Apr 2019 23:33:39 +0000 (16:33 -0700)
The user might have started to drag during authentication,
we want to make sure that the bouncer will be dismissed if
this happens.

Fixes: 129432051
Test: unlock with fp when swiping up
Test: unlock after swipping up
Test: swipe up and then unlock
Test: expand QS after unlocking
Test: atest NotificationPanelViewTest
Change-Id: Iaf189634048ca6735341a271d53e2576a3370602

packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java

index ca45209..2e85fea 100644 (file)
@@ -414,7 +414,9 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
             return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
         }
         if (mStatusBarKeyguardViewManager.isShowing()) {
-            if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
+            if ((mStatusBarKeyguardViewManager.isBouncerShowing()
+                    || mStatusBarKeyguardViewManager.isBouncerPartiallyVisible())
+                    && unlockingAllowed) {
                 return MODE_DISMISS_BOUNCER;
             } else if (unlockingAllowed) {
                 return faceStayingOnKeyguard ? MODE_ONLY_WAKE : MODE_UNLOCK;
index 5afff81..1d2ca9f 100644 (file)
@@ -334,6 +334,11 @@ public class KeyguardBouncer {
                 && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
     }
 
+    public boolean isPartiallyVisible() {
+        return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
+                && mExpansion != EXPANSION_HIDDEN && !isAnimatingAway();
+    }
+
     /**
      * @return {@code true} when bouncer's pre-hide animation already started but isn't completely
      *         hidden yet, {@code false} otherwise.
index 02bad73..cff3855 100644 (file)
@@ -152,9 +152,11 @@ public class NotificationPanelView extends PanelView implements
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
     @VisibleForTesting
     protected KeyguardStatusBarView mKeyguardStatusBar;
-    private ViewGroup mBigClockContainer;
+    @VisibleForTesting
+    protected ViewGroup mBigClockContainer;
     private QS mQs;
-    private FrameLayout mQsFrame;
+    @VisibleForTesting
+    protected FrameLayout mQsFrame;
     @VisibleForTesting
     protected KeyguardStatusView mKeyguardStatusView;
     private View mQsNavbarScrim;
@@ -266,6 +268,7 @@ public class NotificationPanelView extends PanelView implements
     private int mIndicationBottomPadding;
     private int mAmbientIndicationBottomPadding;
     private boolean mIsFullWidth;
+    private boolean mBlockingExpansionForCurrentTouch;
 
     /**
      * Current dark amount that follows regular interpolation curve of animation.
@@ -983,6 +986,11 @@ public class NotificationPanelView extends PanelView implements
             return false;
         }
         initDownStates(event);
+        // Make sure the next touch won't the blocked after the current ends.
+        if (event.getAction() == MotionEvent.ACTION_UP
+                || event.getAction() == MotionEvent.ACTION_CANCEL) {
+            mBlockingExpansionForCurrentTouch = false;
+        }
         if (!mIsExpanding && mPulseExpansionHandler.onTouchEvent(event)) {
             // We're expanding all the other ones shouldn't get this anymore
             return true;
@@ -1662,7 +1670,7 @@ public class NotificationPanelView extends PanelView implements
         if (!mQsExpansionEnabled || mCollapsedOnDown) {
             return false;
         }
-        View header = mKeyguardShowing ? mKeyguardStatusBar : mQs.getHeader();
+        View header = mKeyguardShowing || mQs == null ? mKeyguardStatusBar : mQs.getHeader();
         final boolean onHeader = x >= mQsFrame.getX()
                 && x <= mQsFrame.getX() + mQsFrame.getWidth()
                 && y >= header.getTop() && y <= header.getBottom();
@@ -2337,7 +2345,7 @@ public class NotificationPanelView extends PanelView implements
 
     @Override
     protected boolean isTrackingBlocked() {
-        return mConflictingQsExpansionGesture && mQsExpanded;
+        return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch;
     }
 
     public boolean isQsExpanded() {
@@ -2937,6 +2945,14 @@ public class NotificationPanelView extends PanelView implements
         updateLockIcon();
     }
 
+    /**
+     * Do not let the user drag the shade up and down for the current touch session.
+     * This is necessary to avoid shade expansion while/after the bouncer is dismissed.
+     */
+    public void blockExpansionForCurrentTouch() {
+        mBlockingExpansionForCurrentTouch = mTracking;
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         super.dump(fd, pw, args);
index 3b32d95..92cd280 100644 (file)
@@ -419,6 +419,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
         } else if (finishRunnable != null) {
             finishRunnable.run();
         }
+        mNotificationPanelView.blockExpansionForCurrentTouch();
     }
 
     /**
@@ -572,6 +573,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
         return mBouncer.isShowing();
     }
 
+    public boolean isBouncerPartiallyVisible() {
+        return mBouncer.isPartiallyVisible();
+    }
+
     public boolean isFullscreenBouncer() {
         return mBouncer.isFullscreenBouncer();
     }
index 3b56e45..6d6af47 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.verify;
@@ -23,6 +25,8 @@ import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
 
 import androidx.test.filters.SmallTest;
 
@@ -32,6 +36,7 @@ import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -54,6 +59,8 @@ import org.mockito.MockitoAnnotations;
 public class NotificationPanelViewTest extends SysuiTestCase {
 
     @Mock
+    private StatusBar mStatusBar;
+    @Mock
     private SysuiStatusBarStateController mStatusBarStateController;
     @Mock
     private NotificationStackScrollLayout mNotificationStackScrollLayout;
@@ -62,12 +69,33 @@ public class NotificationPanelViewTest extends SysuiTestCase {
     @Mock
     private KeyguardBottomAreaView mKeyguardBottomArea;
     @Mock
+    private KeyguardBottomAreaView mQsFrame;
+    @Mock
+    private ViewGroup mBigClockContainer;
+    @Mock
+    private ScrimController mScrimController;
+    @Mock
+    private NotificationIconAreaController mNotificationAreaController;
+    @Mock
+    private HeadsUpManagerPhone mHeadsUpManager;
+    @Mock
+    private NotificationShelf mNotificationShelf;
+    @Mock
+    private NotificationGroupManager mGroupManager;
+    @Mock
     private KeyguardStatusBarView mKeyguardStatusBar;
+    @Mock
+    private HeadsUpTouchHelper.Callback mHeadsUpCallback;
+    @Mock
+    private PanelBar mPanelBar;
     private NotificationPanelView mNotificationPanelView;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+        when(mNotificationStackScrollLayout.getHeight()).thenReturn(1000);
+        when(mNotificationStackScrollLayout.getHeadsUpCallback()).thenReturn(mHeadsUpCallback);
+        when(mHeadsUpCallback.getContext()).thenReturn(mContext);
         mDependency.injectTestDependency(StatusBarStateController.class,
                 mStatusBarStateController);
         mDependency.injectMockDependency(ShadeController.class);
@@ -80,6 +108,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
                         new StatusBarStateControllerImpl());
         PulseExpansionHandler expansionHandler = new PulseExpansionHandler(mContext, coordinator);
         mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler);
+        mNotificationPanelView.setHeadsUpManager(mHeadsUpManager);
+        mNotificationPanelView.setBar(mPanelBar);
     }
 
     @Test
@@ -105,6 +135,37 @@ public class NotificationPanelViewTest extends SysuiTestCase {
         verify(mNotificationStackScrollLayout).setShowDarkShelf(eq(false));
     }
 
+    @Test
+    public void testSetExpandedHeight() {
+        mNotificationPanelView.setExpandedHeight(200);
+        assertThat((int) mNotificationPanelView.getExpandedHeight()).isEqualTo(200);
+    }
+
+    @Test
+    public void testOnTouchEvent_expansionCanBeBlocked() {
+        mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
+                0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
+                0 /* metaState */));
+        mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
+                0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 200f /* y */,
+                0 /* metaState */));
+        assertThat((int) mNotificationPanelView.getExpandedHeight()).isEqualTo(200);
+        assertThat(mNotificationPanelView.isTrackingBlocked()).isFalse();
+
+        mNotificationPanelView.blockExpansionForCurrentTouch();
+        mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
+                0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 300f /* y */,
+                0 /* metaState */));
+        // Expansion should not have changed because it was blocked
+        assertThat((int) mNotificationPanelView.getExpandedHeight()).isEqualTo(200);
+        assertThat(mNotificationPanelView.isTrackingBlocked()).isTrue();
+
+        mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
+                0L /* eventTime */, MotionEvent.ACTION_UP, 0f /* x */, 300f /* y */,
+                0 /* metaState */));
+        assertThat(mNotificationPanelView.isTrackingBlocked()).isFalse();
+    }
+
     private class TestableNotificationPanelView extends NotificationPanelView {
         TestableNotificationPanelView(NotificationWakeUpCoordinator coordinator,
                 PulseExpansionHandler expansionHandler) {
@@ -116,6 +177,14 @@ public class NotificationPanelViewTest extends SysuiTestCase {
             mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
             mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
             mKeyguardBottomArea = NotificationPanelViewTest.this.mKeyguardBottomArea;
+            mBigClockContainer = NotificationPanelViewTest.this.mBigClockContainer;
+            mQsFrame = NotificationPanelViewTest.this.mQsFrame;
+            initDependencies(NotificationPanelViewTest.this.mStatusBar,
+                    NotificationPanelViewTest.this.mGroupManager,
+                    NotificationPanelViewTest.this.mNotificationShelf,
+                    NotificationPanelViewTest.this.mHeadsUpManager,
+                    NotificationPanelViewTest.this.mNotificationAreaController,
+                    NotificationPanelViewTest.this.mScrimController);
         }
     }
 }