Making navigation mode listener a singleton so that the change is dispatched
everywhere synchronously.

Change-Id: Iee8c5957d78dfad3fb03e814de0367adcaa0c98b
diff --git a/Android.bp b/Android.bp
index 1121a79..5acec37 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,7 +23,6 @@
     ],
     srcs: [
         "tests/tapl/**/*.java",
-        "quickstep/src/com/android/quickstep/SwipeUpSetting.java",
         "src/com/android/launcher3/util/SecureSettingsObserver.java",
         "src/com/android/launcher3/TestProtocol.java",
     ],
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
index 321861b..d9b9686 100644
--- a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -30,7 +30,7 @@
 import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
 import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
 import com.android.launcher3.util.TouchController;
-import com.android.quickstep.OverviewInteractionState;
+import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.views.IconRecentsView;
 
 import java.util.ArrayList;
@@ -52,8 +52,8 @@
             list.add(new LandscapeStatesTouchController(launcher));
             list.add(new LandscapeEdgeSwipeController(launcher));
         } else {
-            boolean allowDragToOverview = OverviewInteractionState.INSTANCE.get(launcher)
-                    .isSwipeUpGestureEnabled();
+            boolean allowDragToOverview = SysUINavigationMode.INSTANCE.get(launcher)
+                    .getMode().hasGestures;
             list.add(new PortraitStatesTouchController(launcher, allowDragToOverview));
         }
         if (FeatureFlags.PULL_DOWN_STATUS_BAR && Utilities.IS_DEBUG_DEVICE
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
index d0a2f27..36014a9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -20,7 +20,6 @@
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.config.FeatureFlags.SWIPE_HOME;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
@@ -39,7 +38,8 @@
 import com.android.launcher3.util.TouchController;
 import com.android.launcher3.util.UiThreadHelper;
 import com.android.launcher3.util.UiThreadHelper.AsyncCommand;
-import com.android.quickstep.OverviewInteractionState;
+import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 
@@ -58,15 +58,11 @@
     private static final float RECENTS_PREPARE_SCALE = 1.33f;
 
     public static TouchController[] createTouchControllers(Launcher launcher) {
-        boolean swipeUpEnabled = OverviewInteractionState.INSTANCE.get(launcher)
-                .isSwipeUpGestureEnabled();
-        boolean swipeUpToHome = swipeUpEnabled && SWIPE_HOME.get();
-
+        Mode mode = SysUINavigationMode.INSTANCE.get(launcher).getMode();
 
         ArrayList<TouchController> list = new ArrayList<>();
         list.add(launcher.getDragController());
-
-        if (swipeUpToHome) {
+        if (mode == Mode.NO_BUTTON) {
             list.add(new QuickSwitchTouchController(launcher));
             list.add(new FlingAndHoldTouchController(launcher));
         } else {
@@ -75,8 +71,8 @@
                 list.add(new LandscapeEdgeSwipeController(launcher));
             } else {
                 list.add(new PortraitStatesTouchController(launcher,
-                        swipeUpEnabled /* allowDragToOverview */));
-                if (swipeUpEnabled) {
+                        mode.hasGestures /* allowDragToOverview */));
+                if (mode.hasGestures) {
                     list.add(new QuickSwitchTouchController(launcher));
                 }
             }
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index a2219e8..62d954b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -38,7 +38,7 @@
 import com.android.launcher3.util.PendingAnimation;
 import com.android.launcher3.util.TouchController;
 import com.android.launcher3.views.BaseDragLayer;
-import com.android.quickstep.OverviewInteractionState;
+import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 
@@ -123,8 +123,7 @@
                     if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer()
                             .isEventOverView(view, ev)) {
                         mTaskBeingDragged = view;
-                        if (!OverviewInteractionState.INSTANCE.get(mActivity)
-                                .isSwipeUpGestureEnabled()) {
+                        if (!SysUINavigationMode.INSTANCE.get(mActivity).getMode().hasGestures) {
                             // Don't allow swipe down to open if we don't support swipe up
                             // to enter overview.
                             directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
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 8fe0461..323dd9a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -44,10 +44,10 @@
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.EventLogArray;
 import com.android.launcher3.util.LooperExecutor;
 import com.android.launcher3.util.UiThreadHelper;
+import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -315,8 +315,8 @@
                 mOverviewComponentObserver.getActivityControlHelper();
         if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher) {
             return InputConsumer.NO_OP;
-        } else if (mAssistantAvailable && mOverviewInteractionState.isSwipeUpGestureEnabled()
-                && FeatureFlags.ENABLE_ASSISTANT_GESTURE.get()
+        } else if (mAssistantAvailable
+                && SysUINavigationMode.INSTANCE.get(this).getMode() == Mode.NO_BUTTON
                 && AssistantTouchConsumer.withinTouchRegion(this, event)) {
             return new AssistantTouchConsumer(this, mISystemUiProxy, !activityControl.isResumed()
                             ? createOtherActivityInputConsumer(event, runningTaskInfo) : null);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 8da1d2b..329436b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -32,9 +32,7 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.util.AttributeSet;
-import android.util.FloatProperty;
 import android.view.View;
-import android.view.ViewDebug;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
@@ -44,7 +42,7 @@
 import com.android.launcher3.util.PendingAnimation;
 import com.android.launcher3.views.BaseDragLayer;
 import com.android.launcher3.views.ScrimView;
-import com.android.quickstep.OverviewInteractionState;
+import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.hints.ChipsContainer;
 import com.android.quickstep.util.ClipAnimationHelper;
 import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
@@ -132,7 +130,7 @@
             ClipAnimationHelper helper) {
         AnimatorSet anim = super.createAdjacentPageAnimForTaskLaunch(tv, helper);
 
-        if (!OverviewInteractionState.INSTANCE.get(mActivity).isSwipeUpGestureEnabled()) {
+        if (!SysUINavigationMode.INSTANCE.get(mActivity).getMode().hasGestures) {
             // Hotseat doesn't move when opening recents with the button,
             // so don't animate it here either.
             return anim;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index 25e1c89..6d730b6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -41,8 +41,11 @@
 import com.android.launcher3.LauncherStateManager.StateHandler;
 import com.android.launcher3.QuickstepAppTransitionManagerImpl;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.dragndrop.DragLayer;
 import com.android.quickstep.OverviewInteractionState;
 import com.android.quickstep.RecentsModel;
+import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
 import com.android.quickstep.util.RemoteFadeOutAnimationListener;
 import com.android.systemui.shared.system.ActivityCompat;
 
@@ -52,8 +55,11 @@
 
 public class UiFactory extends RecentsUiFactory {
 
-    public static void setOnTouchControllersChangedListener(Context context, Runnable listener) {
-        OverviewInteractionState.INSTANCE.get(context).setOnSwipeUpSettingChangedListener(listener);
+    public static Runnable enableLiveTouchControllerChanges(DragLayer dl) {
+        NavigationModeChangeListener listener = m -> dl.recreateControllers();
+        SysUINavigationMode mode = SysUINavigationMode.INSTANCE.get(dl.getContext());
+        mode.addModeChangeListener(listener);
+        return () -> mode.removeModeChangeListener(listener);
     }
 
     public static StateHandler[] getStateHandler(Launcher launcher) {
@@ -89,8 +95,8 @@
 
                 @Override
                 public void onStateTransitionComplete(LauncherState finalState) {
-                    boolean swipeUpEnabled = OverviewInteractionState.INSTANCE.get(launcher)
-                            .isSwipeUpGestureEnabled();
+                    boolean swipeUpEnabled = SysUINavigationMode.INSTANCE.get(launcher).getMode()
+                            .hasGestures;
                     LauncherState prevState = launcher.getStateManager().getLastState();
 
                     if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled
diff --git a/quickstep/src/com/android/quickstep/NavBarModeOverlayResourceObserver.java b/quickstep/src/com/android/quickstep/NavBarModeOverlayResourceObserver.java
deleted file mode 100644
index 3136632..0000000
--- a/quickstep/src/com/android/quickstep/NavBarModeOverlayResourceObserver.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.util.Log;
-
-import com.android.systemui.shared.system.QuickStepContract;
-
-/**
- * Observer for the resource config that specifies the navigation bar mode.
- */
-public class NavBarModeOverlayResourceObserver extends BroadcastReceiver {
-
-    private static final String TAG = "NavBarModeOverlayResourceObserver";
-
-    private final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
-    private static final String NAV_BAR_INTERACTION_MODE_RES_NAME =
-            "config_navBarInteractionMode";
-
-    private final Context mContext;
-    private final OnChangeListener mOnChangeListener;
-
-    public NavBarModeOverlayResourceObserver(Context context, OnChangeListener listener) {
-        mContext = context;
-        mOnChangeListener = listener;
-    }
-
-    public void register() {
-        IntentFilter filter = new IntentFilter(ACTION_OVERLAY_CHANGED);
-        filter.addDataScheme("package");
-        mContext.registerReceiver(this, filter);
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        mOnChangeListener.onNavBarModeChanged(getSystemIntegerRes(context,
-                NAV_BAR_INTERACTION_MODE_RES_NAME));
-    }
-
-    public interface OnChangeListener {
-        void onNavBarModeChanged(int mode);
-    }
-
-    public static boolean isSwipeUpModeEnabled(Context context) {
-        return QuickStepContract.isSwipeUpMode(getSystemIntegerRes(context,
-                NAV_BAR_INTERACTION_MODE_RES_NAME));
-    }
-
-    public static boolean isEdgeToEdgeModeEnabled(Context context) {
-        return QuickStepContract.isGesturalMode(getSystemIntegerRes(context,
-                NAV_BAR_INTERACTION_MODE_RES_NAME));
-    }
-
-    public static boolean isLegacyModeEnabled(Context context) {
-        return QuickStepContract.isLegacyMode(getSystemIntegerRes(context,
-                NAV_BAR_INTERACTION_MODE_RES_NAME));
-    }
-
-    private static int getSystemIntegerRes(Context context, String resName) {
-        Resources res = context.getResources();
-        int resId = res.getIdentifier(resName, "integer", "android");
-
-        if (resId != 0) {
-            return res.getInteger(resId);
-        } else {
-            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
-            return -1;
-        }
-    }
-}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 903701d..ce472c6 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -30,8 +30,8 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.UiThreadHelper;
+import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.systemui.shared.recents.ISystemUiProxy;
-import com.android.systemui.shared.system.QuickStepContract;
 
 import androidx.annotation.WorkerThread;
 
@@ -56,10 +56,7 @@
 
     private static final int MSG_SET_PROXY = 200;
     private static final int MSG_SET_BACK_BUTTON_ALPHA = 201;
-    private static final int MSG_SET_SWIPE_UP_ENABLED = 202;
-
-    // TODO: Discriminate between swipe up and edge to edge
-    private final NavBarModeOverlayResourceObserver mSwipeUpSettingObserver;
+    private static final int MSG_APPLY_FLAGS = 202;
 
     private final Context mContext;
     private final Handler mUiHandler;
@@ -70,8 +67,6 @@
     private boolean mSwipeUpEnabled;
     private float mBackButtonAlpha = 1;
 
-    private Runnable mOnSwipeUpSettingChangedListener;
-
     private OverviewInteractionState(Context context) {
         mContext = context;
 
@@ -81,20 +76,8 @@
         mUiHandler = new Handler(this::handleUiMessage);
         mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
 
-        mSwipeUpEnabled = NavBarModeOverlayResourceObserver.isSwipeUpModeEnabled(mContext)
-                || NavBarModeOverlayResourceObserver.isEdgeToEdgeModeEnabled(mContext);
-        if (SwipeUpSetting.isSystemNavigationSettingAvailable()) {
-            mSwipeUpSettingObserver = new NavBarModeOverlayResourceObserver(context,
-                    this::notifySwipeUpSettingChanged);
-            mSwipeUpSettingObserver.register();
-            resetHomeBounceSeenOnQuickstepEnabledFirstTime();
-        } else {
-            mSwipeUpSettingObserver = null;
-        }
-    }
-
-    public boolean isSwipeUpGestureEnabled() {
-        return mSwipeUpEnabled;
+        onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(context)
+                .addModeChangeListener(this::onNavigationModeChanged));
     }
 
     public float getBackButtonAlpha() {
@@ -130,23 +113,13 @@
             case MSG_SET_BACK_BUTTON_ALPHA:
                 applyBackButtonAlpha((float) msg.obj, msg.arg1 == 1);
                 return true;
-            case MSG_SET_SWIPE_UP_ENABLED:
-                mSwipeUpEnabled = msg.arg1 != 0;
-                resetHomeBounceSeenOnQuickstepEnabledFirstTime();
-
-                if (mOnSwipeUpSettingChangedListener != null) {
-                    mOnSwipeUpSettingChangedListener.run();
-                }
+            case MSG_APPLY_FLAGS:
                 break;
         }
         applyFlags();
         return true;
     }
 
-    public void setOnSwipeUpSettingChangedListener(Runnable listener) {
-        mOnSwipeUpSettingChangedListener = listener;
-    }
-
     @WorkerThread
     private void applyFlags() {
         if (mISystemUiProxy == null) {
@@ -176,16 +149,12 @@
         }
     }
 
-    private void notifySwipeUpSettingChanged(int mode) {
-        boolean swipeUpEnabled = !QuickStepContract.isLegacyMode(mode);
-        boolean gesturalEnabled = QuickStepContract.isGesturalMode(mode);
+    private void onNavigationModeChanged(SysUINavigationMode.Mode mode) {
+        FeatureFlags.SWIPE_HOME.updateStorage(mContext, mode == Mode.NO_BUTTON);
 
-        FeatureFlags.SWIPE_HOME.updateStorage(mContext, gesturalEnabled);
-        FeatureFlags.ENABLE_ASSISTANT_GESTURE.updateStorage(mContext, gesturalEnabled);
-
-        mUiHandler.removeMessages(MSG_SET_SWIPE_UP_ENABLED);
-        mUiHandler.obtainMessage(MSG_SET_SWIPE_UP_ENABLED, swipeUpEnabled ? 1 : 0, 0).
-                sendToTarget();
+        mSwipeUpEnabled = mode.hasGestures;
+        resetHomeBounceSeenOnQuickstepEnabledFirstTime();
+        mBgHandler.obtainMessage(MSG_APPLY_FLAGS).sendToTarget();
     }
 
     private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
diff --git a/quickstep/src/com/android/quickstep/SwipeUpSetting.java b/quickstep/src/com/android/quickstep/SwipeUpSetting.java
deleted file mode 100644
index 7f830f9..0000000
--- a/quickstep/src/com/android/quickstep/SwipeUpSetting.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep;
-
-import android.content.res.Resources;
-import android.util.Log;
-
-public final class SwipeUpSetting {
-    private static final String TAG = "SwipeUpSetting";
-
-    private static final String SWIPE_UP_SETTING_AVAILABLE_RES_NAME =
-            "config_swipe_up_gesture_setting_available";
-
-    public static boolean isSystemNavigationSettingAvailable() {
-        return getSystemBooleanRes(SWIPE_UP_SETTING_AVAILABLE_RES_NAME);
-    }
-
-    private static boolean getSystemBooleanRes(String resName) {
-        Resources res = Resources.getSystem();
-        int resId = res.getIdentifier(resName, "bool", "android");
-
-        if (resId != 0) {
-            return res.getBoolean(resId);
-        } else {
-            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
-            return false;
-        }
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
new file mode 100644
index 0000000..3773143
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.util.Log;
+
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.systemui.shared.system.QuickStepContract;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Observer for the resource config that specifies the navigation bar mode.
+ */
+public class SysUINavigationMode {
+
+    public enum Mode {
+        THREE_BUTTONS(false),
+        TWO_BUTTONS(true),
+        NO_BUTTON(true);
+
+        public final boolean hasGestures;
+
+        Mode(boolean hasGestures) {
+            this.hasGestures = hasGestures;
+        }
+    }
+
+    public static MainThreadInitializedObject<SysUINavigationMode> INSTANCE =
+            new MainThreadInitializedObject<>(SysUINavigationMode::new);
+
+    private static final String TAG = "SysUINavigationMode";
+
+    private final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
+    private static final String NAV_BAR_INTERACTION_MODE_RES_NAME =
+            "config_navBarInteractionMode";
+
+    private final Context mContext;
+    private Mode mMode;
+
+    private final List<NavigationModeChangeListener> mChangeListeners = new ArrayList<>();
+
+    public SysUINavigationMode(Context context) {
+        mContext = context;
+        initializeMode();
+
+        IntentFilter filter = new IntentFilter(ACTION_OVERLAY_CHANGED);
+        filter.addDataScheme("package");
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Mode oldMode = mMode;
+                initializeMode();
+                if (mMode != oldMode) {
+                    dispatchModeChange();
+                }
+            }
+        }, filter);
+    }
+
+    private void initializeMode() {
+        int modeInt = getSystemIntegerRes(mContext, NAV_BAR_INTERACTION_MODE_RES_NAME);
+
+        if (QuickStepContract.isGesturalMode(modeInt)) {
+            mMode = Mode.NO_BUTTON;
+        } else if (QuickStepContract.isSwipeUpMode(modeInt)) {
+            mMode = Mode.TWO_BUTTONS;
+        } else {
+            mMode = Mode.THREE_BUTTONS;
+        }
+    }
+
+    private void dispatchModeChange() {
+        for (NavigationModeChangeListener listener : mChangeListeners) {
+            listener.onNavigationModeChanged(mMode);
+        }
+    }
+
+    public Mode addModeChangeListener(NavigationModeChangeListener listener) {
+        mChangeListeners.add(listener);
+        return mMode;
+    }
+
+    public void removeModeChangeListener(NavigationModeChangeListener listener) {
+        mChangeListeners.remove(listener);
+    }
+
+    public Mode getMode() {
+        return mMode;
+    }
+
+    private static int getSystemIntegerRes(Context context, String resName) {
+        Resources res = context.getResources();
+        int resId = res.getIdentifier(resName, "integer", "android");
+
+        if (resId != 0) {
+            return res.getInteger(resId);
+        } else {
+            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
+            return -1;
+        }
+    }
+
+    public interface NavigationModeChangeListener {
+
+        void onNavigationModeChanged(Mode newMode);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 867001a..89236aa 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -257,6 +257,7 @@
     public ViewGroupFocusHelper mFocusHandler;
 
     private RotationHelper mRotationHelper;
+    private Runnable mCancelTouchController;
 
     final Handler mHandler = new Handler();
     private final Runnable mHandleDeferredResume = this::handleDeferredResume;
@@ -946,7 +947,7 @@
 
         // Setup the drag layer
         mDragLayer.setup(mDragController, mWorkspace);
-        UiFactory.setOnTouchControllersChangedListener(this, mDragLayer::recreateControllers);
+        mCancelTouchController = UiFactory.enableLiveTouchControllerChanges(mDragLayer);
 
         mWorkspace.setup(mDragController);
         // Until the workspace is bound, ensure that we keep the wallpaper offset locked to the
@@ -1318,7 +1319,10 @@
         unregisterReceiver(mScreenOffReceiver);
         mWorkspace.removeFolderListeners();
 
-        UiFactory.setOnTouchControllersChangedListener(this, null);
+        if (mCancelTouchController != null) {
+            mCancelTouchController.run();
+            mCancelTouchController = null;
+        }
 
         // Stop callbacks from LauncherModel
         // It's possible to receive onDestroy after a new Launcher activity has
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 106d901..656151f 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -118,10 +118,6 @@
             "ENABLE_HINTS_IN_OVERVIEW", false,
             "Show chip hints and gleams on the overview screen");
 
-    public static final TogglableFlag ENABLE_ASSISTANT_GESTURE = new ToggleableGlobalSettingsFlag(
-            "ENABLE_ASSISTANT_GESTURE", false,
-            "Enable swipe up from the bottom right corner to start assistant");
-
     public static void initialize(Context context) {
         // Avoid the disk read for user builds
         if (Utilities.IS_DEBUG_DEVICE) {
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index 0d727fd..9939c25 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -22,6 +22,7 @@
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.util.TouchController;
 
 import java.io.PrintWriter;
@@ -33,7 +34,9 @@
                 launcher.getDragController(), new AllAppsSwipeController(launcher)};
     }
 
-    public static void setOnTouchControllersChangedListener(Context context, Runnable listener) { }
+    public static Runnable enableLiveTouchControllerChanges(DragLayer dl) {
+        return null;
+    }
 
     public static StateHandler[] getStateHandler(Launcher launcher) {
         return new StateHandler[] {
diff --git a/tests/Android.mk b/tests/Android.mk
index ca7395a..080c98b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -30,7 +30,6 @@
     LOCAL_STATIC_JAVA_LIBRARIES += libSharedSystemUI
 
     LOCAL_SRC_FILES := $(call all-java-files-under, tapl) \
-        ../quickstep/src/com/android/quickstep/SwipeUpSetting.java \
         ../src/com/android/launcher3/util/SecureSettingsObserver.java \
         ../src/com/android/launcher3/TestProtocol.java
 endif