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();
+    }
 }