Fix OneHandedGestureHandler incorrect InputMonitor behavior
1) Fix CTS WindowInsetsBehaviorTests test fail in NavBar 3 Button mode
When device set NavBar 3 Button mode, OneHandedGestureHandler
will monitor the InputEvent and pilferPointers() over NavBar region
and break WindowInsetsBehaviorTests
a) systemGesture_excludeViewRects_withoutAnyCancel
b) systemGesture_notExcludeViewRects_withoutAnyCancel
2) In landscape, disposeInputChannelInputMonitor in OneHandedGestureHandler
3) Add dump in OneHandedGestureHandler for bugreport
Test: atest android.systemui.cts.WindowInsetsBehaviorTests
Test: manual test check the UX feel good on 3 Button mode
Bug: 181025710
Change-Id: I4c30578f45e5a569d7b5a1698d3d30229cecb13f
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index d2eb361..5fc7c98 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -525,7 +525,7 @@
public void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
- pw.println(TAG + "states: ");
+ pw.println(TAG + "States: ");
pw.print(innerPrefix + "mOffSetFraction=");
pw.println(mOffSetFraction);
pw.print(innerPrefix + "mLockedDisabled=");
@@ -535,6 +535,10 @@
mDisplayAreaOrganizer.dump(pw);
}
+ if (mGestureHandler != null) {
+ mGestureHandler.dump(pw);
+ }
+
if (mTouchHandler != null) {
mTouchHandler.dump(pw);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
index b86b954..778876c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
@@ -36,16 +36,21 @@
import android.view.WindowManager;
import android.window.WindowContainerTransaction;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
+import java.io.PrintWriter;
+
/**
* The class manage swipe up and down gesture for 3-Button mode navigation,
* others(e.g, 2-button, full gesture mode) are handled by Launcher quick steps.
+ * TODO(b/160934654) Migrate to Launcher quick steps
*/
public class OneHandedGestureHandler implements OneHandedTransitionCallback,
DisplayChangeController.OnDisplayChangingListener {
@@ -72,7 +77,6 @@
InputMonitor mInputMonitor;
@VisibleForTesting
InputEventReceiver mInputEventReceiver;
- private final DisplayController mDisplayController;
private final ShellExecutor mMainExecutor;
@VisibleForTesting
@Nullable
@@ -91,11 +95,10 @@
DisplayController displayController, ViewConfiguration viewConfig,
ShellExecutor mainExecutor) {
mWindowManager = windowManager;
- mDisplayController = displayController;
mMainExecutor = mainExecutor;
displayController.addDisplayChangingController(this);
- mNavGestureHeight = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.navigation_bar_gesture_larger_height);
+ mNavGestureHeight = getNavBarSize(context,
+ displayController.getDisplayLayout(DEFAULT_DISPLAY));
mDragDistThreshold = context.getResources().getDimensionPixelSize(
R.dimen.gestures_onehanded_drag_threshold);
final float slop = viewConfig.getScaledTouchSlop();
@@ -208,10 +211,23 @@
return mGestureRegion.contains(Math.round(x), Math.round(y));
}
+ private int getNavBarSize(Context context, @Nullable DisplayLayout displayLayout) {
+ if (displayLayout != null) {
+ return displayLayout.navBarFrameHeight();
+ } else {
+ return isRotated()
+ ? context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height_landscape)
+ : context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height);
+ }
+ }
+
private void updateIsEnabled() {
disposeInputChannel();
- if (mIsEnabled && mIsThreeButtonModeEnabled) {
+ // Either OHM or swipe notification shade can activate in portrait mode only
+ if (mIsEnabled && mIsThreeButtonModeEnabled && !isRotated()) {
final Rect displaySize = mWindowManager.getCurrentWindowMetrics().getBounds();
// Register input event receiver to monitor the touch region of NavBar gesture height
mGestureRegion.set(0, displaySize.height() - mNavGestureHeight, displaySize.width(),
@@ -239,6 +255,7 @@
public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
WindowContainerTransaction t) {
mRotation = toRotation;
+ updateIsEnabled();
}
// TODO: Use BatchedInputEventReceiver
@@ -253,6 +270,10 @@
}
}
+ private boolean isRotated() {
+ return mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270;
+ }
+
private boolean isValidStartAngle(float deltaX, float deltaY) {
final float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
return angle > -(ANGLE_MAX) && angle < -(ANGLE_MIN);
@@ -267,6 +288,19 @@
return x * x + y * y;
}
+ void dump(@NonNull PrintWriter pw) {
+ final String innerPrefix = " ";
+ pw.println(TAG + "States: ");
+ pw.print(innerPrefix + "mIsEnabled=");
+ pw.println(mIsEnabled);
+ pw.print(innerPrefix + "mNavGestureHeight=");
+ pw.println(mNavGestureHeight);
+ pw.print(innerPrefix + "mIsThreeButtonModeEnabled=");
+ pw.println(mIsThreeButtonModeEnabled);
+ pw.print(innerPrefix + "isLandscape=");
+ pw.println(isRotated());
+ }
+
/**
* The touch(gesture) events to notify {@link OneHandedController} start or stop one handed
*/
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
index f58affc..f683e4a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
@@ -16,14 +16,22 @@
package com.android.wm.shell.onehanded;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
+
import android.testing.AndroidTestingRunner;
+import android.view.Surface;
import android.view.ViewConfiguration;
+import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import org.junit.Before;
@@ -39,14 +47,21 @@
@Mock
DisplayController mMockDisplayController;
@Mock
+ DisplayLayout mMockDisplayLayout;
+ @Mock
ShellExecutor mMockShellMainExecutor;
+ @Mock
+ WindowContainerTransaction mMockWct;
@Before
public void setUp() {
+ final int mockNavBarHeight = 100;
MockitoAnnotations.initMocks(this);
mGestureHandler = new OneHandedGestureHandler(mContext, mWindowManager,
mMockDisplayController, ViewConfiguration.get(mTestContext),
mMockShellMainExecutor);
+ when(mMockDisplayLayout.navBarFrameHeight()).thenReturn(mockNavBarHeight);
+ when(mMockDisplayController.getDisplayLayout(anyInt())).thenReturn(mMockDisplayLayout);
}
@Test
@@ -80,4 +95,14 @@
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
}
+
+ @Test
+ public void testOnlyHandleGestureInPortraitMode() {
+ mGestureHandler.onOneHandedEnabled(true);
+ mGestureHandler.onRotateDisplay(DEFAULT_DISPLAY, Surface.ROTATION_0, Surface.ROTATION_90,
+ mMockWct);
+
+ assertThat(mGestureHandler.mInputMonitor).isNull();
+ assertThat(mGestureHandler.mInputEventReceiver).isNull();
+ }
}