diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 6f156962d136e..6daa5ea984d49 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -1668,6 +1668,24 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.resetScrollPosition(); } + /** Collapses the panel. */ + public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) { + boolean waiting = false; + if (animate && !isFullyCollapsed()) { + collapse(delayed, speedUpFactor); + waiting = true; + } else { + resetViews(false /* animate */); + setExpandedFraction(0); // just in case + } + if (!waiting) { + // it's possible that nothing animated, so we replicate the termination + // conditions of panelExpansionChanged here + // TODO(b/200063118): This can likely go away in a future refactor CL. + mBar.updateState(STATE_CLOSED); + } + } + @Override public void collapse(boolean delayed, float speedUpFactor) { if (!canPanelBeCollapsed()) { @@ -3118,7 +3136,7 @@ public class NotificationPanelViewController extends PanelViewController { @Override protected void onExpandingFinished() { - super.onExpandingFinished(); + mScrimController.onExpandingFinished(); mNotificationStackScrollLayoutController.onExpansionStopped(); mHeadsUpManager.onExpandingFinished(); mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed()); @@ -3193,6 +3211,7 @@ public class NotificationPanelViewController extends PanelViewController { protected void onTrackingStarted() { mFalsingCollector.onTrackingStarted(!mKeyguardStateController.canDismissLockScreen()); super.onTrackingStarted(); + mScrimController.onTrackingStarted(); if (mQsFullyExpanded) { mQsExpandImmediate = true; if (!mShouldUseSplitNotificationShade) { @@ -3203,6 +3222,7 @@ public class NotificationPanelViewController extends PanelViewController { mAffordanceHelper.animateHideLeftRightIcon(); } mNotificationStackScrollLayoutController.onPanelTrackingStarted(); + cancelPendingPanelCollapse(); } @Override @@ -3392,7 +3412,7 @@ public class NotificationPanelViewController extends PanelViewController { @Override protected void onClosingFinished() { - super.onClosingFinished(); + mStatusBar.onClosingFinished(); setClosingWithAlphaFadeout(false); mMediaHierarchyManager.closeGuts(); } @@ -3823,13 +3843,27 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.setScrollingEnabled(b); } + private Runnable mHideExpandedRunnable; + private final Runnable mMaybeHideExpandedRunnable = new Runnable() { + @Override + public void run() { + if (getExpansionFraction() == 0.0f) { + mView.post(mHideExpandedRunnable); + } + } + }; + /** * Initialize objects instead of injecting to avoid circular dependencies. + * + * @param hideExpandedRunnable a runnable to run when we need to hide the expanded panel. */ public void initDependencies( StatusBar statusBar, + Runnable hideExpandedRunnable, NotificationShelfController notificationShelfController) { setStatusBar(statusBar); + mHideExpandedRunnable = hideExpandedRunnable; mNotificationStackScrollLayoutController.setShelfController(notificationShelfController); mNotificationShelfController = notificationShelfController; mLockscreenShadeTransitionController.bindController(notificationShelfController); @@ -3885,6 +3919,45 @@ public class NotificationPanelViewController extends PanelViewController { private long mLastTouchDownTime = -1L; + @Override + public boolean onTouchForwardedFromStatusBar(MotionEvent event) { + // TODO(b/202981994): Move the touch debugging in this method to a central location. + // (Right now, it's split between StatusBar and here.) + + // If panels aren't enabled, ignore the gesture and don't pass it down to the + // panel view. + if (!mCommandQueue.panelsEnabled()) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + Log.v( + TAG, + String.format( + "onTouchForwardedFromStatusBar: " + + "panel disabled, ignoring touch at (%d,%d)", + (int) event.getX(), + (int) event.getY() + ) + ); + } + return false; + } + + // If the view that would receive the touch is disabled, just have status bar eat + // the gesture. + if (event.getAction() == MotionEvent.ACTION_DOWN && !mView.isEnabled()) { + Log.v(TAG, + String.format( + "onTouchForwardedFromStatusBar: " + + "panel view disabled, eating touch at (%d,%d)", + (int) event.getX(), + (int) event.getY() + ) + ); + return true; + } + + return mView.dispatchTouchEvent(event); + } + @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (mBlockTouches || mQs.disallowPanelTouches()) { @@ -3896,7 +3969,7 @@ public class NotificationPanelViewController extends PanelViewController { if (mStatusBar.isBouncerShowing()) { return true; } - if (mBar.panelEnabled() + if (mCommandQueue.panelsEnabled() && !mNotificationStackScrollLayoutController.isLongPressInProgress() && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) { mMetricsLogger.count(COUNTER_PANEL_OPEN, 1); @@ -4754,6 +4827,11 @@ public class NotificationPanelViewController extends PanelViewController { } } + /** Removes any pending runnables that would collapse the panel. */ + public void cancelPendingPanelCollapse() { + mView.removeCallbacks(mMaybeHideExpandedRunnable); + } + private final PanelBar.PanelStateChangeListener mPanelStateChangeListener = new PanelBar.PanelStateChangeListener() { @@ -4768,6 +4846,14 @@ public class NotificationPanelViewController extends PanelViewController { if (state == STATE_OPEN && mCurrentState != state) { mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } + if (state == STATE_OPENING) { + mStatusBar.makeExpandedVisible(false); + } + if (state == STATE_CLOSED) { + // Close the status bar in the next frame so we can show the end of the + // animation. + mView.post(mMaybeHideExpandedRunnable); + } mCurrentState = state; } }; @@ -4775,4 +4861,10 @@ public class NotificationPanelViewController extends PanelViewController { public PanelBar.PanelStateChangeListener getPanelStateChangeListener() { return mPanelStateChangeListener; } + + + /** Returns the handler that the status bar should forward touches to. */ + public PhoneStatusBarView.TouchEventHandler getStatusBarTouchEventHandler() { + return getTouchHandler()::onTouchForwardedFromStatusBar; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index 310fe73df1eac..e90258db85718 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -25,7 +25,6 @@ import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; -import android.view.MotionEvent; import android.widget.FrameLayout; import androidx.annotation.Nullable; @@ -53,11 +52,18 @@ public abstract class PanelBar extends FrameLayout { public static final int STATE_OPENING = 1; public static final int STATE_OPEN = 2; - private PanelViewController mPanel; @Nullable private PanelStateChangeListener mPanelStateChangeListener; private int mState = STATE_CLOSED; private boolean mTracking; + /** Updates the panel state if necessary. */ + public void updateState(@PanelState int state) { + if (DEBUG) LOG("update state: %d -> %d", mState, state); + if (mState != state) { + go(state); + } + } + private void go(@PanelState int state) { if (DEBUG) LOG("go state: %d -> %d", mState, state); mState = state; @@ -97,54 +103,11 @@ public abstract class PanelBar extends FrameLayout { super.onFinishInflate(); } - /** Set the PanelViewController */ - public void setPanel(PanelViewController pv) { - mPanel = pv; - pv.setBar(this); - } - /** Sets the listener that will be notified of panel state changes. */ public void setPanelStateChangeListener(PanelStateChangeListener listener) { mPanelStateChangeListener = listener; } - public boolean panelEnabled() { - return true; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - // Allow subclasses to implement enable/disable semantics - if (!panelEnabled()) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)", - (int) event.getX(), (int) event.getY())); - } - return false; - } - - if (event.getAction() == MotionEvent.ACTION_DOWN) { - final PanelViewController panel = mPanel; - if (panel == null) { - // panel is not there, so we'll eat the gesture - Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)", - (int) event.getX(), (int) event.getY())); - return true; - } - boolean enabled = panel.isEnabled(); - if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel, - (enabled ? "" : " (disabled)")); - if (!enabled) { - // panel is disabled, so we'll eat the gesture - Log.v(TAG, String.format( - "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)", - panel, (int) event.getX(), (int) event.getY())); - return true; - } - } - return mPanel == null || mPanel.getView().dispatchTouchEvent(event); - } - /** * @param frac the fraction from the expansion in [0, 1] * @param expanded whether the panel is currently expanded; this is independent from the @@ -162,7 +125,6 @@ public abstract class PanelBar extends FrameLayout { if (expanded) { if (mState == STATE_CLOSED) { go(STATE_OPENING); - onPanelPeeked(); } fullyClosed = false; fullyOpened = frac >= 1f; @@ -171,44 +133,16 @@ public abstract class PanelBar extends FrameLayout { go(STATE_OPEN); } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { go(STATE_CLOSED); - onPanelCollapsed(); } if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":""); } - public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) { - boolean waiting = false; - PanelViewController pv = mPanel; - if (animate && !pv.isFullyCollapsed()) { - pv.collapse(delayed, speedUpFactor); - waiting = true; - } else { - pv.resetViews(false /* animate */); - pv.setExpandedFraction(0); // just in case - } - if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting); - if (!waiting && mState != STATE_CLOSED) { - // it's possible that nothing animated, so we replicate the termination - // conditions of panelExpansionChanged here - go(STATE_CLOSED); - onPanelCollapsed(); - } - } - - public void onPanelPeeked() { - if (DEBUG) LOG("onPanelPeeked"); - } - public boolean isClosed() { return mState == STATE_CLOSED; } - public void onPanelCollapsed() { - if (DEBUG) LOG("onPanelCollapsed"); - } - public void onTrackingStarted() { mTracking = true; } @@ -217,14 +151,6 @@ public abstract class PanelBar extends FrameLayout { mTracking = false; } - public void onExpandingFinished() { - if (DEBUG) LOG("onExpandingFinished"); - } - - public void onClosingFinished() { - - } - /** An interface that will be notified of panel state changes. */ public interface PanelStateChangeListener { /** Called when the state changes. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index c23577c523e36..ac8ebd9badc27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -185,10 +185,9 @@ public abstract class PanelViewController { protected final SysuiStatusBarStateController mStatusBarStateController; protected final AmbientState mAmbientState; protected final LockscreenGestureLogger mLockscreenGestureLogger; + private final TouchHandler mTouchHandler; - protected void onExpandingFinished() { - mBar.onExpandingFinished(); - } + protected abstract void onExpandingFinished(); protected void onExpandingStarted() { } @@ -226,6 +225,7 @@ public abstract class PanelViewController { mView = view; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mLockscreenGestureLogger = lockscreenGestureLogger; + mTouchHandler = createTouchHandler(); mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { @@ -238,7 +238,7 @@ public abstract class PanelViewController { }); mView.addOnLayoutChangeListener(createLayoutChangeListener()); - mView.setOnTouchListener(createTouchHandler()); + mView.setOnTouchListener(mTouchHandler); mView.setOnConfigurationChangedListener(createOnConfigurationChangedListener()); mResources = mView.getResources(); @@ -289,6 +289,10 @@ public abstract class PanelViewController { : mTouchSlop; } + protected TouchHandler getTouchHandler() { + return mTouchHandler; + } + private void addMovement(MotionEvent event) { // Add movement to velocity tracker using raw screen X and Y coordinates instead // of window coordinates because the window frame may be moving at the same time. @@ -448,6 +452,7 @@ public abstract class PanelViewController { protected void onTrackingStopped(boolean expand) { mTracking = false; mBar.onTrackingStopped(expand); + mStatusBar.onTrackingStopped(expand); updatePanelExpansionAndVisibility(); } @@ -455,6 +460,7 @@ public abstract class PanelViewController { endClosing(); mTracking = true; mBar.onTrackingStarted(); + mStatusBar.onTrackingStarted(); notifyExpandingStarted(); updatePanelExpansionAndVisibility(); } @@ -927,10 +933,7 @@ public abstract class PanelViewController { mView.removeCallbacks(mFlingCollapseRunnable); } - protected void onClosingFinished() { - mBar.onClosingFinished(); - } - + protected abstract void onClosingFinished(); protected void startUnlockHintAnimation() { @@ -1153,23 +1156,28 @@ public abstract class PanelViewController { return mView; } - public boolean isEnabled() { - return mView.isEnabled(); - } - public OnLayoutChangeListener createLayoutChangeListener() { return new OnLayoutChangeListener(); } - protected TouchHandler createTouchHandler() { - return new TouchHandler(); - } + protected abstract TouchHandler createTouchHandler(); protected OnConfigurationChangedListener createOnConfigurationChangedListener() { return new OnConfigurationChangedListener(); } - public class TouchHandler implements View.OnTouchListener { + public abstract class TouchHandler implements View.OnTouchListener { + /** + * Method called when a touch has occurred on {@link PhoneStatusBarView}. + * + * Touches that occur on the status bar view may have ramifications for the notification + * panel (e.g. a touch that pulls down the shade could start on the status bar), so we need + * to notify the panel controller when these touches occur. + * + * Returns true if the event was handled and false otherwise. + */ + public abstract boolean onTouchForwardedFromStatusBar(MotionEvent event); + public boolean onInterceptTouchEvent(MotionEvent event) { if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled || (mMotionAborted && event.getActionMasked() != MotionEvent.ACTION_DOWN)) { @@ -1435,4 +1443,8 @@ public abstract class PanelViewController { private void cancelJankMonitoring(int cuj) { InteractionJankMonitor.getInstance().cancel(cuj); } + + protected float getExpansionFraction() { + return mExpandedFraction; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 150d9c8fcce66..06a31c94896a4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -24,7 +24,6 @@ import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; import android.util.AttributeSet; -import android.util.EventLog; import android.util.Log; import android.util.Pair; import android.view.DisplayCutout; @@ -37,7 +36,6 @@ import android.view.accessibility.AccessibilityEvent; import android.widget.LinearLayout; import com.android.systemui.Dependency; -import com.android.systemui.EventLogTags; import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; @@ -55,14 +53,6 @@ public class PhoneStatusBarView extends PanelBar { StatusBar mBar; private ScrimController mScrimController; - private Runnable mHideExpandedRunnable = new Runnable() { - @Override - public void run() { - if (mPanelFraction == 0.0f) { - mBar.makeExpandedInvisible(); - } - } - }; private DarkReceiver mBattery; private DarkReceiver mClock; private int mRotationOrientation = -1; @@ -76,15 +66,12 @@ public class PhoneStatusBarView extends PanelBar { @Nullable private List mExpansionChangedListeners; @Nullable - private PanelExpansionStateChangedListener mPanelExpansionStateChangedListener; - - private PanelEnabledProvider mPanelEnabledProvider; + private TouchEventHandler mTouchEventHandler; /** * Draw this many pixels into the left/right side of the cutout to optimally use the space */ private int mCutoutSideNudge = 0; - private boolean mHeadsUpVisible; public PhoneStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); @@ -100,8 +87,8 @@ public class PhoneStatusBarView extends PanelBar { mExpansionChangedListeners = listeners; } - void setPanelExpansionStateChangedListener(PanelExpansionStateChangedListener listener) { - mPanelExpansionStateChangedListener = listener; + void setTouchEventHandler(TouchEventHandler handler) { + mTouchEventHandler = handler; } public void setScrimController(ScrimController scrimController) { @@ -177,15 +164,6 @@ public class PhoneStatusBarView extends PanelBar { return changed; } - @Override - public boolean panelEnabled() { - if (mPanelEnabledProvider == null) { - Log.e(TAG, "panelEnabledProvider is null; defaulting to super class."); - return super.panelEnabled(); - } - return mPanelEnabledProvider.panelEnabled(); - } - @Override public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) { if (super.onRequestSendAccessibilityEventInternal(child, event)) { @@ -201,80 +179,32 @@ public class PhoneStatusBarView extends PanelBar { return false; } - @Override - public void onPanelPeeked() { - super.onPanelPeeked(); - mBar.makeExpandedVisible(false); - } - - @Override - public void onPanelCollapsed() { - super.onPanelCollapsed(); - // Close the status bar in the next frame so we can show the end of the animation. - post(mHideExpandedRunnable); - } - - public void removePendingHideExpandedRunnables() { - removeCallbacks(mHideExpandedRunnable); - } - @Override public boolean onTouchEvent(MotionEvent event) { - boolean barConsumedEvent = mBar.interceptTouchEvent(event); - - if (DEBUG_GESTURES) { - if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { - EventLog.writeEvent(EventLogTags.SYSUI_PANELBAR_TOUCH, - event.getActionMasked(), (int) event.getX(), (int) event.getY(), - barConsumedEvent ? 1 : 0); - } + mBar.onTouchEvent(event); + if (mTouchEventHandler == null) { + Log.w( + TAG, + String.format( + "onTouch: No touch handler provided; eating gesture at (%d,%d)", + (int) event.getX(), + (int) event.getY() + ) + ); + return true; } - - return barConsumedEvent || super.onTouchEvent(event); - } - - @Override - public void onTrackingStarted() { - super.onTrackingStarted(); - mBar.onTrackingStarted(); - mScrimController.onTrackingStarted(); - removePendingHideExpandedRunnables(); - } - - @Override - public void onClosingFinished() { - super.onClosingFinished(); - mBar.onClosingFinished(); - } - - @Override - public void onTrackingStopped(boolean expand) { - super.onTrackingStopped(expand); - mBar.onTrackingStopped(expand); - } - - @Override - public void onExpandingFinished() { - super.onExpandingFinished(); - mScrimController.onExpandingFinished(); + return mTouchEventHandler.handleTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { - return mBar.interceptTouchEvent(event) || super.onInterceptTouchEvent(event); + mBar.onTouchEvent(event); + return super.onInterceptTouchEvent(event); } @Override public void panelExpansionChanged(float frac, boolean expanded) { super.panelExpansionChanged(frac, expanded); - if ((frac == 0 || frac == 1)) { - if (mPanelExpansionStateChangedListener != null) { - mPanelExpansionStateChangedListener.onPanelExpansionStateChanged(); - } else { - Log.w(TAG, "No PanelExpansionStateChangedListener provided."); - } - } - if (mExpansionChangedListeners != null) { for (StatusBar.ExpansionChangedListener listener : mExpansionChangedListeners) { listener.onExpansionChanged(frac, expanded); @@ -282,11 +212,6 @@ public class PhoneStatusBarView extends PanelBar { } } - /** Set the {@link PanelEnabledProvider} to use. */ - public void setPanelEnabledProvider(PanelEnabledProvider panelEnabledProvider) { - mPanelEnabledProvider = panelEnabledProvider; - } - public void updateResources() { mCutoutSideNudge = getResources().getDimensionPixelSize( R.dimen.display_cutout_margin_consumption); @@ -366,15 +291,14 @@ public class PhoneStatusBarView extends PanelBar { getPaddingBottom()); } - /** An interface that will provide whether panel is enabled. */ - interface PanelEnabledProvider { - /** Returns true if the panel is enabled and false otherwise. */ - boolean panelEnabled(); - } - - /** A listener that will be notified when a panel's expansion state may have changed. */ - public interface PanelExpansionStateChangedListener { - /** Called when a panel's expansion state may have changed. */ - void onPanelExpansionStateChanged(); + /** + * A handler repsonsible for all touch event handling on the status bar. + * + * The handler will be notified each time {@link this#onTouchEvent} is called, and the return + * value from the handler will be returned from {@link this#onTouchEvent}. + **/ + public interface TouchEventHandler { + /** Called each time {@link this#onTouchEvent} is called. */ + boolean handleTouchEvent(MotionEvent event); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt index 4c0332a75df10..e27f4585e3206 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt @@ -26,19 +26,15 @@ import com.android.systemui.util.ViewController /** Controller for [PhoneStatusBarView]. */ class PhoneStatusBarViewController( view: PhoneStatusBarView, - commandQueue: CommandQueue, statusBarMoveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?, - panelExpansionStateChangedListener: PhoneStatusBarView.PanelExpansionStateChangedListener, + touchEventHandler: PhoneStatusBarView.TouchEventHandler, ) : ViewController(view) { override fun onViewAttached() {} override fun onViewDetached() {} init { - mView.setPanelEnabledProvider { - commandQueue.panelsEnabled() - } - mView.setPanelExpansionStateChangedListener(panelExpansionStateChangedListener) + mView.setTouchEventHandler(touchEventHandler) statusBarMoveFromCenterAnimationController?.let { animationController -> val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_left_side) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java index 768222d348624..a54251a469018 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java @@ -128,7 +128,8 @@ public class ShadeControllerImpl implements ShadeController { mNotificationShadeWindowController.setNotificationShadeFocusable(false); getStatusBar().getNotificationShadeWindowViewController().cancelExpandHelper(); - getStatusBarView().collapsePanel(true /* animate */, delayed, speedUpFactor); + getNotificationPanelViewController() + .collapsePanel(true /* animate */, delayed, speedUpFactor); } else if (mBubblesOptional.isPresent()) { mBubblesOptional.get().collapseStack(); } 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 a4e2b3492177f..b7bd482ddce4e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -902,6 +902,7 @@ public class StatusBar extends SystemUI implements mExpansionChangedListeners = new ArrayList<>(); addExpansionChangedListener( (expansion, expanded) -> mScrimController.setRawPanelExpansionFraction(expansion)); + addExpansionChangedListener(this::onPanelExpansionChanged); mBubbleExpandListener = (isExpanding, key) -> mContext.getMainExecutor().execute(() -> { @@ -1167,7 +1168,6 @@ public class StatusBar extends SystemUI implements PhoneStatusBarView oldStatusBarView = mStatusBarView; mStatusBarView = (PhoneStatusBarView) statusBarFragment.getView(); mStatusBarView.setBar(this); - mStatusBarView.setPanel(mNotificationPanelViewController); mStatusBarView.setPanelStateChangeListener( mNotificationPanelViewController.getPanelStateChangeListener()); mStatusBarView.setScrimController(mScrimController); @@ -1176,6 +1176,8 @@ public class StatusBar extends SystemUI implements sendInitialExpansionAmount(listener); } + mNotificationPanelViewController.setBar(mStatusBarView); + StatusBarMoveFromCenterAnimationController moveFromCenterAnimation = null; if (mUnfoldTransitionConfig.isEnabled()) { moveFromCenterAnimation = mMoveFromCenterAnimation.get(); @@ -1183,9 +1185,9 @@ public class StatusBar extends SystemUI implements mPhoneStatusBarViewController = new PhoneStatusBarViewController( mStatusBarView, - mCommandQueue, moveFromCenterAnimation, - this::onPanelExpansionStateChanged); + mNotificationPanelViewController.getStatusBarTouchEventHandler() + ); mPhoneStatusBarViewController.init(); mBatteryMeterViewController = new BatteryMeterViewController( @@ -1316,6 +1318,7 @@ public class StatusBar extends SystemUI implements mNotificationPanelViewController.initDependencies( this, + this::makeExpandedInvisible, mNotificationShelfController); BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop); @@ -1453,12 +1456,14 @@ public class StatusBar extends SystemUI implements } } - private void onPanelExpansionStateChanged() { - if (getNavigationBarView() != null) { - getNavigationBarView().onStatusBarPanelStateChanged(); - } - if (getNotificationPanelViewController() != null) { - getNotificationPanelViewController().updateSystemUiStateFlags(); + private void onPanelExpansionChanged(float frac, boolean expanded) { + if (frac == 0 || frac == 1) { + if (getNavigationBarView() != null) { + getNavigationBarView().onStatusBarPanelStateChanged(); + } + if (getNotificationPanelViewController() != null) { + getNotificationPanelViewController().updateSystemUiStateFlags(); + } } } @@ -2157,7 +2162,8 @@ public class StatusBar extends SystemUI implements public void animateCollapseQuickSettings() { if (mState == StatusBarState.SHADE) { - mStatusBarView.collapsePanel(true, false /* delayed */, 1.0f /* speedUpFactor */); + mNotificationPanelViewController.collapsePanel( + true, false /* delayed */, 1.0f /* speedUpFactor */); } } @@ -2170,7 +2176,7 @@ public class StatusBar extends SystemUI implements } // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) - mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/, + mNotificationPanelViewController.collapsePanel(/*animate=*/ false, false /* delayed*/, 1.0f /* speedUpFactor */); mNotificationPanelViewController.closeQs(); @@ -2204,7 +2210,10 @@ public class StatusBar extends SystemUI implements } } - public boolean interceptTouchEvent(MotionEvent event) { + /** Called when a touch event occurred on {@link PhoneStatusBarView}. */ + public void onTouchEvent(MotionEvent event) { + // TODO(b/202981994): Move this touch debugging to a central location. (Right now, it's + // split between NotificationPanelViewController and here.) if (DEBUG_GESTURES) { if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH, @@ -2236,7 +2245,6 @@ public class StatusBar extends SystemUI implements event.getAction() == MotionEvent.ACTION_CANCEL; setInteracting(StatusBarManager.WINDOW_STATUS_BAR, !upOrCancel || mExpandedVisible); } - return false; } boolean isSameStatusBarState(int state) { @@ -4464,7 +4472,7 @@ public class StatusBar extends SystemUI implements mNavigationBarController.touchAutoDim(mDisplayId); Trace.beginSection("StatusBar#updateKeyguardState"); if (mState == StatusBarState.KEYGUARD && mStatusBarView != null) { - mStatusBarView.removePendingHideExpandedRunnables(); + mNotificationPanelViewController.cancelPendingPanelCollapse(); } updateDozingState(); checkBarModes(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java index 5301b25715340..bb1daa252cdf5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java @@ -536,7 +536,7 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { } if (mStatusBar.getStatusBarView() != null) { if (!showing && mStatusBarStateController.getState() == StatusBarState.SHADE) { - mStatusBar.getStatusBarView().collapsePanel( + mNotificationPanelViewController.collapsePanel( false /* animate */, false /* delayed */, 1.0f /* speedUpFactor */); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 52c6bac0bbba4..1194cd256827c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -517,6 +517,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mControlsComponent); mNotificationPanelViewController.initDependencies( mStatusBar, + () -> {}, mNotificationShelfController); mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager); mNotificationPanelViewController.setBar(mPanelBar); @@ -584,6 +585,51 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { assertThat(mNotificationPanelViewController.isTrackingBlocked()).isFalse(); } + @Test + public void onTouchForwardedFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() { + when(mCommandQueue.panelsEnabled()).thenReturn(false); + + boolean returnVal = mTouchHandler.onTouchForwardedFromStatusBar( + MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)); + + assertThat(returnVal).isFalse(); + verify(mView, never()).dispatchTouchEvent(any()); + } + + @Test + public void onTouchForwardedFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() { + when(mCommandQueue.panelsEnabled()).thenReturn(true); + when(mView.isEnabled()).thenReturn(false); + + boolean returnVal = mTouchHandler.onTouchForwardedFromStatusBar( + MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)); + + assertThat(returnVal).isTrue(); + verify(mView, never()).dispatchTouchEvent(any()); + } + + @Test + public void onTouchForwardedFromStatusBar_viewNotEnabledButIsMoveEvent_viewReceivesEvent() { + when(mCommandQueue.panelsEnabled()).thenReturn(true); + when(mView.isEnabled()).thenReturn(false); + MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0); + + mTouchHandler.onTouchForwardedFromStatusBar(event); + + verify(mView).dispatchTouchEvent(event); + } + + @Test + public void onTouchForwardedFromStatusBar_panelAndViewEnabled_viewReceivesEvent() { + when(mCommandQueue.panelsEnabled()).thenReturn(true); + when(mView.isEnabled()).thenReturn(true); + MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0); + + mTouchHandler.onTouchForwardedFromStatusBar(event); + + verify(mView).dispatchTouchEvent(event); + } + @Test public void testA11y_initializeNode() { AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt index 52a5e064f984e..033f689945c86 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt @@ -17,13 +17,13 @@ package com.android.systemui.statusbar.phone import android.view.LayoutInflater +import android.view.MotionEvent import android.view.ViewGroup import android.widget.FrameLayout import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.systemui.R import com.android.systemui.SysuiTestCase -import com.android.systemui.statusbar.CommandQueue import com.android.systemui.util.mockito.any import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -31,15 +31,14 @@ import org.junit.Test import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.verify +import org.mockito.Mockito.mock import org.mockito.MockitoAnnotations @SmallTest class PhoneStatusBarViewControllerTest : SysuiTestCase() { - private val stateChangeListener = TestStateChangedListener() + private val touchEventHandler = TestTouchEventHandler() - @Mock - private lateinit var commandQueue: CommandQueue @Mock private lateinit var panelViewController: PanelViewController @Mock @@ -63,58 +62,41 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { val parent = FrameLayout(mContext) // add parent to keep layout params view = LayoutInflater.from(mContext) .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView - view.setPanel(panelViewController) view.setScrimController(scrimController) + view.setBar(mock(StatusBar::class.java)) } controller = PhoneStatusBarViewController( view, - commandQueue, null, - stateChangeListener + touchEventHandler, ) } @Test - fun constructor_setsPanelEnabledProviderOnView() { - var providerUsed = false - `when`(commandQueue.panelsEnabled()).then { - providerUsed = true - true - } + fun constructor_setsTouchHandlerOnView() { + val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) - // If the constructor correctly set a [PanelEnabledProvider], then it should be used - // when [PhoneStatusBarView.panelEnabled] is called. - view.panelEnabled() + view.onTouchEvent(event) - assertThat(providerUsed).isTrue() + assertThat(touchEventHandler.lastEvent).isEqualTo(event) } @Test fun constructor_moveFromCenterAnimationIsNotNull_moveFromCenterAnimationInitialized() { controller = PhoneStatusBarViewController( - view, commandQueue, moveFromCenterAnimation, stateChangeListener + view, moveFromCenterAnimation, touchEventHandler ) verify(moveFromCenterAnimation).init(any(), any()) } - @Test - fun constructor_setsExpansionStateChangedListenerOnView() { - assertThat(stateChangeListener.stateChangeCalled).isFalse() - - // If the constructor correctly set the listener, then it should be used when - // [PhoneStatusBarView.panelExpansionChanged] is called. - view.panelExpansionChanged(0f, false) - - assertThat(stateChangeListener.stateChangeCalled).isTrue() - } - - private class TestStateChangedListener : PhoneStatusBarView.PanelExpansionStateChangedListener { - var stateChangeCalled: Boolean = false - - override fun onPanelExpansionStateChanged() { - stateChangeCalled = true + private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler { + var lastEvent: MotionEvent? = null + override fun handleTouchEvent(event: MotionEvent?): Boolean { + lastEvent = event + return false } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt index ec7e07f905c63..fe3490399e81e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone +import android.view.MotionEvent import android.view.ViewGroup import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase @@ -48,63 +49,25 @@ class PhoneStatusBarViewTest : SysuiTestCase() { `when`(panelViewController.view).thenReturn(panelView) view = PhoneStatusBarView(mContext, null) - view.setPanel(panelViewController) view.setScrimController(scrimController) view.setBar(statusBar) } @Test - fun panelEnabled_providerReturnsTrue_returnsTrue() { - view.setPanelEnabledProvider { true } + fun panelExpansionChanged_expansionChangeListenerNotified() { + val listener = TestExpansionChangedListener() + view.setExpansionChangedListeners(listOf(listener)) + val fraction = 0.4f + val isExpanded = true - assertThat(view.panelEnabled()).isTrue() + view.panelExpansionChanged(fraction, isExpanded) + + assertThat(listener.fraction).isEqualTo(fraction) + assertThat(listener.isExpanded).isEqualTo(isExpanded) } @Test - fun panelEnabled_providerReturnsFalse_returnsFalse() { - view.setPanelEnabledProvider { false } - - assertThat(view.panelEnabled()).isFalse() - } - - @Test - fun panelEnabled_noProvider_noCrash() { - view.panelEnabled() - // No assert needed, just testing no crash - } - - @Test - fun panelExpansionChanged_fracZero_stateChangeListenerNotified() { - val listener = TestExpansionStateChangedListener() - view.setPanelExpansionStateChangedListener(listener) - - view.panelExpansionChanged(0f, false) - - assertThat(listener.stateChangeCalled).isTrue() - } - - @Test - fun panelExpansionChanged_fracOne_stateChangeListenerNotified() { - val listener = TestExpansionStateChangedListener() - view.setPanelExpansionStateChangedListener(listener) - - view.panelExpansionChanged(1f, false) - - assertThat(listener.stateChangeCalled).isTrue() - } - - @Test - fun panelExpansionChanged_fracHalf_stateChangeListenerNotNotified() { - val listener = TestExpansionStateChangedListener() - view.setPanelExpansionStateChangedListener(listener) - - view.panelExpansionChanged(0.5f, false) - - assertThat(listener.stateChangeCalled).isFalse() - } - - @Test - fun panelExpansionChanged_noStateChangeListener_noCrash() { + fun panelExpansionChanged_noListeners_noCrash() { view.panelExpansionChanged(1f, false) // No assert needed, just testing no crash } @@ -144,17 +107,52 @@ class PhoneStatusBarViewTest : SysuiTestCase() { } @Test - fun panelStateChanged_noListener_noCrash() { - view.panelExpansionChanged(1f, true) + fun onTouchEvent_listenerNotified() { + val handler = TestTouchEventHandler() + view.setTouchEventHandler(handler) + + val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) + view.onTouchEvent(event) + + assertThat(handler.lastEvent).isEqualTo(event) + } + + @Test + fun onTouchEvent_listenerReturnsTrue_viewReturnsTrue() { + val handler = TestTouchEventHandler() + view.setTouchEventHandler(handler) + val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) + + handler.returnValue = true + + assertThat(view.onTouchEvent(event)).isTrue() + } + + @Test + fun onTouchEvent_listenerReturnsFalse_viewReturnsFalse() { + val handler = TestTouchEventHandler() + view.setTouchEventHandler(handler) + val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) + + handler.returnValue = false + + assertThat(view.onTouchEvent(event)).isFalse() + } + + @Test + fun onTouchEvent_noListener_noCrash() { + view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)) // No assert needed, just testing no crash } - private class TestExpansionStateChangedListener - : PhoneStatusBarView.PanelExpansionStateChangedListener { - var stateChangeCalled: Boolean = false + private class TestExpansionChangedListener + : StatusBar.ExpansionChangedListener { + var fraction: Float = 0f + var isExpanded: Boolean = false - override fun onPanelExpansionStateChanged() { - stateChangeCalled = true + override fun onExpansionChanged(expansion: Float, expanded: Boolean) { + this.fraction = expansion + this.isExpanded = expanded } } @@ -164,4 +162,13 @@ class PhoneStatusBarViewTest : SysuiTestCase() { this.state = state } } + + private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler { + var lastEvent: MotionEvent? = null + var returnValue: Boolean = false + override fun handleTouchEvent(event: MotionEvent?): Boolean { + lastEvent = event + return returnValue + } + } }