Merge "Enabled haptics during long press nav handle" into main
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
index 3a206af..28d4bf8 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
@@ -171,13 +171,20 @@
             return;
         }
         pw.println("DeviceFlags:");
+        pw.println("  BooleanFlags:");
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
                 if (flag instanceof DeviceFlag) {
-                    pw.println("  " + flag);
+                    pw.println("    " + flag);
                 }
             }
         }
+        pw.println("  IntFlags:");
+        synchronized (sIntFlags) {
+            for (IntFlag flag : sIntFlags) {
+                pw.println("    " + flag);
+            }
+        }
         pw.println("DebugFlags:");
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
@@ -186,12 +193,6 @@
                 }
             }
         }
-        pw.println("IntFlags:");
-        synchronized (sIntFlags) {
-            for (IntFlag flag : sIntFlags) {
-                pw.println("  " + flag);
-            }
-        }
     }
 
     private void onPropertiesChanged(Properties properties) {
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 8d26fd4..db5ad82 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -23,9 +23,9 @@
 import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
 import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
 import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
-import static com.android.launcher3.util.NavigationMode.TWO_BUTTONS;
 import static com.android.launcher3.util.SettingsCache.ONE_HANDED_ENABLED;
 import static com.android.launcher3.util.SettingsCache.ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@@ -55,8 +55,11 @@
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.util.Log;
+import android.view.ISystemGestureExclusionListener;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
+import android.view.WindowManagerGlobal;
 
 import androidx.annotation.BinderThread;
 import androidx.annotation.NonNull;
@@ -74,7 +77,6 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
-import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 
@@ -86,6 +88,8 @@
  */
 public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
 
+    private static final String TAG = "RecentsAnimationDeviceState";
+
     static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
 
     // TODO: Move to quickstep contract
@@ -95,6 +99,23 @@
     private final Context mContext;
     private final DisplayController mDisplayController;
     private final int mDisplayId;
+
+    private final ISystemGestureExclusionListener mGestureExclusionListener =
+            new ISystemGestureExclusionListener.Stub() {
+                @BinderThread
+                @Override
+                public void onSystemGestureExclusionChanged(int displayId,
+                        Region systemGestureExclusionRegion, Region unrestrictedOrNull) {
+                    if (displayId != mDisplayId) {
+                        return;
+                    }
+                    // Assignments are atomic, it should be safe on binder thread. Also we don't
+                    // think systemGestureExclusionRegion can be null but just in case, don't let
+                    // mExclusionRegion be null.
+                    mExclusionRegion = systemGestureExclusionRegion != null
+                            ? systemGestureExclusionRegion : new Region();
+                }
+            };
     private final RotationTouchHelper mRotationTouchHelper;
     private final TaskStackChangeListener mPipListener;
     // Cache for better performance since it doesn't change at runtime.
@@ -118,7 +139,7 @@
 
     private int mGestureBlockingTaskId = -1;
     private @NonNull Region mExclusionRegion = new Region();
-    private SystemGestureExclusionListenerCompat mExclusionListener;
+    private boolean mExclusionListenerRegistered;
 
     public RecentsAnimationDeviceState(Context context) {
         this(context, false);
@@ -142,19 +163,7 @@
         }
 
         // Register for exclusion updates
-        mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) {
-            @Override
-            @BinderThread
-            public void onExclusionChanged(Region region) {
-                if (region == null) {
-                    // Don't think this is possible but just in case, don't let it be null.
-                    region = new Region();
-                }
-                // Assignments are atomic, it should be safe on binder thread
-                mExclusionRegion = region;
-            }
-        };
-        runOnDestroy(mExclusionListener::unregister);
+        runOnDestroy(() -> unregisterExclusionListener());
 
         // Register for display changes changes
         mDisplayController.addChangeListener(this);
@@ -247,13 +256,54 @@
             mNavBarPosition = new NavBarPosition(mMode, info);
 
             if (mMode == NO_BUTTON) {
-                mExclusionListener.register();
+                registerExclusionListener();
             } else {
-                mExclusionListener.unregister();
+                unregisterExclusionListener();
             }
         }
     }
 
+    /**
+     * Registers {@link mGestureExclusionListener} for getting exclusion rect changes. Note that we
+     * make binder call on {@link UI_HELPER_EXECUTOR} to avoid jank.
+     */
+    public void registerExclusionListener() {
+        UI_HELPER_EXECUTOR.execute(() -> {
+            if (mExclusionListenerRegistered) {
+                return;
+            }
+            try {
+                WindowManagerGlobal.getWindowManagerService()
+                        .registerSystemGestureExclusionListener(
+                                mGestureExclusionListener, mDisplayId);
+                mExclusionListenerRegistered = true;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to register window manager callbacks", e);
+            }
+        });
+    }
+
+    /**
+     * Unregisters {@link mGestureExclusionListener} if previously registered. We make binder call
+     * on same {@link UI_HELPER_EXECUTOR} as in {@link #registerExclusionListener()} so that
+     * read/write {@link mExclusionListenerRegistered} field is thread safe.
+     */
+    public void unregisterExclusionListener() {
+        UI_HELPER_EXECUTOR.execute(() -> {
+            if (!mExclusionListenerRegistered) {
+                return;
+            }
+            try {
+                WindowManagerGlobal.getWindowManagerService()
+                        .unregisterSystemGestureExclusionListener(
+                                mGestureExclusionListener, mDisplayId);
+                mExclusionListenerRegistered = false;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to unregister window manager callbacks", e);
+            }
+        });
+    }
+
     public void onOneHandedModeChanged(int newGesturalHeight) {
         mRotationTouchHelper.setGesturalHeight(newGesturalHeight);
     }
@@ -280,13 +330,6 @@
     }
 
     /**
-     * @return whether the current nav mode is 2-button-based.
-     */
-    public boolean isTwoButtonNavMode() {
-        return mMode == TWO_BUTTONS;
-    }
-
-    /**
      * @return whether the current nav mode is button-based.
      */
     public boolean isButtonNavMode() {
@@ -391,13 +434,6 @@
     }
 
     /**
-     * @return whether notification panel is expanded
-     */
-    public boolean isNotificationPanelExpanded() {
-        return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
-    }
-
-    /**
      * @return whether the global actions dialog is showing
      */
     public boolean isSystemUiDialogShowing() {
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index d53922b..b5709f7 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -402,6 +402,17 @@
     }
 
     @Override
+    public void animateNavBarLongPress(boolean isTouchDown, long durationMs) {
+        if (mSystemUiProxy != null) {
+            try {
+                mSystemUiProxy.animateNavBarLongPress(isTouchDown, durationMs);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call animateNavBarLongPress", e);
+            }
+        }
+    }
+
+    @Override
     public void notifyAccessibilityButtonClicked(int displayId) {
         if (mSystemUiProxy != null) {
             try {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
index 32f7bd5..ed4f7b8 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -38,7 +38,6 @@
     private final NavHandleLongPressHandler mNavHandleLongPressHandler;
     private final float mNavHandleWidth;
     private final float mScreenWidth;
-    private final ViewConfiguration mViewConfiguration;
 
     private final Runnable mTriggerLongPress = this::triggerLongPress;
     private final float mTouchSlopSquared;
@@ -49,7 +48,6 @@
     public NavHandleLongPressInputConsumer(Context context, InputConsumer delegate,
             InputMonitorCompat inputMonitor, RecentsAnimationDeviceState deviceState) {
         super(delegate, inputMonitor);
-        mViewConfiguration = ViewConfiguration.get(context);
         mNavHandleWidth = context.getResources().getDimensionPixelSize(
                 R.dimen.navigation_home_handle_width);
         mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 3acca9f..73861c1 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -119,6 +119,10 @@
             getReleaseFlag(301680992, "CUSTOM_LPNH_THRESHOLDS", DISABLED,
                     "Add dev options to customize the LPNH trigger slop and milliseconds");
 
+    public static final BooleanFlag ANIMATE_LPNH =
+            getReleaseFlag(308693847, "ANIMATE_LPNH", TEAMFOOD,
+                    "Animates navbar when long pressing");
+
     public static final IntFlag LPNH_SLOP_PERCENTAGE =
             getIntFlag(301680992, "LPNH_SLOP_PERCENTAGE", 100,
                     "Controls touch slop percentage for lpnh");