Merge "Moved PhoneStatusBarView touchHandler out of NPVC" into tm-qpr-dev am: be69929b02 am: 4de42cb5ed

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20487107

Change-Id: I449f6c9946aee9e5efe2ab639e184d4d5dfe4deb
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Shawn Lee
2022-12-05 00:05:27 +00:00
committed by Automerger Merge Worker
7 changed files with 163 additions and 191 deletions

View File

@@ -200,7 +200,6 @@ import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -4587,55 +4586,6 @@ public final class NotificationPanelViewController implements Dumpable {
return new TouchHandler();
}
private final PhoneStatusBarView.TouchEventHandler mStatusBarViewTouchEventHandler =
new PhoneStatusBarView.TouchEventHandler() {
@Override
public void onInterceptTouchEvent(MotionEvent event) {
mCentralSurfaces.onTouchEvent(event);
}
@Override
public boolean handleTouchEvent(MotionEvent event) {
mCentralSurfaces.onTouchEvent(event);
// TODO(b/202981994): Move the touch debugging in this method to a central
// location. (Right now, it's split between CentralSurfaces 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 (event.getAction() == MotionEvent.ACTION_DOWN) {
// If the view that would receive the touch is disabled, just have status
// bar eat the gesture.
if (!mView.isEnabled()) {
mShadeLog.logMotionEvent(event,
"onTouchForwardedFromStatusBar: panel view disabled");
return true;
}
if (isFullyCollapsed() && event.getY() < 1f) {
// b/235889526 Eat events on the top edge of the phone when collapsed
mShadeLog.logMotionEvent(event, "top edge touch ignored");
return true;
}
}
return mView.dispatchTouchEvent(event);
}
};
public NotificationStackScrollLayoutController getNotificationStackScrollLayoutController() {
return mNotificationStackScrollLayoutController;
}
@@ -5237,6 +5187,11 @@ public final class NotificationPanelViewController implements Dumpable {
return mView.onInterceptTouchEvent(event);
}
/** */
public boolean sendTouchEventToView(MotionEvent event) {
return mView.dispatchTouchEvent(event);
}
/** */
public void requestLayoutOnView() {
mView.requestLayout();
@@ -5247,6 +5202,11 @@ public final class NotificationPanelViewController implements Dumpable {
ViewGroupFadeHelper.reset(mView);
}
/** */
public boolean isViewEnabled() {
return mView.isEnabled();
}
private void beginJankMonitoring() {
if (mInteractionJankMonitor == null) {
return;
@@ -5796,11 +5756,6 @@ public final class NotificationPanelViewController implements Dumpable {
mCurrentPanelState = state;
}
/** Returns the handler that the status bar should forward touches to. */
public PhoneStatusBarView.TouchEventHandler getStatusBarTouchEventHandler() {
return mStatusBarViewTouchEventHandler;
}
@VisibleForTesting
StatusBarStateController getStatusBarStateController() {
return mStatusBarStateController;

View File

@@ -28,7 +28,6 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.View;
import android.view.ViewGroup;
@@ -285,7 +284,11 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
void animateCollapseQuickSettings();
void onTouchEvent(MotionEvent event);
/** */
boolean getCommandQueuePanelsEnabled();
/** */
int getStatusBarWindowState();
BiometricUnlockController getBiometricUnlockController();

View File

@@ -93,7 +93,6 @@ import android.view.Display;
import android.view.IRemoteAnimationRunner;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
@@ -2011,43 +2010,14 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
}
/** Called when a touch event occurred on {@link PhoneStatusBarView}. */
@Override
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,
event.getActionMasked(), (int) event.getX(), (int) event.getY(),
mDisabled1, mDisabled2);
}
public boolean getCommandQueuePanelsEnabled() {
return mCommandQueue.panelsEnabled();
}
}
if (SPEW) {
Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1="
+ mDisabled1 + " mDisabled2=" + mDisabled2);
} else if (CHATTY) {
if (event.getAction() != MotionEvent.ACTION_MOVE) {
Log.d(TAG, String.format(
"panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x",
MotionEvent.actionToString(event.getAction()),
event.getRawX(), event.getRawY(), mDisabled1, mDisabled2));
}
}
if (DEBUG_GESTURES) {
mGestureRec.add(event);
}
if (mStatusBarWindowState == WINDOW_STATE_SHOWING) {
final boolean upOrCancel =
event.getAction() == MotionEvent.ACTION_UP ||
event.getAction() == MotionEvent.ACTION_CANCEL;
setInteracting(StatusBarManager.WINDOW_STATUS_BAR,
!upOrCancel || mShadeController.isExpandedVisible());
}
@Override
public int getStatusBarWindowState() {
return mStatusBarWindowState;
}
@Override

View File

@@ -15,14 +15,20 @@
*/
package com.android.systemui.statusbar.phone
import android.app.StatusBarManager.WINDOW_STATE_SHOWING
import android.app.StatusBarManager.WINDOW_STATUS_BAR
import android.content.res.Configuration
import android.graphics.Point
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.android.systemui.R
import com.android.systemui.shade.ShadeController
import com.android.systemui.shade.ShadeLogger
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
import com.android.systemui.statusbar.phone.PhoneStatusBarView.TouchEventHandler
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.UNFOLD_STATUS_BAR
@@ -35,14 +41,18 @@ import java.util.Optional
import javax.inject.Inject
import javax.inject.Named
private const val TAG = "PhoneStatusBarViewController"
/** Controller for [PhoneStatusBarView]. */
class PhoneStatusBarViewController private constructor(
view: PhoneStatusBarView,
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
private val centralSurfaces: CentralSurfaces,
private val shadeController: ShadeController,
private val shadeLogger: ShadeLogger,
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
private val userChipViewModel: StatusBarUserChipViewModel,
private val viewUtil: ViewUtil,
touchEventHandler: PhoneStatusBarView.TouchEventHandler,
private val configurationController: ConfigurationController
) : ViewController<PhoneStatusBarView>(view) {
@@ -90,7 +100,7 @@ class PhoneStatusBarViewController private constructor(
}
init {
mView.setTouchEventHandler(touchEventHandler)
mView.setTouchEventHandler(PhoneStatusBarViewTouchHandler())
mView.init(userChipViewModel)
}
@@ -120,6 +130,54 @@ class PhoneStatusBarViewController private constructor(
return viewUtil.touchIsWithinView(mView, x, y)
}
/** Called when a touch event occurred on {@link PhoneStatusBarView}. */
fun onTouchEvent(event: MotionEvent) {
if (centralSurfaces.statusBarWindowState == WINDOW_STATE_SHOWING) {
val upOrCancel =
event.action == MotionEvent.ACTION_UP ||
event.action == MotionEvent.ACTION_CANCEL
centralSurfaces.setInteracting(WINDOW_STATUS_BAR,
!upOrCancel || shadeController.isExpandedVisible)
}
}
inner class PhoneStatusBarViewTouchHandler : TouchEventHandler {
override fun onInterceptTouchEvent(event: MotionEvent) {
onTouchEvent(event)
}
override fun handleTouchEvent(event: MotionEvent): Boolean {
onTouchEvent(event)
// If panels aren't enabled, ignore the gesture and don't pass it down to the
// panel view.
if (!centralSurfaces.commandQueuePanelsEnabled) {
if (event.action == MotionEvent.ACTION_DOWN) {
Log.v(TAG, String.format("onTouchForwardedFromStatusBar: panel disabled, " +
"ignoring touch at (${event.x.toInt()},${event.y.toInt()})"))
}
return false
}
if (event.action == MotionEvent.ACTION_DOWN) {
// If the view that would receive the touch is disabled, just have status
// bar eat the gesture.
if (!centralSurfaces.notificationPanelViewController.isViewEnabled) {
shadeLogger.logMotionEvent(event,
"onTouchForwardedFromStatusBar: panel view disabled")
return true
}
if (centralSurfaces.notificationPanelViewController.isFullyCollapsed &&
event.y < 1f) {
// b/235889526 Eat events on the top edge of the phone when collapsed
shadeLogger.logMotionEvent(event, "top edge touch ignored")
return true
}
}
return centralSurfaces.notificationPanelViewController.sendTouchEventToView(event)
}
}
class StatusBarViewsCenterProvider : UnfoldMoveFromCenterAnimator.ViewCenterProvider {
override fun getViewCenter(view: View, outPoint: Point) =
when (view.id) {
@@ -157,20 +215,24 @@ class PhoneStatusBarViewController private constructor(
@Named(UNFOLD_STATUS_BAR)
private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
private val userChipViewModel: StatusBarUserChipViewModel,
private val centralSurfaces: CentralSurfaces,
private val shadeController: ShadeController,
private val shadeLogger: ShadeLogger,
private val viewUtil: ViewUtil,
private val configurationController: ConfigurationController,
) {
fun create(
view: PhoneStatusBarView,
touchEventHandler: PhoneStatusBarView.TouchEventHandler
view: PhoneStatusBarView
) =
PhoneStatusBarViewController(
view,
progressProvider.getOrNull(),
centralSurfaces,
shadeController,
shadeLogger,
unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController(),
userChipViewModel,
viewUtil,
touchEventHandler,
configurationController
)
}

View File

@@ -21,7 +21,6 @@ import android.view.View;
import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
@@ -127,11 +126,9 @@ public interface StatusBarFragmentModule {
@StatusBarFragmentScope
static PhoneStatusBarViewController providePhoneStatusBarViewController(
PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
@RootView PhoneStatusBarView phoneStatusBarView,
NotificationPanelViewController notificationPanelViewController) {
@RootView PhoneStatusBarView phoneStatusBarView) {
return phoneStatusBarViewControllerFactory.create(
phoneStatusBarView,
notificationPanelViewController.getStatusBarTouchEventHandler());
phoneStatusBarView);
}
/** */

View File

@@ -801,66 +801,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
assertThat(mNotificationPanelViewController.isFlinging()).isTrue();
}
@Test
public void handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
when(mCommandQueue.panelsEnabled()).thenReturn(false);
boolean returnVal = mNotificationPanelViewController
.getStatusBarTouchEventHandler()
.handleTouchEvent(
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
assertThat(returnVal).isFalse();
verify(mView, never()).dispatchTouchEvent(any());
}
@Test
public void handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() {
when(mCommandQueue.panelsEnabled()).thenReturn(true);
when(mView.isEnabled()).thenReturn(false);
boolean returnVal = mNotificationPanelViewController
.getStatusBarTouchEventHandler()
.handleTouchEvent(
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
assertThat(returnVal).isTrue();
verify(mView, never()).dispatchTouchEvent(any());
}
@Test
public void handleTouchEventFromStatusBar_viewNotEnabledButIsMoveEvent_viewReceivesEvent() {
when(mCommandQueue.panelsEnabled()).thenReturn(true);
when(mView.isEnabled()).thenReturn(false);
MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0);
mNotificationPanelViewController.getStatusBarTouchEventHandler().handleTouchEvent(event);
verify(mView).dispatchTouchEvent(event);
}
@Test
public void handleTouchEventFromStatusBar_panelAndViewEnabled_viewReceivesEvent() {
when(mCommandQueue.panelsEnabled()).thenReturn(true);
when(mView.isEnabled()).thenReturn(true);
MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0);
mNotificationPanelViewController.getStatusBarTouchEventHandler().handleTouchEvent(event);
verify(mView).dispatchTouchEvent(event);
}
@Test
public void handleTouchEventFromStatusBar_topEdgeTouch_viewNeverReceivesEvent() {
when(mCommandQueue.panelsEnabled()).thenReturn(true);
when(mView.isEnabled()).thenReturn(true);
MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0);
mNotificationPanelViewController.getStatusBarTouchEventHandler().handleTouchEvent(event);
verify(mView, never()).dispatchTouchEvent(event);
}
@Test
public void testA11y_initializeNode() {
AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo();

View File

@@ -27,6 +27,8 @@ import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.shade.ShadeControllerImpl
import com.android.systemui.shade.ShadeLogger
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.config.UnfoldTransitionConfig
@@ -41,6 +43,7 @@ import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -49,8 +52,6 @@ import java.util.Optional
@SmallTest
class PhoneStatusBarViewControllerTest : SysuiTestCase() {
private val touchEventHandler = TestTouchEventHandler()
@Mock
private lateinit var notificationPanelViewController: NotificationPanelViewController
@Mock
@@ -66,6 +67,12 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Mock
private lateinit var userChipViewModel: StatusBarUserChipViewModel
@Mock
private lateinit var centralSurfacesImpl: CentralSurfacesImpl
@Mock
private lateinit var shadeControllerImpl: ShadeControllerImpl
@Mock
private lateinit var shadeLogger: ShadeLogger
@Mock
private lateinit var viewUtil: ViewUtil
private lateinit var view: PhoneStatusBarView
@@ -87,18 +94,6 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
}
}
@Test
fun constructor_setsTouchHandlerOnView() {
val interceptEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 10f, 10f, 0)
val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
view.onInterceptTouchEvent(interceptEvent)
view.onTouchEvent(event)
assertThat(touchEventHandler.lastInterceptEvent).isEqualTo(interceptEvent)
assertThat(touchEventHandler.lastEvent).isEqualTo(event)
}
@Test
fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
val view = createViewMock()
@@ -115,6 +110,66 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
verify(moveFromCenterAnimation).onViewsReady(any())
}
@Test
fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
val returnVal = view.onTouchEvent(
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isFalse()
verify(notificationPanelViewController, never()).sendTouchEventToView(any())
}
@Test
fun handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
`when`(centralSurfacesImpl.notificationPanelViewController)
.thenReturn(notificationPanelViewController)
`when`(notificationPanelViewController.isViewEnabled).thenReturn(false)
val returnVal = view.onTouchEvent(
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isTrue()
verify(notificationPanelViewController, never()).sendTouchEventToView(any())
}
@Test
fun handleTouchEventFromStatusBar_viewNotEnabledButIsMoveEvent_viewReceivesEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
`when`(centralSurfacesImpl.notificationPanelViewController)
.thenReturn(notificationPanelViewController)
`when`(notificationPanelViewController.isViewEnabled).thenReturn(false)
val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
view.onTouchEvent(event)
verify(notificationPanelViewController).sendTouchEventToView(event)
}
@Test
fun handleTouchEventFromStatusBar_panelAndViewEnabled_viewReceivesEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
`when`(centralSurfacesImpl.notificationPanelViewController)
.thenReturn(notificationPanelViewController)
`when`(notificationPanelViewController.isViewEnabled).thenReturn(true)
val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)
view.onTouchEvent(event)
verify(notificationPanelViewController).sendTouchEventToView(event)
}
@Test
fun handleTouchEventFromStatusBar_topEdgeTouch_viewNeverReceivesEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
`when`(centralSurfacesImpl.notificationPanelViewController)
.thenReturn(notificationPanelViewController)
`when`(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
view.onTouchEvent(event)
verify(notificationPanelViewController, never()).sendTouchEventToView(any())
}
private fun createViewMock(): PhoneStatusBarView {
val view = spy(view)
val viewTreeObserver = mock(ViewTreeObserver::class.java)
@@ -128,9 +183,12 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
Optional.of(sysuiUnfoldComponent),
Optional.of(progressProvider),
userChipViewModel,
centralSurfacesImpl,
shadeControllerImpl,
shadeLogger,
viewUtil,
configurationController
).create(view, touchEventHandler).also {
).create(view).also {
it.init()
}
}
@@ -140,17 +198,4 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
override var isHingeAngleEnabled: Boolean = false
override val halfFoldedTimeoutMillis: Int = 0
}
private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler {
var lastEvent: MotionEvent? = null
var lastInterceptEvent: MotionEvent? = null
override fun onInterceptTouchEvent(event: MotionEvent?) {
lastInterceptEvent = event
}
override fun handleTouchEvent(event: MotionEvent?): Boolean {
lastEvent = event
return false
}
}
}