Update state and touch region after one handed overlay changed

The matrix for overall modes x state changes:
-----------------------------------------------------
   Mode     |      State changed     | *Before|*After
-----------------------------------------------------
  OneHanded |  Portrait->Landscape   |  80dp  |  32dp
  OneHanded |  Landscape->Portrait   |  32dp  |  80dp
-----------------------------------------------------
  OneHanded |  Disable->Enable       |  32dp  |  32dp
 (Landscape)|  Enable->Disable       |  32dp  |  32dp
-----------------------------------------------------
  OneHanded |  Disable->Enable       |  32dp  |  80dp
 (Portrait) |  Enable->Disable       |  80dp  |  32dp
-----------------------------------------------------
  NO_BUTTON |  Portrait->Landscape   |  32dp  |  32dp
  NO_BUTTON |  Landscape->Portrait   |  32dp  |  32dp
  2 BUTTON  |  Portrait->Landscape   |  48dp  |  48dp
  2 BUTTON  |  Landscape->Portrait   |  48dp  |  48dp
  3 BUTTON  |  Portrait->Landscape   |  48dp  |  48dp
  3 BUTTON  |  Landscape->Portrait   |  48dp  |  48dp
-----------------------------------------------------
* dimen : navigation_bar_gesture_height

Test: adb bugrepot | grep mOneHandedModeRegion
Test: manually triger one handed
Test: atest WindowInsetsBehaviorTests
Bug: 157958539

Change-Id: I0f4b5d18053058730a06c3c216e849850c0390f4
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index a696c21..901c981 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -58,6 +58,7 @@
 
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
+import com.android.launcher3.ResourceUtils;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.UserEventDispatcher;
@@ -298,6 +299,7 @@
         mAM = ActivityManagerWrapper.getInstance();
         mDeviceState = new RecentsAnimationDeviceState(this);
         mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
+        mDeviceState.addOneHandedModeChangedCallback(this::onOneHandedModeOverlayChanged);
         mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
         ProtoTracer.INSTANCE.get(this).add(this);
 
@@ -338,6 +340,13 @@
         resetHomeBounceSeenOnQuickstepEnabledFirstTime();
     }
 
+    /**
+     * Called when the one handed mode overlay package changes, to recreate touch region.
+     */
+    private void onOneHandedModeOverlayChanged(int newGesturalHeight) {
+        initInputMonitor();
+    }
+
     @UiThread
     public void onUserUnlocked() {
         mTaskAnimationManager = new TaskAnimationManager();
@@ -811,6 +820,13 @@
         }
         if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(),
                 activity.getResources().getConfiguration().diff(newConfig))) {
+            // Since navBar gestural height are different between portrait and landscape,
+            // can handle orientation changes and refresh navigation gestural region through
+            // onOneHandedModeChanged()
+            int newGesturalHeight = ResourceUtils.getNavbarSize(
+                    ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
+                    getApplicationContext().getResources());
+            mDeviceState.onOneHandedModeChanged(newGesturalHeight);
             return;
         }
 
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index b49bc5a..5dcdd7a 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -65,6 +65,7 @@
     private final RectF mAssistantRightRegion = new RectF();
     private final RectF mOneHandedModeRegion = new RectF();
     private int mCurrentDisplayRotation;
+    private int mNavBarGesturalHeight;
     private boolean mEnableMultipleRegions;
     private Resources mResources;
     private OrientationRectF mLastRectTouched;
@@ -104,18 +105,33 @@
         mResources = resources;
         mMode = mode;
         mContractInfo = contractInfo;
+        mNavBarGesturalHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
     }
 
-    void setNavigationMode(SysUINavigationMode.Mode newMode, DefaultDisplay.Info info) {
+    private void refreshTouchRegion(DefaultDisplay.Info info, Resources newRes) {
+        // Swipe touch regions are independent of nav mode, so we have to clear them explicitly
+        // here to avoid, for ex, a nav region for 2-button rotation 0 being used for 3-button mode
+        // It tries to cache and reuse swipe regions whenever possible based only on rotation
+        mResources = newRes;
+        mSwipeTouchRegions.clear();
+        resetSwipeRegions(info);
+    }
+
+    void setNavigationMode(SysUINavigationMode.Mode newMode, DefaultDisplay.Info info,
+            Resources newRes) {
         if (mMode == newMode) {
             return;
         }
         this.mMode = newMode;
-        // Swipe touch regions are independent of nav mode, so we have to clear them explicitly
-        // here to avoid, for ex, a nav region for 2-button rotation 0 being used for 3-button mode
-        // It tries to cache and reuse swipe regions whenever possible based only on rotation
-        mSwipeTouchRegions.clear();
-        resetSwipeRegions(info);
+        refreshTouchRegion(info, newRes);
+    }
+
+    void setGesturalHeight(int newGesturalHeight, DefaultDisplay.Info info, Resources newRes) {
+        if (mNavBarGesturalHeight == newGesturalHeight) {
+            return;
+        }
+        mNavBarGesturalHeight = newGesturalHeight;
+        refreshTouchRegion(info, newRes);
     }
 
     /**
@@ -197,7 +213,7 @@
 
         Point size = display.realSize;
         int rotation = display.rotation;
-        int touchHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
+        int touchHeight = mNavBarGesturalHeight;
         OrientationRectF orientationRectF =
                 new OrientationRectF(0, 0, size.x, size.y, rotation);
         if (mMode == SysUINavigationMode.Mode.NO_BUTTON) {
@@ -338,6 +354,7 @@
             regions.append(rectF.mRotation).append(" ");
         }
         pw.println(regions.toString());
+        pw.println("  mNavBarGesturalHeight=" + mNavBarGesturalHeight);
         pw.println("  mOneHandedModeRegion=" + mOneHandedModeRegion);
     }
 
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 04aba22..8a1c30f 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -52,8 +52,8 @@
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.view.MotionEvent;
-import android.view.Surface;
 import android.view.OrientationEventListener;
+import android.view.Surface;
 
 import androidx.annotation.BinderThread;
 
@@ -63,6 +63,7 @@
 import com.android.launcher3.util.DefaultDisplay;
 import com.android.launcher3.util.SecureSettingsObserver;
 import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
+import com.android.quickstep.SysUINavigationMode.OneHandedModeChangeListener;
 import com.android.quickstep.util.NavBarPosition;
 import com.android.quickstep.util.RecentsOrientedState;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -81,7 +82,8 @@
  */
 public class RecentsAnimationDeviceState implements
         NavigationModeChangeListener,
-        DefaultDisplay.DisplayInfoChangeListener {
+        DefaultDisplay.DisplayInfoChangeListener,
+        OneHandedModeChangeListener {
 
     private final Context mContext;
     private final SysUINavigationMode mSysUiNavMode;
@@ -310,6 +312,15 @@
         runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(listener));
     }
 
+    /**
+     * Adds a listener for the one handed mode change,
+     * guaranteed to be called after the device state's mode has changed.
+     */
+    public void addOneHandedModeChangedCallback(OneHandedModeChangeListener listener) {
+        listener.onOneHandedModeChanged(mSysUiNavMode.addOneHandedOverlayChangeListener(listener));
+        runOnDestroy(() -> mSysUiNavMode.removeOneHandedOverlayChangeListener(listener));
+    }
+
     @Override
     public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
         mDefaultDisplay.removeChangeListener(this);
@@ -324,7 +335,8 @@
 
         mNavBarPosition = new NavBarPosition(newMode, mDefaultDisplay.getInfo());
 
-        mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo());
+        mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo(),
+                mContext.getApplicationContext().getResources());
         if (!mMode.hasGestures && newMode.hasGestures) {
             setupOrientationSwipeHandler();
         } else if (mMode.hasGestures && !newMode.hasGestures){
@@ -363,6 +375,12 @@
         }
     }
 
+    @Override
+    public void onOneHandedModeChanged(int newGesturalHeight) {
+        mOrientationTouchTransformer.setGesturalHeight(newGesturalHeight, mDefaultDisplay.getInfo(),
+                mContext.getApplicationContext().getResources());
+    }
+
     /**
      * @return the current navigation mode for the device.
      */
diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
index 05ce2a2..26c72a2 100644
--- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java
+++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
@@ -24,6 +24,7 @@
 import android.content.res.Resources;
 import android.util.Log;
 
+import com.android.launcher3.ResourceUtils;
 import com.android.launcher3.touch.PagedOrientationHandler;
 import com.android.launcher3.util.MainThreadInitializedObject;
 
@@ -62,11 +63,20 @@
     private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
     private static final String NAV_BAR_INTERACTION_MODE_RES_NAME =
             "config_navBarInteractionMode";
+    private static final String NAV_BAR_INTERACTION_MODE_OVERLAY_PACKAGE_PREFIX =
+            "com.android.internal.systemui.navbar";
+    private static final String ONE_HANDED_MODE_OVERLAY_PACKAGE_PREFIX =
+            "com.android.internal.systemui.onehanded";
+    private static final int INVALID_RESOURCE_HANDLE = -1;
 
     private final Context mContext;
     private Mode mMode;
 
+    private int mNavBarGesturalHeight;
+
     private final List<NavigationModeChangeListener> mChangeListeners = new ArrayList<>();
+    private final List<OneHandedModeChangeListener> mOneHandedOverlayChangeListeners =
+            new ArrayList<>();
 
     public SysUINavigationMode(Context context) {
         mContext = context;
@@ -77,7 +87,15 @@
             public void onReceive(Context context, Intent intent) {
                 updateMode();
             }
-        }, getPackageFilter("android", ACTION_OVERLAY_CHANGED));
+        }, getPackageFilter(NAV_BAR_INTERACTION_MODE_OVERLAY_PACKAGE_PREFIX,
+                ACTION_OVERLAY_CHANGED));
+
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                updateGesturalHeight();
+            }
+        }, getPackageFilter(ONE_HANDED_MODE_OVERLAY_PACKAGE_PREFIX, ACTION_OVERLAY_CHANGED));
     }
 
     /** Updates navigation mode when needed. */
@@ -89,8 +107,24 @@
         }
     }
 
+    private void updateGesturalHeight() {
+        int newGesturalHeight = getSystemIntegerRes(mContext,
+                ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
+
+        if (newGesturalHeight == INVALID_RESOURCE_HANDLE) {
+            return;
+        }
+
+        if (mNavBarGesturalHeight != newGesturalHeight) {
+            mNavBarGesturalHeight = newGesturalHeight;
+            dispatchOneHandedOverlayChange();
+        }
+    }
+
     private void initializeMode() {
         int modeInt = getSystemIntegerRes(mContext, NAV_BAR_INTERACTION_MODE_RES_NAME);
+        mNavBarGesturalHeight = getSystemIntegerRes(mContext,
+                ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
         for(Mode m : Mode.values()) {
             if (m.resValue == modeInt) {
                 mMode = m;
@@ -104,6 +138,12 @@
         }
     }
 
+    private void dispatchOneHandedOverlayChange() {
+        for (OneHandedModeChangeListener listener : mOneHandedOverlayChangeListeners) {
+            listener.onOneHandedModeChanged(mNavBarGesturalHeight);
+        }
+    }
+
     public Mode addModeChangeListener(NavigationModeChangeListener listener) {
         mChangeListeners.add(listener);
         return mMode;
@@ -113,6 +153,15 @@
         mChangeListeners.remove(listener);
     }
 
+    public int addOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
+        mOneHandedOverlayChangeListeners.add(listener);
+        return mNavBarGesturalHeight;
+    }
+
+    public void removeOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
+        mOneHandedOverlayChangeListeners.remove(listener);
+    }
+
     public Mode getMode() {
         return mMode;
     }
@@ -125,7 +174,7 @@
             return res.getInteger(resId);
         } else {
             Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
-            return -1;
+            return INVALID_RESOURCE_HANDLE;
         }
     }
 
@@ -150,4 +199,9 @@
 
         void onNavigationModeChanged(Mode newMode);
     }
+
+    public interface OneHandedModeChangeListener {
+
+        void onOneHandedModeChanged(int newGesturalHeight);
+    }
 }
\ No newline at end of file