Clean up navigation bar

- Move off fragments, now we have direct ownership of
  NavBarController -> NavBar (per display) -> NavBarView
- Move the nav bar components to its own package
- Removed some unused files
- Can finally dump NavigationBarController instead of FragmentService :)
- Clean up some of the dumps to be more consistent

Bug: 163690441
Bug: 158605244
Test: atest SystemUITests
Test: Test bar in various nav modes

Change-Id: I21130899df560f6cf8b7f38d4d86edca6d8f920e
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index f242157..92e7d88 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -1,9 +1,9 @@
--keep class com.android.systemui.statusbar.policy.KeyButtonView {
+-keep class com.android.systemui.navigationbar.buttons.KeyButtonView {
   public float getDrawingAlpha();
   public void setDrawingAlpha(float);
 }
 
--keep class com.android.systemui.statusbar.policy.KeyButtonRipple {
+-keep class com.android.systemui.navigationbar.buttons.KeyButtonRipple {
   public float getGlowAlpha();
   public float getGlowScale();
   public void setGlowAlpha(float);
diff --git a/packages/SystemUI/res/layout/back.xml b/packages/SystemUI/res/layout/back.xml
index 4e8726b..046aecd 100644
--- a/packages/SystemUI/res/layout/back.xml
+++ b/packages/SystemUI/res/layout/back.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<com.android.systemui.statusbar.policy.KeyButtonView
+<com.android.systemui.navigationbar.buttons.KeyButtonView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/back"
diff --git a/packages/SystemUI/res/layout/contextual.xml b/packages/SystemUI/res/layout/contextual.xml
index 90a7768..2cd7926 100644
--- a/packages/SystemUI/res/layout/contextual.xml
+++ b/packages/SystemUI/res/layout/contextual.xml
@@ -24,7 +24,7 @@
              android:clipChildren="false"
              android:clipToPadding="false"
              >
-    <com.android.systemui.statusbar.policy.KeyButtonView
+    <com.android.systemui.navigationbar.buttons.KeyButtonView
         android:id="@+id/menu"
         android:layout_height="match_parent"
         android:layout_width="match_parent"
@@ -47,7 +47,7 @@
              android:layout_height="match_parent"
              android:visibility="invisible"
     />
-    <com.android.systemui.statusbar.policy.KeyButtonView
+    <com.android.systemui.navigationbar.buttons.KeyButtonView
         android:id="@+id/accessibility_button"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/custom_key.xml b/packages/SystemUI/res/layout/custom_key.xml
index 0b5cb72..dc65777 100644
--- a/packages/SystemUI/res/layout/custom_key.xml
+++ b/packages/SystemUI/res/layout/custom_key.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.systemui.statusbar.policy.KeyButtonView
+<com.android.systemui.navigationbar.buttons.KeyButtonView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_width="@dimen/navigation_side_padding"
diff --git a/packages/SystemUI/res/layout/home.xml b/packages/SystemUI/res/layout/home.xml
index 9586327..84eed6a 100644
--- a/packages/SystemUI/res/layout/home.xml
+++ b/packages/SystemUI/res/layout/home.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.systemui.statusbar.policy.KeyButtonView
+<com.android.systemui.navigationbar.buttons.KeyButtonView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/home"
diff --git a/packages/SystemUI/res/layout/home_handle.xml b/packages/SystemUI/res/layout/home_handle.xml
index 54a0b9f..c9d3f98 100644
--- a/packages/SystemUI/res/layout/home_handle.xml
+++ b/packages/SystemUI/res/layout/home_handle.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License.
   -->
 
-<com.android.systemui.statusbar.phone.NavigationHandle
+<com.android.systemui.navigationbar.gestural.NavigationHandle
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/home_handle"
     android:layout_width="@dimen/navigation_home_handle_width"
diff --git a/packages/SystemUI/res/layout/ime_switcher.xml b/packages/SystemUI/res/layout/ime_switcher.xml
index 7710b25..a2c8308 100644
--- a/packages/SystemUI/res/layout/ime_switcher.xml
+++ b/packages/SystemUI/res/layout/ime_switcher.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.policy.KeyButtonView
+<com.android.systemui.navigationbar.buttons.KeyButtonView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/ime_switcher"
     android:layout_width="@dimen/navigation_key_width"
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index df717f6..0bb622b 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -25,7 +25,7 @@
     are placed inside a view that has a size controlled by weight. Ensure weight is large enough to
     support icon size. Use layout_width=navigation_side_padding like other navbar buttons. -->
 
-    <com.android.systemui.statusbar.policy.KeyButtonView
+    <com.android.systemui.navigationbar.buttons.KeyButtonView
         android:id="@+id/menu"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -43,7 +43,7 @@
         android:paddingStart="0dp"
         android:paddingEnd="0dp"
         />
-    <com.android.systemui.statusbar.policy.KeyButtonView
+    <com.android.systemui.navigationbar.buttons.KeyButtonView
         android:id="@+id/rotate_suggestion"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -51,7 +51,7 @@
         android:scaleType="centerInside"
         android:contentDescription="@string/accessibility_rotate_button"
         />
-    <com.android.systemui.statusbar.policy.KeyButtonView
+    <com.android.systemui.navigationbar.buttons.KeyButtonView
         android:id="@+id/accessibility_button"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index ba6b695..23f36a9 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -17,9 +17,10 @@
 */
 -->
 
-<com.android.systemui.statusbar.phone.NavigationBarView
+<com.android.systemui.navigationbar.NavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/navigation_bar_view"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     android:background="@drawable/system_bar_background">
@@ -39,9 +40,9 @@
         android:rotation="180"
         android:visibility="gone"/>
 
-    <com.android.systemui.statusbar.phone.NavigationBarInflaterView
+    <com.android.systemui.navigationbar.NavigationBarInflaterView
         android:id="@+id/navigation_inflater"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-</com.android.systemui.statusbar.phone.NavigationBarView>
+</com.android.systemui.navigationbar.NavigationBarView>
diff --git a/packages/SystemUI/res/layout/navigation_bar_window.xml b/packages/SystemUI/res/layout/navigation_bar_window.xml
index f98cbd8..b2473cd 100644
--- a/packages/SystemUI/res/layout/navigation_bar_window.xml
+++ b/packages/SystemUI/res/layout/navigation_bar_window.xml
@@ -16,7 +16,7 @@
 ** limitations under the License.
 */
 -->
-<com.android.systemui.statusbar.phone.NavigationBarFrame
+<com.android.systemui.navigationbar.NavigationBarFrame
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/navigation_bar_frame"
@@ -24,4 +24,4 @@
     android:layout_height="match_parent"
     android:layout_width="match_parent">
 
-</com.android.systemui.statusbar.phone.NavigationBarFrame>
+</com.android.systemui.navigationbar.NavigationBarFrame>
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index db1c79d..0e576fb 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -25,7 +25,7 @@
     android:paddingEnd="@dimen/nav_content_padding"
     android:id="@+id/horizontal">
 
-    <com.android.systemui.statusbar.phone.NearestTouchFrame
+    <com.android.systemui.navigationbar.buttons.NearestTouchFrame
         android:id="@+id/nav_buttons"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -50,6 +50,6 @@
             android:clipToPadding="false"
             android:clipChildren="false" />
 
-    </com.android.systemui.statusbar.phone.NearestTouchFrame>
+    </com.android.systemui.navigationbar.buttons.NearestTouchFrame>
 
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_layout_vertical.xml b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
index 285c5c4..4b67700 100644
--- a/packages/SystemUI/res/layout/navigation_layout_vertical.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
@@ -25,14 +25,14 @@
     android:paddingBottom="@dimen/nav_content_padding"
     android:id="@+id/vertical">
 
-    <com.android.systemui.statusbar.phone.NearestTouchFrame
+    <com.android.systemui.navigationbar.buttons.NearestTouchFrame
         android:id="@+id/nav_buttons"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:clipChildren="false"
         android:clipToPadding="false">
 
-        <com.android.systemui.statusbar.phone.ReverseLinearLayout
+        <com.android.systemui.navigationbar.buttons.ReverseLinearLayout
             android:id="@+id/ends_group"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
@@ -40,7 +40,7 @@
             android:clipToPadding="false"
             android:clipChildren="false" />
 
-        <com.android.systemui.statusbar.phone.ReverseLinearLayout
+        <com.android.systemui.navigationbar.buttons.ReverseLinearLayout
             android:id="@+id/center_group"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
@@ -49,6 +49,6 @@
             android:clipToPadding="false"
             android:clipChildren="false" />
 
-    </com.android.systemui.statusbar.phone.NearestTouchFrame>
+    </com.android.systemui.navigationbar.buttons.NearestTouchFrame>
 
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/recent_apps.xml b/packages/SystemUI/res/layout/recent_apps.xml
index 870bcf7..e2b1374 100644
--- a/packages/SystemUI/res/layout/recent_apps.xml
+++ b/packages/SystemUI/res/layout/recent_apps.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<com.android.systemui.statusbar.policy.KeyButtonView
+<com.android.systemui.navigationbar.buttons.KeyButtonView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/recent_apps"
diff --git a/packages/SystemUI/res/layout/rotate_suggestion.xml b/packages/SystemUI/res/layout/rotate_suggestion.xml
index d7f67db..194d2e0 100644
--- a/packages/SystemUI/res/layout/rotate_suggestion.xml
+++ b/packages/SystemUI/res/layout/rotate_suggestion.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.policy.KeyButtonView
+<com.android.systemui.navigationbar.buttons.KeyButtonView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/rotate_suggestion"
     android:layout_width="match_parent"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index d6fabd6..6f19613 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -36,8 +36,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.phone.NavigationBarView;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.util.InjectionInflationController;
 
 public class KeyguardDisplayManager {
@@ -54,9 +54,6 @@
 
     private final SparseArray<Presentation> mPresentations = new SparseArray<>();
 
-    private final NavigationBarController mNavBarController =
-            Dependency.get(NavigationBarController.class);
-
     private final DisplayManager.DisplayListener mDisplayListener =
             new DisplayManager.DisplayListener() {
 
@@ -227,7 +224,8 @@
         // Leave this task to {@link StatusBarKeyguardViewManager}
         if (displayId == DEFAULT_DISPLAY) return;
 
-        NavigationBarView navBarView = mNavBarController.getNavigationBarView(displayId);
+        NavigationBarView navBarView = Dependency.get(NavigationBarController.class)
+                .getNavigationBarView(displayId);
         // We may not have nav bar on a display.
         if (navBarView == null) return;
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 58f8c07..10f2069 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -64,7 +64,7 @@
 import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -85,7 +85,7 @@
 import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index 0135e4c..1752579 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -130,8 +130,6 @@
 
     private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
 
-    private Recents mRecents;
-    private StatusBar mStatusBar;
     private SystemActionsBroadcastReceiver mReceiver;
     private Locale mLocale;
     private AccessibilityManager mA11yManager;
@@ -139,8 +137,6 @@
     @Inject
     public SystemActions(Context context) {
         super(context);
-        mRecents = Dependency.get(Recents.class);
-        mStatusBar = Dependency.get(StatusBar.class);
         mReceiver = new SystemActionsBroadcastReceiver();
         mLocale = mContext.getResources().getConfiguration().getLocales().get(0);
         mA11yManager = (AccessibilityManager) mContext.getSystemService(
@@ -317,15 +313,15 @@
     }
 
     private void handleRecents() {
-        mRecents.toggleRecentApps();
+        Dependency.get(Recents.class).toggleRecentApps();
     }
 
     private void handleNotifications() {
-        mStatusBar.animateExpandNotificationsPanel();
+        Dependency.get(StatusBar.class).animateExpandNotificationsPanel();
     }
 
     private void handleQuickSettings() {
-        mStatusBar.animateExpandSettingsPanel(null);
+        Dependency.get(StatusBar.class).animateExpandSettingsPanel(null);
     }
 
     private void handlePowerDialog() {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
index 7ae3e73..2df48fc 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
@@ -35,7 +35,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
index 5010f31..f19e53f 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
@@ -30,7 +30,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.CornerHandleView;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.NavigationBarTransitions;
+import com.android.systemui.navigationbar.NavigationBarTransitions;
 
 /**
  * A class for managing Assistant handle show, hide and animation.
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
index 6f5a17d..0dc06f2 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
@@ -25,7 +25,7 @@
 import androidx.slice.Clock;
 
 import com.android.internal.app.AssistUtils;
-import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarController;
 
 import java.util.EnumMap;
 import java.util.Map;
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index 05f3617..722e3124 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -41,7 +41,7 @@
 import com.android.systemui.assist.AssistLogger;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.assist.AssistantSessionEvent;
-import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarController;
 
 import java.util.Locale;
 
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index e5121a8..ac39ed5 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -33,9 +33,9 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.phone.NavigationBarFragment;
-import com.android.systemui.statusbar.phone.NavigationBarTransitions;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBar;
+import com.android.systemui.navigationbar.NavigationBarTransitions;
 
 import java.util.ArrayList;
 
@@ -284,7 +284,7 @@
                 return;
             }
 
-            NavigationBarFragment navBar = controller.getDefaultNavigationBarFragment();
+            NavigationBar navBar = controller.getDefaultNavigationBar();
             if (navBar == null) {
                 return;
             }
@@ -301,7 +301,7 @@
                 return;
             }
 
-            NavigationBarFragment navBar = controller.getDefaultNavigationBarFragment();
+            NavigationBar navBar = controller.getDefaultNavigationBar();
             if (navBar == null) {
                 return;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 3d31070..21bcfcd 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -31,6 +31,7 @@
 import android.view.IWindowManager;
 import android.view.LayoutInflater;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
@@ -40,6 +41,8 @@
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.Prefs;
 import com.android.systemui.accessibility.ModeSwitchesController;
+import com.android.systemui.accessibility.SystemActions;
+import com.android.systemui.assist.AssistManager;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger;
 import com.android.systemui.dagger.qualifiers.Background;
@@ -47,25 +50,38 @@
 import com.android.systemui.doze.AlwaysOnDisplayPolicy;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.PluginInitializerImpl;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.Recents;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginManagerImpl;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
+import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.util.leak.LeakDetector;
 
+import java.util.Optional;
 import java.util.concurrent.Executor;
 
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
@@ -159,8 +175,49 @@
     @Singleton
     @Provides
     public NavigationBarController provideNavigationBarController(Context context,
-            @Main Handler mainHandler, CommandQueue commandQueue) {
-        return new NavigationBarController(context, mainHandler, commandQueue);
+            WindowManager windowManager,
+            Lazy<AssistManager> assistManagerLazy,
+            AccessibilityManager accessibilityManager,
+            AccessibilityManagerWrapper accessibilityManagerWrapper,
+            DeviceProvisionedController deviceProvisionedController,
+            MetricsLogger metricsLogger,
+            OverviewProxyService overviewProxyService,
+            NavigationModeController navigationModeController,
+            StatusBarStateController statusBarStateController,
+            SysUiState sysUiFlagsContainer,
+            BroadcastDispatcher broadcastDispatcher,
+            CommandQueue commandQueue,
+            Divider divider,
+            Optional<Recents> recentsOptional,
+            Lazy<StatusBar> statusBarLazy,
+            ShadeController shadeController,
+            NotificationRemoteInputManager notificationRemoteInputManager,
+            SystemActions systemActions,
+            @Main Handler mainHandler,
+            UiEventLogger uiEventLogger,
+            ConfigurationController configurationController) {
+        return new NavigationBarController(context,
+                windowManager,
+                assistManagerLazy,
+                accessibilityManager,
+                accessibilityManagerWrapper,
+                deviceProvisionedController,
+                metricsLogger,
+                overviewProxyService,
+                navigationModeController,
+                statusBarStateController,
+                sysUiFlagsContainer,
+                broadcastDispatcher,
+                commandQueue,
+                divider,
+                recentsOptional,
+                statusBarLazy,
+                shadeController,
+                notificationRemoteInputManager,
+                systemActions,
+                mainHandler,
+                uiEventLogger,
+                configurationController);
     }
 
     @Singleton
@@ -230,6 +287,12 @@
     }
 
     /** */
+    @Provides
+    public SystemActions providesSystemActions(Context context) {
+        return new SystemActions(context);
+    }
+
+    /** */
     @Singleton
     @Provides
     public Choreographer providesChoreographer() {
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 0507592..e888869 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -22,7 +22,6 @@
 
 import com.android.systemui.Dumpable;
 import com.android.systemui.qs.QSFragment;
-import com.android.systemui.statusbar.phone.NavigationBarFragment;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import java.io.FileDescriptor;
@@ -126,10 +125,6 @@
             FragmentCreator build();
         }
         /**
-         * Inject a NavigationBarFragment.
-         */
-        NavigationBarFragment createNavigationBarFragment();
-        /**
          * Inject a QSFragment.
          */
         QSFragment createQSFragment();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d55ac7c..6214a64 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -93,7 +93,7 @@
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.DeviceConfigProxy;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index ab41afb..fc789a6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -29,7 +29,7 @@
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.InjectionInflationController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
similarity index 87%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index fd653b4..88400f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -1,18 +1,20 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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
+ * 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.
+ * 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.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
 import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
@@ -21,6 +23,7 @@
 import static android.app.StatusBarManager.WindowType;
 import static android.app.StatusBarManager.WindowVisibleState;
 import static android.app.StatusBarManager.windowStateToString;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.containsType;
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -78,17 +81,16 @@
 import android.util.Log;
 import android.view.Display;
 import android.view.Gravity;
+import android.view.IWindowManager;
 import android.view.InsetsState.InternalInsetsType;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.WindowInsetsController.Appearance;
 import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
@@ -102,6 +104,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.view.AppearanceRegion;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.accessibility.SystemActions;
 import com.android.systemui.assist.AssistHandleViewController;
@@ -109,8 +112,12 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
 import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
+import com.android.systemui.navigationbar.buttons.KeyButtonView;
+import com.android.systemui.navigationbar.buttons.RotationContextButton;
+import com.android.systemui.navigationbar.gestural.QuickswitchOrientedNavHandle;
+import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
@@ -123,29 +130,28 @@
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
-import com.android.systemui.statusbar.phone.ContextualButton.ContextButtonListener;
+import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.BarTransitions;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.KeyButtonView;
-import com.android.systemui.util.LifecycleFragment;
 
-import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
 import java.util.function.Consumer;
 
-import javax.inject.Inject;
-
 import dagger.Lazy;
 
 /**
- * Fragment containing the NavigationBarFragment. Contains logic for what happens
- * on clicks and view states of the nav bar.
+ * Contains logic for a navigation bar view.
  */
-public class NavigationBarFragment extends LifecycleFragment implements Callbacks,
-        NavigationModeController.ModeChangedListener, DisplayManager.DisplayListener {
+public class NavigationBar implements View.OnAttachStateChangeListener,
+        Callbacks, NavigationModeController.ModeChangedListener, DisplayManager.DisplayListener {
 
     public static final String TAG = "NavigationBar";
     private static final boolean DEBUG = false;
@@ -158,35 +164,41 @@
     private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
     private static final long AUTODIM_TIMEOUT_MS = 2250;
 
+    private final Context mContext;
+    private final WindowManager mWindowManager;
+    private final AccessibilityManager mAccessibilityManager;
     private final AccessibilityManagerWrapper mAccessibilityManagerWrapper;
-    protected final AssistManager mAssistManager;
-    private SysUiState mSysUiFlagsContainer;
-    private final MetricsLogger mMetricsLogger;
     private final DeviceProvisionedController mDeviceProvisionedController;
     private final StatusBarStateController mStatusBarStateController;
+    private final MetricsLogger mMetricsLogger;
+    private final Lazy<AssistManager> mAssistManagerLazy;
+    private final SysUiState mSysUiFlagsContainer;
+    private final Lazy<StatusBar> mStatusBarLazy;
+    private final ShadeController mShadeController;
+    private final NotificationRemoteInputManager mNotificationRemoteInputManager;
+    private final OverviewProxyService mOverviewProxyService;
     private final NavigationModeController mNavigationModeController;
+    private final BroadcastDispatcher mBroadcastDispatcher;
+    private final CommandQueue mCommandQueue;
+    private final Divider mDivider;
+    private final Optional<Recents> mRecentsOptional;
+    private final SystemActions mSystemActions;
+    private final Handler mHandler;
+    private final UiEventLogger mUiEventLogger;
 
-    protected NavigationBarView mNavigationBarView = null;
+    private Bundle mSavedState;
+    private NavigationBarView mNavigationBarView = null;
 
     private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
 
     private int mNavigationIconHints = 0;
     private @TransitionMode int mNavigationBarMode;
-    private AccessibilityManager mAccessibilityManager;
     private ContentResolver mContentResolver;
     private boolean mAssistantAvailable;
 
     private int mDisabledFlags1;
     private int mDisabledFlags2;
-    private final Lazy<StatusBar> mStatusBarLazy;
-    private final ShadeController mShadeController;
-    private final NotificationRemoteInputManager mNotificationRemoteInputManager;
-    private final Divider mDivider;
-    private final Optional<Recents> mRecentsOptional;
-    private WindowManager mWindowManager;
-    private final CommandQueue mCommandQueue;
     private long mLastLockToAppLongPress;
-    private final SystemActions mSystemActions;
 
     private Locale mLocale;
     private int mLayoutDirection;
@@ -202,10 +214,6 @@
     private LightBarController mLightBarController;
     private AutoHideController mAutoHideController;
 
-    private OverviewProxyService mOverviewProxyService;
-
-    private final BroadcastDispatcher mBroadcastDispatcher;
-
     @VisibleForTesting
     public int mDisplayId;
     private boolean mIsOnDefaultDisplay;
@@ -226,7 +234,6 @@
     private int mStartingQuickSwitchRotation = -1;
     private int mCurrentRotation;
     private ViewTreeObserver.OnGlobalLayoutListener mOrientationHandleGlobalLayoutListener;
-    private UiEventLogger mUiEventLogger;
     private boolean mShowOrientedHandleForImmersiveMode;
 
     @com.android.internal.annotations.VisibleForTesting
@@ -251,7 +258,6 @@
     @Nullable
     private AssistHandleViewController mAssistHandlerViewController;
 
-    private final Handler mHandler;
 
     private final AutoHideUiElement mAutoHideUiElement = new AutoHideUiElement() {
         @Override
@@ -307,7 +313,7 @@
 
         @Override
         public void startAssistant(Bundle bundle) {
-            mAssistManager.startAssist(bundle);
+            mAssistManagerLazy.get().startAssist(bundle);
         }
 
         @Override
@@ -360,7 +366,7 @@
             new Handler(Looper.getMainLooper())) {
         @Override
         public void onChange(boolean selfChange, Uri uri) {
-            boolean available = mAssistManager
+            boolean available = mAssistManagerLazy.get()
                     .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
             if (mAssistantAvailable != available) {
                 sendAssistantAvailability(available);
@@ -369,34 +375,6 @@
         }
     };
 
-    private static class NavBarViewAttachedListener implements View.OnAttachStateChangeListener {
-        private NavigationBarFragment mFragment;
-        private FragmentListener mListener;
-
-        NavBarViewAttachedListener(NavigationBarFragment fragment, FragmentListener listener) {
-            mFragment = fragment;
-            mListener = listener;
-        }
-
-        @Override
-        public void onViewAttachedToWindow(View v) {
-            final FragmentHostManager fragmentHost = FragmentHostManager.get(v);
-            fragmentHost.getFragmentManager().beginTransaction()
-                    .replace(R.id.navigation_bar_frame, mFragment, TAG)
-                    .commit();
-            fragmentHost.addTagListener(TAG, mListener);
-            mFragment = null;
-        }
-
-        @Override
-        public void onViewDetachedFromWindow(View v) {
-            final FragmentHostManager fragmentHost = FragmentHostManager.get(v);
-            fragmentHost.removeTagListener(TAG, mListener);
-            FragmentHostManager.removeAndDestroy(v);
-            v.removeOnAttachStateChangeListener(this);
-        }
-    }
-
     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
             new DeviceConfig.OnPropertiesChangedListener() {
         @Override
@@ -416,10 +394,14 @@
         }
     };
 
-    @Inject
-    public NavigationBarFragment(AccessibilityManagerWrapper accessibilityManagerWrapper,
-            DeviceProvisionedController deviceProvisionedController, MetricsLogger metricsLogger,
-            AssistManager assistManager, OverviewProxyService overviewProxyService,
+    public NavigationBar(Context context,
+            WindowManager windowManager,
+            Lazy<AssistManager> assistManagerLazy,
+            AccessibilityManager accessibilityManager,
+            AccessibilityManagerWrapper accessibilityManagerWrapper,
+            DeviceProvisionedController deviceProvisionedController,
+            MetricsLogger metricsLogger,
+            OverviewProxyService overviewProxyService,
             NavigationModeController navigationModeController,
             StatusBarStateController statusBarStateController,
             SysUiState sysUiFlagsContainer,
@@ -431,16 +413,18 @@
             SystemActions systemActions,
             @Main Handler mainHandler,
             UiEventLogger uiEventLogger) {
+        mContext = context;
+        mWindowManager = windowManager;
+        mAccessibilityManager = accessibilityManager;
         mAccessibilityManagerWrapper = accessibilityManagerWrapper;
         mDeviceProvisionedController = deviceProvisionedController;
         mStatusBarStateController = statusBarStateController;
         mMetricsLogger = metricsLogger;
-        mAssistManager = assistManager;
+        mAssistManagerLazy = assistManagerLazy;
         mSysUiFlagsContainer = sysUiFlagsContainer;
         mStatusBarLazy = statusBarLazy;
         mShadeController = shadeController;
         mNotificationRemoteInputManager = notificationRemoteInputManager;
-        mAssistantAvailable = mAssistManager.getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
         mOverviewProxyService = overviewProxyService;
         mNavigationModeController = navigationModeController;
         mNavBarMode = navigationModeController.addListener(this);
@@ -453,25 +437,53 @@
         mUiEventLogger = uiEventLogger;
     }
 
-    // ----- Fragment Lifecycle Callbacks -----
+    public View getView() {
+        return mNavigationBarView;
+    }
 
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mCommandQueue.observe(getLifecycle(), this);
-        mWindowManager = getContext().getSystemService(WindowManager.class);
-        mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
-        mContentResolver = getContext().getContentResolver();
+    public View createView(Bundle savedState) {
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
+                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
+                PixelFormat.TRANSLUCENT);
+        lp.token = new Binder();
+        lp.setTitle("NavigationBar" + mContext.getDisplayId());
+        lp.accessibilityTitle = mContext.getString(R.string.nav_bar);
+        lp.windowAnimations = 0;
+        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
+
+        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+        NavigationBarFrame frame = (NavigationBarFrame) layoutInflater.inflate(
+                R.layout.navigation_bar_window, null);
+        View barView = layoutInflater.inflate(R.layout.navigation_bar, frame);
+        barView.addOnAttachStateChangeListener(this);
+
+        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + barView);
+        mContext.getSystemService(WindowManager.class).addView(frame, lp);
+        mDisplayId = mContext.getDisplayId();
+        mIsOnDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
+
+        mCommandQueue.addCallback(this);
+        mAssistantAvailable = mAssistManagerLazy.get()
+                .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+        mContentResolver = mContext.getContentResolver();
         mContentResolver.registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
                 false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
 
-        if (savedInstanceState != null) {
-            mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
-            mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
-            mAppearance = savedInstanceState.getInt(EXTRA_APPEARANCE, 0);
-            mTransientShown = savedInstanceState.getBoolean(EXTRA_TRANSIENT_STATE, false);
+        if (savedState != null) {
+            mDisabledFlags1 = savedState.getInt(EXTRA_DISABLE_STATE, 0);
+            mDisabledFlags2 = savedState.getInt(EXTRA_DISABLE2_STATE, 0);
+            mAppearance = savedState.getInt(EXTRA_APPEARANCE, 0);
+            mTransientShown = savedState.getBoolean(EXTRA_TRANSIENT_STATE, false);
         }
+        mSavedState = savedState;
         mAccessibilityManagerWrapper.addCallback(mAccessibilityListener);
 
         // Respect the latest disabled-flags.
@@ -486,12 +498,16 @@
 
         mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
         mDeviceProvisionedController.addCallback(mUserSetupListener);
+
+        return barView;
     }
 
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
+    public void destroyView() {
+        mCommandQueue.removeCallback(this);
+        mContext.getSystemService(WindowManager.class).removeViewImmediate(
+                mNavigationBarView.getRootView());
         mNavigationModeController.removeListener(this);
+
         mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener);
         mContentResolver.unregisterContentObserver(mAssistContentObserver);
         mDeviceProvisionedController.removeCallback(mUserSetupListener);
@@ -500,28 +516,15 @@
     }
 
     @Override
-    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
-            Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.navigation_bar, container, false);
-    }
-
-    @Override
-    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        mNavigationBarView = (NavigationBarView) view;
-        final Display display = view.getDisplay();
-        // It may not have display when running unit test.
-        if (display != null) {
-            mDisplayId = display.getDisplayId();
-            mIsOnDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
-        }
-
+    public void onViewAttachedToWindow(View v) {
+        final Display display = v.getDisplay();
+        mNavigationBarView = v.findViewById(R.id.navigation_bar_view);
         mNavigationBarView.setComponents(mStatusBarLazy.get().getPanelController());
         mNavigationBarView.setDisabledFlags(mDisabledFlags1);
         mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged);
         mNavigationBarView.setOnTouchListener(this::onNavigationTouch);
-        if (savedInstanceState != null) {
-            mNavigationBarView.getLightTransitionsController().restoreState(savedInstanceState);
+        if (mSavedState != null) {
+            mNavigationBarView.getLightTransitionsController().restoreState(mSavedState);
         }
         mNavigationBarView.setNavigationIconHints(mNavigationIconHints);
         mNavigationBarView.setWindowVisible(isNavBarWindowVisible());
@@ -561,11 +564,32 @@
         }
 
         initSecondaryHomeHandleForRotation();
+
+        // Unfortunately, we still need it because status bar needs LightBarController
+        // before notifications creation. We cannot directly use getLightBarController()
+        // from NavigationBarFragment directly.
+        LightBarController lightBarController = mIsOnDefaultDisplay
+                ? Dependency.get(LightBarController.class)
+                : new LightBarController(mContext,
+                        Dependency.get(DarkIconDispatcher.class),
+                        Dependency.get(BatteryController.class),
+                        Dependency.get(NavigationModeController.class));
+        setLightBarController(lightBarController);
+
+        // TODO(b/118592525): to support multi-display, we start to add something which is
+        //                    per-display, while others may be global. I think it's time to
+        //                    add a new class maybe named DisplayDependency to solve
+        //                    per-display Dependency problem.
+        AutoHideController autoHideController = mIsOnDefaultDisplay
+                ? Dependency.get(AutoHideController.class)
+                : new AutoHideController(mContext, mHandler,
+                        Dependency.get(IWindowManager.class));
+        setAutoHideController(autoHideController);
+        restoreAppearanceAndTransientState();
     }
 
     @Override
-    public void onDestroyView() {
-        super.onDestroyView();
+    public void onViewDetachedFromWindow(View v) {
         if (mNavigationBarView != null) {
             if (mIsOnDefaultDisplay) {
                 mNavigationBarView.getBarTransitions()
@@ -573,13 +597,13 @@
                 mAssistHandlerViewController = null;
             }
             mNavigationBarView.getBarTransitions().destroy();
-            mNavigationBarView.getLightTransitionsController().destroy(getContext());
+            mNavigationBarView.getLightTransitionsController().destroy(mContext);
         }
         mOverviewProxyService.removeCallback(mOverviewProxyListener);
         mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
         if (mOrientationHandle != null) {
             resetSecondaryHandle();
-            getContext().getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+            mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
             getBarTransitions().removeDarkIntensityListener(mOrientationHandleIntensityListener);
             mWindowManager.removeView(mOrientationHandle);
             mOrientationHandle.getViewTreeObserver().removeOnGlobalLayoutListener(
@@ -590,9 +614,8 @@
         mOrientationHandle = null;
     }
 
-    @Override
+    // TODO: Remove this when we update nav bar recreation
     public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
         outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
         outState.putInt(EXTRA_DISABLE2_STATE, mDisabledFlags2);
         outState.putInt(EXTRA_APPEARANCE, mAppearance);
@@ -602,10 +625,11 @@
         }
     }
 
-    @Override
+    /**
+     * Called when a non-reloading configuration change happens and we need to update.
+     */
     public void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        final Locale locale = getContext().getResources().getConfiguration().locale;
+        final Locale locale = mContext.getResources().getConfiguration().locale;
         final int ld = TextUtils.getLayoutDirectionFromLocale(locale);
         if (!locale.equals(mLocale) || ld != mLayoutDirection) {
             if (DEBUG) {
@@ -625,10 +649,10 @@
             return;
         }
 
-        getContext().getSystemService(DisplayManager.class)
+        mContext.getSystemService(DisplayManager.class)
                 .registerDisplayListener(this, new Handler(Looper.getMainLooper()));
 
-        mOrientationHandle = new QuickswitchOrientedNavHandle(getContext());
+        mOrientationHandle = new QuickswitchOrientedNavHandle(mContext);
         mOrientationHandle.setId(R.id.secondary_home_handle);
 
         getBarTransitions().addDarkIntensityListener(mOrientationHandleIntensityListener);
@@ -640,7 +664,7 @@
                         | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                         | WindowManager.LayoutParams.FLAG_SLIPPERY,
                 PixelFormat.TRANSLUCENT);
-        mOrientationParams.setTitle("SecondaryHomeHandle" + getContext().getDisplayId());
+        mOrientationParams.setTitle("SecondaryHomeHandle" + mContext.getDisplayId());
         mOrientationParams.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
         mWindowManager.addView(mOrientationHandle, mOrientationParams);
         mOrientationHandle.setVisibility(View.GONE);
@@ -729,23 +753,20 @@
         return delta;
     }
 
-    @Override
-    public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mNavigationBarView != null) {
-            pw.print("  mNavigationBarWindowState=");
-            pw.println(windowStateToString(mNavigationBarWindowState));
-            pw.print("  mNavigationBarMode=");
-            pw.println(BarTransitions.modeToString(mNavigationBarMode));
-            dumpBarTransitions(pw, "mNavigationBarView", mNavigationBarView.getBarTransitions());
-        }
+    public void dump(PrintWriter pw) {
+        pw.println("NavigationBar (displayId=" + mDisplayId + "):");
+        pw.println("  mStartingQuickSwitchRotation=" + mStartingQuickSwitchRotation);
+        pw.println("  mCurrentRotation=" + mCurrentRotation);
 
-        pw.print("  mStartingQuickSwitchRotation=" + mStartingQuickSwitchRotation);
-        pw.print("  mCurrentRotation=" + mCurrentRotation);
-        pw.print("  mNavigationBarView=");
-        if (mNavigationBarView == null) {
-            pw.println("null");
+        if (mNavigationBarView != null) {
+            pw.println("  mNavigationBarWindowState="
+                    + windowStateToString(mNavigationBarWindowState));
+            pw.println("  mNavigationBarMode="
+                    + BarTransitions.modeToString(mNavigationBarMode));
+            dumpBarTransitions(pw, "mNavigationBarView", mNavigationBarView.getBarTransitions());
+            mNavigationBarView.dump(pw);
         } else {
-            mNavigationBarView.dump(fd, pw, args);
+            pw.print("  mNavigationBarView=null");
         }
     }
 
@@ -834,7 +855,7 @@
         rotationButtonController.onRotationProposal(rotation, winRotation, isValid);
     }
 
-    /** Restores the appearance and the transient saved state to {@link NavigationBarFragment}. */
+    /** Restores the appearance and the transient saved state to {@link NavigationBar}. */
     public void restoreAppearanceAndTransientState() {
         final int barMode = barMode(mTransientShown, mAppearance);
         mNavigationBarMode = barMode;
@@ -1053,7 +1074,7 @@
             case MotionEvent.ACTION_DOWN:
                 mHomeBlockedThisTouch = false;
                 TelecomManager telecomManager =
-                        getContext().getSystemService(TelecomManager.class);
+                        mContext.getSystemService(TelecomManager.class);
                 if (telecomManager != null && telecomManager.isRinging()) {
                     if (mStatusBarLazy.get().isKeyguardShowing()) {
                         Log.i(TAG, "Ignoring HOME; there's a ringing incoming call. " +
@@ -1094,7 +1115,7 @@
         Bundle args  = new Bundle();
         args.putInt(
                 AssistManager.INVOCATION_TYPE_KEY, AssistManager.INVOCATION_HOME_BUTTON_LONG_PRESS);
-        mAssistManager.startAssist(args);
+        mAssistManagerLazy.get().startAssist(args);
         mStatusBarLazy.get().awakenDreams();
 
         if (mNavigationBarView != null) {
@@ -1120,8 +1141,8 @@
     }
 
     private void onRecentsClick(View v) {
-        if (LatencyTracker.isEnabled(getContext())) {
-            LatencyTracker.getInstance(getContext()).onActionStart(
+        if (LatencyTracker.isEnabled(mContext)) {
+            LatencyTracker.getInstance(mContext).onActionStart(
                     LatencyTracker.ACTION_TOGGLE_RECENTS);
         }
         mStatusBarLazy.get().awakenDreams();
@@ -1215,7 +1236,7 @@
     }
 
     private boolean onLongPressRecents() {
-        if (mRecentsOptional.isPresent() || !ActivityTaskManager.supportsMultiWindow(getContext())
+        if (mRecentsOptional.isPresent() || !ActivityTaskManager.supportsMultiWindow(mContext)
                 || !mDivider.getView().getSnapAlgorithm().isSplitScreenFeasible()
                 || ActivityManager.isLowRamDeviceStatic()
                 // If we are connected to the overview service, then disable the recents button
@@ -1230,7 +1251,7 @@
     private void onAccessibilityClick(View v) {
         final Display display = v.getDisplay();
         mAccessibilityManager.notifyAccessibilityButtonClicked(
-                display != null ? display.getDisplayId() : Display.DEFAULT_DISPLAY);
+                display != null ? display.getDisplayId() : DEFAULT_DISPLAY);
     }
 
     private boolean onAccessibilityLongClick(View v) {
@@ -1238,7 +1259,7 @@
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         final String chooserClassName = AccessibilityButtonChooserActivity.class.getName();
         intent.setClassName(CHOOSER_PACKAGE_NAME, chooserClassName);
-        v.getContext().startActivityAsUser(intent, UserHandle.CURRENT);
+        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         return true;
     }
 
@@ -1381,17 +1402,6 @@
         if (!canShowSecondaryHandle()) {
             resetSecondaryHandle();
         }
-
-        // Workaround for b/132825155, for secondary users, we currently don't receive configuration
-        // changes on overlay package change since SystemUI runs for the system user. In this case,
-        // trigger a new configuration change to ensure that the nav bar is updated in the same way.
-        int userId = ActivityManagerWrapper.getInstance().getCurrentUserId();
-        if (userId != UserHandle.USER_SYSTEM) {
-            mHandler.post(() -> {
-                FragmentHostManager fragmentHost = FragmentHostManager.get(mNavigationBarView);
-                fragmentHost.reloadFragments();
-            });
-        }
     }
 
     public void disableAnimationsDuringHide(long delay) {
@@ -1442,7 +1452,7 @@
             return;
         }
 
-        int rotation = getContext().getResources().getConfiguration()
+        int rotation = mContext.getResources().getConfiguration()
                 .windowConfiguration.getRotation();
         if (rotation != mCurrentRotation) {
             mCurrentRotation = rotation;
@@ -1480,37 +1490,6 @@
         }
     };
 
-    public static View create(Context context, FragmentListener listener) {
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
-                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
-                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
-                PixelFormat.TRANSLUCENT);
-        lp.token = new Binder();
-        lp.setTitle("NavigationBar" + context.getDisplayId());
-        lp.accessibilityTitle = context.getString(R.string.nav_bar);
-        lp.windowAnimations = 0;
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
-
-        View navigationBarView = LayoutInflater.from(context).inflate(
-                R.layout.navigation_bar_window, null);
-
-        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
-        if (navigationBarView == null) return null;
-
-        NavigationBarFragment fragment = FragmentHostManager.get(navigationBarView)
-                .create(NavigationBarFragment.class);
-        navigationBarView.addOnAttachStateChangeListener(new NavBarViewAttachedListener(fragment,
-                listener));
-        context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
-        return navigationBarView;
-    }
-
     @VisibleForTesting
     int getNavigationIconHints() {
         return mNavigationIconHints;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
new file mode 100644
index 0000000..73cdde8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2020 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.systemui.navigationbar;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.hardware.display.DisplayManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.statusbar.RegisterStatusBarResult;
+import com.android.settingslib.applications.InterestingConfigChanges;
+import com.android.systemui.Dumpable;
+import com.android.systemui.accessibility.SystemActions;
+import com.android.systemui.assist.AssistHandleViewController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+
+/** A controller to handle navigation bars. */
+@Singleton
+public class NavigationBarController implements Callbacks,
+        ConfigurationController.ConfigurationListener,
+        NavigationModeController.ModeChangedListener, Dumpable {
+
+    private static final String TAG = NavigationBarController.class.getSimpleName();
+
+    private final Context mContext;
+    private final WindowManager mWindowManager;
+    private final Lazy<AssistManager> mAssistManagerLazy;
+    private final AccessibilityManager mAccessibilityManager;
+    private final AccessibilityManagerWrapper mAccessibilityManagerWrapper;
+    private final DeviceProvisionedController mDeviceProvisionedController;
+    private final MetricsLogger mMetricsLogger;
+    private final OverviewProxyService mOverviewProxyService;
+    private final NavigationModeController mNavigationModeController;
+    private final StatusBarStateController mStatusBarStateController;
+    private final SysUiState mSysUiFlagsContainer;
+    private final BroadcastDispatcher mBroadcastDispatcher;
+    private final CommandQueue mCommandQueue;
+    private final Divider mDivider;
+    private final Optional<Recents> mRecentsOptional;
+    private final Lazy<StatusBar> mStatusBarLazy;
+    private final ShadeController mShadeController;
+    private final NotificationRemoteInputManager mNotificationRemoteInputManager;
+    private final SystemActions mSystemActions;
+    private final UiEventLogger mUiEventLogger;
+    private final Handler mHandler;
+    private final DisplayManager mDisplayManager;
+
+    /** A displayId - nav bar maps. */
+    @VisibleForTesting
+    SparseArray<NavigationBar> mNavigationBars = new SparseArray<>();
+
+    // Tracks config changes that will actually recreate the nav bar
+    private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
+            ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
+                    | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS
+                    | ActivityInfo.CONFIG_UI_MODE);
+
+    @Inject
+    public NavigationBarController(Context context,
+            WindowManager windowManager,
+            Lazy<AssistManager> assistManagerLazy,
+            AccessibilityManager accessibilityManager,
+            AccessibilityManagerWrapper accessibilityManagerWrapper,
+            DeviceProvisionedController deviceProvisionedController,
+            MetricsLogger metricsLogger,
+            OverviewProxyService overviewProxyService,
+            NavigationModeController navigationModeController,
+            StatusBarStateController statusBarStateController,
+            SysUiState sysUiFlagsContainer,
+            BroadcastDispatcher broadcastDispatcher,
+            CommandQueue commandQueue,
+            Divider divider,
+            Optional<Recents> recentsOptional,
+            Lazy<StatusBar> statusBarLazy,
+            ShadeController shadeController,
+            NotificationRemoteInputManager notificationRemoteInputManager,
+            SystemActions systemActions,
+            @Main Handler mainHandler,
+            UiEventLogger uiEventLogger,
+            ConfigurationController configurationController) {
+        mContext = context;
+        mWindowManager = windowManager;
+        mAssistManagerLazy = assistManagerLazy;
+        mAccessibilityManager = accessibilityManager;
+        mAccessibilityManagerWrapper = accessibilityManagerWrapper;
+        mDeviceProvisionedController = deviceProvisionedController;
+        mMetricsLogger = metricsLogger;
+        mOverviewProxyService = overviewProxyService;
+        mNavigationModeController = navigationModeController;
+        mStatusBarStateController = statusBarStateController;
+        mSysUiFlagsContainer = sysUiFlagsContainer;
+        mBroadcastDispatcher = broadcastDispatcher;
+        mCommandQueue = commandQueue;
+        mDivider = divider;
+        mRecentsOptional = recentsOptional;
+        mStatusBarLazy = statusBarLazy;
+        mShadeController = shadeController;
+        mNotificationRemoteInputManager = notificationRemoteInputManager;
+        mSystemActions = systemActions;
+        mUiEventLogger = uiEventLogger;
+        mHandler = mainHandler;
+        mDisplayManager = mContext.getSystemService(DisplayManager.class);
+        commandQueue.addCallback(this);
+        configurationController.addCallback(this);
+        mConfigChanges.applyNewConfig(mContext.getResources());
+    }
+
+    @Override
+    public void onConfigChanged(Configuration newConfig) {
+        if (mConfigChanges.applyNewConfig(mContext.getResources())) {
+            for (int i = 0; i < mNavigationBars.size(); i++) {
+                recreateNavigationBar(mNavigationBars.keyAt(i));
+            }
+        } else {
+            for (int i = 0; i < mNavigationBars.size(); i++) {
+                mNavigationBars.get(i).onConfigurationChanged(newConfig);
+            }
+        }
+    }
+
+    @Override
+    public void onNavigationModeChanged(int mode) {
+        // Workaround for b/132825155, for secondary users, we currently don't receive configuration
+        // changes on overlay package change since SystemUI runs for the system user. In this case,
+        // trigger a new configuration change to ensure that the nav bar is updated in the same way.
+        int userId = ActivityManagerWrapper.getInstance().getCurrentUserId();
+        if (userId != UserHandle.USER_SYSTEM) {
+            mHandler.post(() -> {
+                for (int i = 0; i < mNavigationBars.size(); i++) {
+                    recreateNavigationBar(mNavigationBars.keyAt(i));
+                }
+            });
+        }
+    }
+
+    @Override
+    public void onDisplayRemoved(int displayId) {
+        removeNavigationBar(displayId);
+    }
+
+    @Override
+    public void onDisplayReady(int displayId) {
+        Display display = mDisplayManager.getDisplay(displayId);
+        createNavigationBar(display, null /* savedState */, null /* result */);
+    }
+
+    /**
+     * Recreates the navigation bar for the given display.
+     */
+    private void recreateNavigationBar(int displayId) {
+        // TODO: Improve this flow so that we don't need to create a new nav bar but just
+        //       the view
+        Bundle savedState = new Bundle();
+        NavigationBar bar = mNavigationBars.get(displayId);
+        if (bar != null) {
+            bar.onSaveInstanceState(savedState);
+        }
+        removeNavigationBar(displayId);
+        createNavigationBar(mDisplayManager.getDisplay(displayId), savedState, null /* result */);
+    }
+
+    // TODO(b/117478341): I use {@code includeDefaultDisplay} to make this method compatible to
+    // CarStatusBar because they have their own nav bar. Think about a better way for it.
+    /**
+     * Creates navigation bars when car/status bar initializes.
+     *
+     * @param includeDefaultDisplay {@code true} to create navigation bar on default display.
+     */
+    public void createNavigationBars(final boolean includeDefaultDisplay,
+            RegisterStatusBarResult result) {
+        Display[] displays = mDisplayManager.getDisplays();
+        for (Display display : displays) {
+            if (includeDefaultDisplay || display.getDisplayId() != DEFAULT_DISPLAY) {
+                createNavigationBar(display, null /* savedState */, result);
+            }
+        }
+    }
+
+    /**
+     * Adds a navigation bar on default display or an external display if the display supports
+     * system decorations.
+     *
+     * @param display the display to add navigation bar on.
+     */
+    @VisibleForTesting
+    void createNavigationBar(Display display, Bundle savedState, RegisterStatusBarResult result) {
+        if (display == null) {
+            return;
+        }
+
+        final int displayId = display.getDisplayId();
+        final boolean isOnDefaultDisplay = displayId == DEFAULT_DISPLAY;
+        final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
+
+        try {
+            if (!wms.hasNavigationBar(displayId)) {
+                return;
+            }
+        } catch (RemoteException e) {
+            // Cannot get wms, just return with warning message.
+            Log.w(TAG, "Cannot get WindowManager.");
+            return;
+        }
+        final Context context = isOnDefaultDisplay
+                ? mContext
+                : mContext.createDisplayContext(display);
+        NavigationBar navBar = new NavigationBar(context,
+                mWindowManager,
+                mAssistManagerLazy,
+                mAccessibilityManager,
+                mAccessibilityManagerWrapper,
+                mDeviceProvisionedController,
+                mMetricsLogger,
+                mOverviewProxyService,
+                mNavigationModeController,
+                mStatusBarStateController,
+                mSysUiFlagsContainer,
+                mBroadcastDispatcher,
+                mCommandQueue,
+                mDivider,
+                mRecentsOptional,
+                mStatusBarLazy,
+                mShadeController,
+                mNotificationRemoteInputManager,
+                mSystemActions,
+                mHandler,
+                mUiEventLogger);
+
+        View navigationBarView = navBar.createView(savedState);
+        navigationBarView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View v) {
+                mNavigationBars.put(displayId, navBar);
+
+                if (result != null) {
+                    navBar.setImeWindowStatus(display.getDisplayId(), result.mImeToken,
+                            result.mImeWindowVis, result.mImeBackDisposition,
+                            result.mShowImeSwitcher);
+                }
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View v) {
+                v.removeOnAttachStateChangeListener(this);
+            }
+        });
+    }
+
+    private void removeNavigationBar(int displayId) {
+        NavigationBar navBar = mNavigationBars.get(displayId);
+        if (navBar != null) {
+            navBar.setAutoHideController(/* autoHideController */ null);
+            navBar.destroyView();
+            mNavigationBars.remove(displayId);
+        }
+    }
+
+    /** @see NavigationBar#checkNavBarModes() */
+    public void checkNavBarModes(int displayId) {
+        NavigationBar navBar = mNavigationBars.get(displayId);
+        if (navBar != null) {
+            navBar.checkNavBarModes();
+        }
+    }
+
+    /** @see NavigationBar#finishBarAnimations() */
+    public void finishBarAnimations(int displayId) {
+        NavigationBar navBar = mNavigationBars.get(displayId);
+        if (navBar != null) {
+            navBar.finishBarAnimations();
+        }
+    }
+
+    /** @see NavigationBar#touchAutoDim() */
+    public void touchAutoDim(int displayId) {
+        NavigationBar navBar = mNavigationBars.get(displayId);
+        if (navBar != null) {
+            navBar.touchAutoDim();
+        }
+    }
+
+    /** @see NavigationBar#transitionTo(int, boolean) */
+    public void transitionTo(int displayId, @TransitionMode int barMode, boolean animate) {
+        NavigationBar navBar = mNavigationBars.get(displayId);
+        if (navBar != null) {
+            navBar.transitionTo(barMode, animate);
+        }
+    }
+
+    /** @see NavigationBar#disableAnimationsDuringHide(long) */
+    public void disableAnimationsDuringHide(int displayId, long delay) {
+        NavigationBar navBar = mNavigationBars.get(displayId);
+        if (navBar != null) {
+            navBar.disableAnimationsDuringHide(delay);
+        }
+    }
+
+    /** @return {@link NavigationBarView} on the default display. */
+    public @Nullable NavigationBarView getDefaultNavigationBarView() {
+        return getNavigationBarView(DEFAULT_DISPLAY);
+    }
+
+    /**
+     * @param displayId the ID of display which Navigation bar is on
+     * @return {@link NavigationBarView} on the display with {@code displayId}.
+     *         {@code null} if no navigation bar on that display.
+     */
+    public @Nullable NavigationBarView getNavigationBarView(int displayId) {
+        NavigationBar navBar = mNavigationBars.get(displayId);
+        return (navBar == null) ? null : (NavigationBarView) navBar.getView();
+    }
+
+    /** @return {@link NavigationBar} on the default display. */
+    @Nullable
+    public NavigationBar getDefaultNavigationBar() {
+        return mNavigationBars.get(DEFAULT_DISPLAY);
+    }
+
+    /** @return {@link AssistHandleViewController} (only on the default display). */
+    @Nullable
+    public AssistHandleViewController getAssistHandlerViewController() {
+        NavigationBar navBar = getDefaultNavigationBar();
+        return navBar == null ? null : navBar.getAssistHandlerViewController();
+    }
+
+    @Override
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+        for (int i = 0; i < mNavigationBars.size(); i++) {
+            if (i > 0) {
+                pw.println();
+            }
+            mNavigationBars.get(i).dump(pw);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarFrame.java
similarity index 71%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarFrame.java
index 741f783..6c531d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarFrame.java
@@ -1,18 +1,20 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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
+ * 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.
+ * 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.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static android.view.MotionEvent.ACTION_OUTSIDE;
 
@@ -24,7 +26,7 @@
 import android.view.MotionEvent;
 import android.widget.FrameLayout;
 
-import com.android.systemui.statusbar.policy.DeadZone;
+import com.android.systemui.navigationbar.buttons.DeadZone;
 
 public class NavigationBarFrame extends FrameLayout {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
index 4337e20..2707460 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
@@ -1,18 +1,20 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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
+ * 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.
+ * 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.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
@@ -35,10 +37,12 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
+import com.android.systemui.navigationbar.buttons.KeyButtonView;
+import com.android.systemui.navigationbar.buttons.ReverseLinearLayout;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout;
-import com.android.systemui.statusbar.policy.KeyButtonView;
+import com.android.systemui.navigationbar.buttons.ReverseLinearLayout.ReverseRelativeLayout;
 
 import java.io.PrintWriter;
 import java.util.Objects;
@@ -472,8 +476,7 @@
     }
 
     public void dump(PrintWriter pw) {
-        pw.println("NavigationBarInflaterView {");
-        pw.println("      mCurrentLayout: " + mCurrentLayout);
-        pw.println("    }");
+        pw.println("NavigationBarInflaterView");
+        pw.println("  mCurrentLayout: " + mCurrentLayout);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
index 1f50954..c0535b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,27 +14,27 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
 
 import static com.android.systemui.util.Utils.isGesturalModeOnDefaultDisplay;
 
-import android.content.Context;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.IWallpaperVisibilityListener;
 import android.view.IWindowManager;
 import android.view.View;
 
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.BarTransitions;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index e3cb105..a335183 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
 
@@ -70,6 +70,15 @@
 import com.android.systemui.R;
 import com.android.systemui.assist.AssistHandleViewController;
 import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
+import com.android.systemui.navigationbar.buttons.ContextualButton;
+import com.android.systemui.navigationbar.buttons.ContextualButtonGroup;
+import com.android.systemui.navigationbar.buttons.DeadZone;
+import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
+import com.android.systemui.navigationbar.buttons.RotationContextButton;
+import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
+import com.android.systemui.navigationbar.gestural.FloatingRotationButton;
+import com.android.systemui.navigationbar.gestural.RegionSamplingHelper;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsOnboarding;
@@ -80,9 +89,10 @@
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.policy.DeadZone;
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
+import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController;
+import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -167,7 +177,7 @@
      * When quickswitching between apps of different orientations, we draw a secondary home handle
      * in the position of the first app's orientation. This rect represents the region of that
      * home handle so we can apply the correct light/dark luma on that.
-     * @see {@link NavigationBarFragment#mOrientationHandle}
+     * @see {@link NavigationBar#mOrientationHandle}
      */
     @Nullable
     private Rect mOrientedHandleSamplingRegion;
@@ -779,7 +789,7 @@
             } else {
                 return;
             }
-            WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
+            WindowManager wm = getContext().getSystemService(WindowManager.class);
             wm.updateViewLayout((View) getParent(), lp);
         }
     }
@@ -867,7 +877,7 @@
         } else {
             lp.flags &= ~flags;
         }
-        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+        WindowManager wm = getContext().getSystemService(WindowManager.class);
         wm.updateViewLayout(navbarView, lp);
     }
 
@@ -1163,6 +1173,9 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+        // This needs to happen first as it can changed the enabled state which can affect whether
+        // the back button is visible
+        mEdgeBackGestureHandler.onNavBarAttached();
         requestApplyInsets();
         reorient();
         onNavigationModeChanged(mNavBarMode);
@@ -1171,7 +1184,6 @@
             mRotationButtonController.registerListeners();
         }
 
-        mEdgeBackGestureHandler.onNavBarAttached();
         getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
     }
 
@@ -1200,12 +1212,12 @@
         }
     }
 
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("NavigationBarView {");
+    public void dump(PrintWriter pw) {
         final Rect r = new Rect();
         final Point size = new Point();
         getContextDisplay().getRealSize(size);
 
+        pw.println("NavigationBarView:");
         pw.println(String.format("      this: " + StatusBar.viewInfo(this)
                         + " " + visibilityToString(getVisibility())));
 
@@ -1228,6 +1240,8 @@
                         getLightTransitionsController().getCurrentDarkIntensity()));
 
         pw.println("      mOrientedHandleSamplingRegion: " + mOrientedHandleSamplingRegion);
+        pw.println("    mScreenOn: " + mScreenOn);
+
 
         dumpButton(pw, "back", getBackButton());
         dumpButton(pw, "home", getHomeButton());
@@ -1236,9 +1250,6 @@
         dumpButton(pw, "a11y", getAccessibilityButton());
         dumpButton(pw, "ime", getImeSwitchButton());
 
-        pw.println("    }");
-        pw.println("    mScreenOn: " + mScreenOn);
-
         if (mNavigationInflaterView != null) {
             mNavigationInflaterView.dump(pw);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
index c211de0..6e301c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static android.content.Intent.ACTION_OVERLAY_CHANGED;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButton.java
similarity index 87%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/RotationButton.java
index 74d4eb1..e487858 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButton.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import android.view.View;
 
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
+import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
 
 import java.util.function.Consumer;
 
 /** Interface of a rotation button that interacts {@link RotationButtonController}. */
-interface RotationButton {
+public interface RotationButton {
     void setRotationButtonController(RotationButtonController rotationButtonController);
     void setVisibilityChangedCallback(Consumer<Boolean> visibilityChangedCallback);
     View getCurrentView();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
index 2f2e1f9..6cbf065 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static com.android.internal.view.RotationPolicy.NATURAL_ROTATION;
 
@@ -23,7 +23,6 @@
 import android.animation.ObjectAnimator;
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
-import android.annotation.StyleRes;
 import android.app.StatusBarManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -32,7 +31,6 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.util.Log;
-import android.view.ContextThemeWrapper;
 import android.view.IRotationWatcher.Stub;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -43,14 +41,13 @@
 import com.android.internal.logging.UiEvent;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.logging.UiEventLoggerImpl;
-import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 import com.android.systemui.statusbar.policy.RotationLockController;
 
 import java.util.Optional;
@@ -328,7 +325,7 @@
         }
     }
 
-    Context getContext() {
+    public Context getContext() {
         return mContext;
     }
 
@@ -336,15 +333,15 @@
         return mRotationButton;
     }
 
-    @DrawableRes int getIconResId() {
+    public @DrawableRes int getIconResId() {
         return mIconResId;
     }
 
-    @ColorInt int getLightIconColor() {
+    public @ColorInt int getLightIconColor() {
         return mLightIconColor;
     }
 
-    @ColorInt int getDarkIconColor() {
+    public @ColorInt int getDarkIconColor() {
         return mDarkIconColor;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java b/packages/SystemUI/src/com/android/systemui/navigationbar/ScreenPinningNotify.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/ScreenPinningNotify.java
index 071e00d..ac7baf5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/ScreenPinningNotify.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import android.content.Context;
 import android.os.SystemClock;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
index c273108..ade2923a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
@@ -1,18 +1,20 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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
+ * 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.
+ * 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.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import static com.android.systemui.Interpolators.LINEAR;
 
@@ -24,7 +26,6 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.assist.AssistManager;
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
 import java.util.ArrayList;
 
@@ -75,11 +76,11 @@
         mAssistManager = Dependency.get(AssistManager.class);
     }
 
-    void clear() {
+    public void clear() {
         mViews.clear();
     }
 
-    void addView(View view) {
+    public void addView(View view) {
         mViews.add(view);
         view.setOnClickListener(mClickListener);
         view.setOnTouchListener(mTouchListener);
@@ -337,6 +338,6 @@
     /**
      * Executes when button is detached from window.
      */
-    protected void onDestroy() {
+    public void onDestroy() {
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonInterface.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonInterface.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
index 150a960..8d291dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonInterface.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,10 +11,10 @@
  * 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
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import android.annotation.Nullable;
 import android.graphics.drawable.Drawable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButton.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButton.java
index eb47645..453e85a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButton.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,10 +11,10 @@
  * 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
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import android.annotation.DrawableRes;
 import android.annotation.IdRes;
@@ -22,9 +22,6 @@
 import android.content.Context;
 import android.view.View;
 
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
-import com.android.systemui.statusbar.policy.KeyButtonView;
-
 /**
  * Simple contextual button that is added to the {@link ContextualButtonGroup}. Extend if need extra
  * functionality.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButtonGroup.java
similarity index 90%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButtonGroup.java
index c1017f4..50b638b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButtonGroup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,10 +11,10 @@
  * 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
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import android.annotation.IdRes;
 import android.annotation.NonNull;
@@ -119,21 +119,20 @@
 
     public void dump(PrintWriter pw) {
         View view = getCurrentView();
-        pw.println("ContextualButtonGroup {");
-        pw.println("      getVisibleContextButton(): " + getVisibleContextButton());
-        pw.println("      isVisible(): " + isVisible());
-        pw.println("      attached(): " + (view != null && view.isAttachedToWindow()));
-        pw.println("      mButtonData [ ");
+        pw.println("ContextualButtonGroup");
+        pw.println("  getVisibleContextButton(): " + getVisibleContextButton());
+        pw.println("  isVisible(): " + isVisible());
+        pw.println("  attached(): " + (view != null && view.isAttachedToWindow()));
+        pw.println("  mButtonData [ ");
         for (int i = mButtonData.size() - 1; i >= 0; --i) {
             final ButtonData data = mButtonData.get(i);
             view = data.button.getCurrentView();
-            pw.println("            " + i + ": markedVisible=" + data.markedVisible
+            pw.println("    " + i + ": markedVisible=" + data.markedVisible
                     + " visible=" + data.button.getVisibility()
                     + " attached=" + (view != null && view.isAttachedToWindow())
                     + " alpha=" + data.button.getAlpha());
         }
-        pw.println("      ]");
-        pw.println("    }");
+        pw.println("  ]");
     }
 
     private int getContextButtonIndex(@IdRes int buttonResId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/DeadZone.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/DeadZone.java
index 12d0617..7e5b554 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/DeadZone.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package com.android.systemui.navigationbar.buttons;
 
 import android.animation.ObjectAnimator;
 import android.content.res.Resources;
@@ -26,8 +26,8 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.phone.NavigationBarView;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarView;
 
 /**
  * The "dead zone" consumes unintentional taps along the top edge of the navigation bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java
index 7559388..fc20169 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,10 +11,10 @@
  * 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
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package com.android.systemui.navigationbar.buttons;
 
 import android.animation.ArgbEvaluator;
 import android.annotation.ColorInt;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
index 2d8784d..72cd4f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,10 +11,10 @@
  * 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
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package com.android.systemui.navigationbar.buttons;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java
index 8d7ecd0..d6b8316 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package com.android.systemui.navigationbar.buttons;
 
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.KeyEvent.KEYCODE_UNKNOWN;
@@ -61,7 +61,6 @@
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.statusbar.phone.ButtonInterface;
 
 public class KeyButtonView extends ImageView implements ButtonInterface {
     private static final String TAG = KeyButtonView.class.getSimpleName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java
similarity index 88%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java
index d022808..88c8fea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java
@@ -1,18 +1,20 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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
+ * 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.
+ * 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.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import android.content.Context;
 import android.content.res.Configuration;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ReverseLinearLayout.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ReverseLinearLayout.java
index d3ec187..f1e1366 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ReverseLinearLayout.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import android.annotation.Nullable;
 import android.content.Context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java
similarity index 87%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java
index d63d445..6a97a33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,17 +11,20 @@
  * 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
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import android.annotation.DrawableRes;
 import android.annotation.IdRes;
 import android.content.Context;
 import android.view.View;
 
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
+import com.android.systemui.navigationbar.RotationButton;
+import com.android.systemui.navigationbar.RotationButtonController;
+import com.android.systemui.navigationbar.buttons.ContextualButton;
+import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
 
 import java.util.function.Consumer;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 9606318..a1b55c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -1,5 +1,5 @@
-/**
- * Copyright (C) 2019 The Android Open Source Project
+/*
+ * Copyright (C) 2020 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.gestural;
 
 import static android.view.Display.INVALID_DISPLAY;
 
@@ -59,6 +59,8 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationBarView;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.NavigationEdgeBackPlugin;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.recents.OverviewProxyService;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButton.java
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButton.java
index 8a85f7d..61118c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/FloatingRotationButton.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.gestural;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -27,8 +27,10 @@
 import android.view.WindowManager;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
-import com.android.systemui.statusbar.policy.KeyButtonView;
+import com.android.systemui.navigationbar.RotationButton;
+import com.android.systemui.navigationbar.RotationButtonController;
+import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
+import com.android.systemui.navigationbar.buttons.KeyButtonView;
 
 import java.util.function.Consumer;
 
@@ -49,7 +51,7 @@
     private RotationButtonController mRotationButtonController;
     private Consumer<Boolean> mVisibilityChangedCallback;
 
-    FloatingRotationButton(Context context) {
+    public FloatingRotationButton(Context context) {
         mContext = context;
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         mKeyButtonView = (KeyButtonView) LayoutInflater.from(mContext).inflate(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index 2357309..284f41a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.gestural;
 
 import android.animation.ValueAnimator;
 import android.content.Context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
index b874795..33e6aa4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.gestural;
 
 import android.animation.ArgbEvaluator;
 import android.annotation.ColorInt;
@@ -29,6 +29,7 @@
 
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
+import com.android.systemui.navigationbar.buttons.ButtonInterface;
 
 public class NavigationHandle extends View implements ButtonInterface {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickswitchOrientedNavHandle.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/QuickswitchOrientedNavHandle.java
similarity index 91%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickswitchOrientedNavHandle.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/gestural/QuickswitchOrientedNavHandle.java
index fe74677..71c8a2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickswitchOrientedNavHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/QuickswitchOrientedNavHandle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.gestural;
 
 import android.content.Context;
 import android.graphics.Canvas;
@@ -34,7 +34,7 @@
         mWidth = context.getResources().getDimensionPixelSize(R.dimen.navigation_home_handle_width);
     }
 
-    void setDeltaRotation(@Surface.Rotation int rotation) {
+    public void setDeltaRotation(@Surface.Rotation int rotation) {
         mDeltaRotation = rotation;
     }
 
@@ -43,7 +43,7 @@
         canvas.drawRoundRect(computeHomeHandleBounds(), mRadius, mRadius, mPaint);
     }
 
-    RectF computeHomeHandleBounds() {
+    public RectF computeHomeHandleBounds() {
         int left;
         int top;
         int bottom;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/RegionSamplingHelper.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
rename to packages/SystemUI/src/com/android/systemui/navigationbar/gestural/RegionSamplingHelper.java
index 3c8aa86..70117eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/RegionSamplingHelper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,10 +11,10 @@
  * 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
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.gestural;
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -108,7 +108,7 @@
         }
     }
 
-    void start(Rect initialSamplingBounds) {
+    public void start(Rect initialSamplingBounds) {
         if (!mCallback.isSamplingEnabled()) {
             return;
         }
@@ -122,12 +122,12 @@
         updateSamplingListener();
     }
 
-    void stop() {
+    public void stop() {
         mSamplingEnabled = false;
         updateSamplingListener();
     }
 
-    void stopAndDestroy() {
+    public void stopAndDestroy() {
         stop();
         mSamplingListener.destroy();
         mIsDestroyed = true;
@@ -220,12 +220,12 @@
         }
     }
 
-    void setWindowVisible(boolean visible) {
+    public void setWindowVisible(boolean visible) {
         mWindowVisible = visible;
         updateSamplingListener();
     }
 
-    void dump(PrintWriter pw) {
+    public void dump(PrintWriter pw) {
         pw.println("RegionSamplingHelper:");
         pw.println("  sampleView isAttached: " + mSampledView.isAttachedToWindow());
         pw.println("  sampleView isScValid: " + (mSampledView.isAttachedToWindow()
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
index 563684a..ba50db1 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
@@ -40,7 +40,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.wm.shell.common.DisplayChangeController;
 import com.android.wm.shell.common.DisplayController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index d03082e..5fb71e8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -81,10 +81,10 @@
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.phone.NavigationBarFragment;
-import com.android.systemui.statusbar.phone.NavigationBarView;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBar;
+import com.android.systemui.navigationbar.NavigationBarView;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
@@ -124,7 +124,7 @@
     private final Optional<Divider> mDividerOptional;
     private SysUiState mSysUiState;
     private final Handler mHandler;
-    private final NavigationBarController mNavBarController;
+    private final Lazy<NavigationBarController> mNavBarControllerLazy;
     private final NotificationShadeWindowController mStatusBarWinController;
     private final Runnable mConnectionRunnable = this::internalConnectToCurrentUser;
     private final ComponentName mRecentsComponentName;
@@ -598,7 +598,7 @@
     @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
     @Inject
     public OverviewProxyService(Context context, CommandQueue commandQueue,
-            NavigationBarController navBarController, NavigationModeController navModeController,
+            Lazy<NavigationBarController> navBarControllerLazy, NavigationModeController navModeController,
             NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
             PipUI pipUI, Optional<Divider> dividerOptional,
             Optional<Lazy<StatusBar>> statusBarOptionalLazy, OneHandedUI oneHandedUI,
@@ -608,7 +608,7 @@
         mPipUI = pipUI;
         mStatusBarOptionalLazy = statusBarOptionalLazy;
         mHandler = new Handler();
-        mNavBarController = navBarController;
+        mNavBarControllerLazy = navBarControllerLazy;
         mStatusBarWinController = statusBarWinController;
         mConnectionBackoffAttempts = 0;
         mDividerOptional = dividerOptional;
@@ -677,10 +677,10 @@
     }
 
     private void updateSystemUiStateFlags() {
-        final NavigationBarFragment navBarFragment =
-                mNavBarController.getDefaultNavigationBarFragment();
+        final NavigationBar navBarFragment =
+                mNavBarControllerLazy.get().getDefaultNavigationBar();
         final NavigationBarView navBarView =
-                mNavBarController.getNavigationBarView(mContext.getDisplayId());
+                mNavBarControllerLazy.get().getNavigationBarView(mContext.getDisplayId());
         if (SysUiState.DEBUG) {
             Log.d(TAG_OPS, "Updating sysui state flags: navBarFragment=" + navBarFragment
                     + " navBarView=" + navBarView);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index 3b3d9dd..9c5a3de 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -466,23 +466,22 @@
     }
 
     public void dump(PrintWriter pw) {
-        pw.println("RecentsOnboarding {");
-        pw.println("      mTaskListenerRegistered: " + mTaskListenerRegistered);
-        pw.println("      mOverviewProxyListenerRegistered: " + mOverviewProxyListenerRegistered);
-        pw.println("      mLayoutAttachedToWindow: " + mLayoutAttachedToWindow);
-        pw.println("      mHasDismissedSwipeUpTip: " + mHasDismissedSwipeUpTip);
-        pw.println("      mHasDismissedQuickScrubTip: " + mHasDismissedQuickScrubTip);
-        pw.println("      mNumAppsLaunchedSinceSwipeUpTipDismiss: "
+        pw.println("RecentsOnboarding");
+        pw.println("  mTaskListenerRegistered: " + mTaskListenerRegistered);
+        pw.println("  mOverviewProxyListenerRegistered: " + mOverviewProxyListenerRegistered);
+        pw.println("  mLayoutAttachedToWindow: " + mLayoutAttachedToWindow);
+        pw.println("  mHasDismissedSwipeUpTip: " + mHasDismissedSwipeUpTip);
+        pw.println("  mHasDismissedQuickScrubTip: " + mHasDismissedQuickScrubTip);
+        pw.println("  mNumAppsLaunchedSinceSwipeUpTipDismiss: "
                 + mNumAppsLaunchedSinceSwipeUpTipDismiss);
-        pw.println("      hasSeenSwipeUpOnboarding: " + hasSeenSwipeUpOnboarding());
-        pw.println("      hasSeenQuickScrubOnboarding: " + hasSeenQuickScrubOnboarding());
-        pw.println("      getDismissedSwipeUpOnboardingCount: "
+        pw.println("  hasSeenSwipeUpOnboarding: " + hasSeenSwipeUpOnboarding());
+        pw.println("  hasSeenQuickScrubOnboarding: " + hasSeenQuickScrubOnboarding());
+        pw.println("  getDismissedSwipeUpOnboardingCount: "
                 + getDismissedSwipeUpOnboardingCount());
-        pw.println("      hasDismissedQuickScrubOnboardingOnce: "
+        pw.println("  hasDismissedQuickScrubOnboardingOnce: "
                 + hasDismissedQuickScrubOnboardingOnce());
-        pw.println("      getOpenedOverviewCount: " + getOpenedOverviewCount());
-        pw.println("      getOpenedOverviewFromHomeCount: " + getOpenedOverviewFromHomeCount());
-        pw.println("    }");
+        pw.println("  getOpenedOverviewCount: " + getOpenedOverviewCount());
+        pw.println("  getOpenedOverviewFromHomeCount: " + getOpenedOverviewFromHomeCount());
     }
 
     private WindowManager.LayoutParams getWindowLayoutParams(int gravity, int x) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 3874903..6afc756 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -51,8 +51,8 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.statusbar.phone.NavigationBarView;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationBarView;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.leak.RotationUtils;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
deleted file mode 100644
index 2638d28..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ /dev/null
@@ -1,248 +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.systemui.statusbar;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.Display;
-import android.view.IWindowManager;
-import android.view.View;
-import android.view.WindowManagerGlobal;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.statusbar.RegisterStatusBarResult;
-import com.android.systemui.Dependency;
-import com.android.systemui.assist.AssistHandleViewController;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.plugins.DarkIconDispatcher;
-import com.android.systemui.statusbar.CommandQueue.Callbacks;
-import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
-import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.NavigationBarFragment;
-import com.android.systemui.statusbar.phone.NavigationBarView;
-import com.android.systemui.statusbar.phone.NavigationModeController;
-import com.android.systemui.statusbar.policy.BatteryController;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-
-/** A controller to handle navigation bars. */
-@Singleton
-public class NavigationBarController implements Callbacks {
-
-    private static final String TAG = NavigationBarController.class.getSimpleName();
-
-    private final Context mContext;
-    private final Handler mHandler;
-    private final DisplayManager mDisplayManager;
-
-    /** A displayId - nav bar maps. */
-    @VisibleForTesting
-    SparseArray<NavigationBarFragment> mNavigationBars = new SparseArray<>();
-
-    @Inject
-    public NavigationBarController(Context context, @Main Handler handler,
-            CommandQueue commandQueue) {
-        mContext = context;
-        mHandler = handler;
-        mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
-        commandQueue.addCallback(this);
-    }
-
-    @Override
-    public void onDisplayRemoved(int displayId) {
-        removeNavigationBar(displayId);
-    }
-
-    @Override
-    public void onDisplayReady(int displayId) {
-        Display display = mDisplayManager.getDisplay(displayId);
-        createNavigationBar(display, null);
-    }
-
-    // TODO(b/117478341): I use {@code includeDefaultDisplay} to make this method compatible to
-    // CarStatusBar because they have their own nav bar. Think about a better way for it.
-    /**
-     * Creates navigation bars when car/status bar initializes.
-     *
-     * @param includeDefaultDisplay {@code true} to create navigation bar on default display.
-     */
-    public void createNavigationBars(final boolean includeDefaultDisplay,
-            RegisterStatusBarResult result) {
-        Display[] displays = mDisplayManager.getDisplays();
-        for (Display display : displays) {
-            if (includeDefaultDisplay || display.getDisplayId() != DEFAULT_DISPLAY) {
-                createNavigationBar(display, result);
-            }
-        }
-    }
-
-    /**
-     * Adds a navigation bar on default display or an external display if the display supports
-     * system decorations.
-     *
-     * @param display the display to add navigation bar on.
-     */
-    @VisibleForTesting
-    void createNavigationBar(Display display, RegisterStatusBarResult result) {
-        if (display == null) {
-            return;
-        }
-
-        final int displayId = display.getDisplayId();
-        final boolean isOnDefaultDisplay = displayId == DEFAULT_DISPLAY;
-        final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
-
-        try {
-            if (!wms.hasNavigationBar(displayId)) {
-                return;
-            }
-        } catch (RemoteException e) {
-            // Cannot get wms, just return with warning message.
-            Log.w(TAG, "Cannot get WindowManager.");
-            return;
-        }
-        final Context context = isOnDefaultDisplay
-                ? mContext
-                : mContext.createDisplayContext(display);
-        NavigationBarFragment.create(context, (tag, fragment) -> {
-            NavigationBarFragment navBar = (NavigationBarFragment) fragment;
-
-            // Unfortunately, we still need it because status bar needs LightBarController
-            // before notifications creation. We cannot directly use getLightBarController()
-            // from NavigationBarFragment directly.
-            LightBarController lightBarController = isOnDefaultDisplay
-                    ? Dependency.get(LightBarController.class)
-                    : new LightBarController(context,
-                            Dependency.get(DarkIconDispatcher.class),
-                            Dependency.get(BatteryController.class),
-                            Dependency.get(NavigationModeController.class));
-            navBar.setLightBarController(lightBarController);
-
-            // TODO(b/118592525): to support multi-display, we start to add something which is
-            //                    per-display, while others may be global. I think it's time to add
-            //                    a new class maybe named DisplayDependency to solve per-display
-            //                    Dependency problem.
-            AutoHideController autoHideController = isOnDefaultDisplay
-                    ? Dependency.get(AutoHideController.class)
-                    : new AutoHideController(context, mHandler,
-                            Dependency.get(IWindowManager.class));
-            navBar.setAutoHideController(autoHideController);
-            navBar.restoreAppearanceAndTransientState();
-            mNavigationBars.put(displayId, navBar);
-
-            if (result != null) {
-                navBar.setImeWindowStatus(display.getDisplayId(), result.mImeToken,
-                        result.mImeWindowVis, result.mImeBackDisposition,
-                        result.mShowImeSwitcher);
-            }
-        });
-    }
-
-    private void removeNavigationBar(int displayId) {
-        NavigationBarFragment navBar = mNavigationBars.get(displayId);
-        if (navBar != null) {
-            navBar.setAutoHideController(/* autoHideController */ null);
-            View navigationWindow = navBar.getView().getRootView();
-            WindowManagerGlobal.getInstance()
-                    .removeView(navigationWindow, true /* immediate */);
-            // Also remove FragmentHostState here in case that onViewDetachedFromWindow has not yet
-            // invoked after display removal.
-            FragmentHostManager.removeAndDestroy(navigationWindow);
-            mNavigationBars.remove(displayId);
-        }
-    }
-
-    /** @see NavigationBarFragment#checkNavBarModes() */
-    public void checkNavBarModes(int displayId) {
-        NavigationBarFragment navBar = mNavigationBars.get(displayId);
-        if (navBar != null) {
-            navBar.checkNavBarModes();
-        }
-    }
-
-    /** @see NavigationBarFragment#finishBarAnimations() */
-    public void finishBarAnimations(int displayId) {
-        NavigationBarFragment navBar = mNavigationBars.get(displayId);
-        if (navBar != null) {
-            navBar.finishBarAnimations();
-        }
-    }
-
-    /** @see NavigationBarFragment#touchAutoDim() */
-    public void touchAutoDim(int displayId) {
-        NavigationBarFragment navBar = mNavigationBars.get(displayId);
-        if (navBar != null) {
-            navBar.touchAutoDim();
-        }
-    }
-
-    /** @see NavigationBarFragment#transitionTo(int, boolean) */
-    public void transitionTo(int displayId, @TransitionMode int barMode, boolean animate) {
-        NavigationBarFragment navBar = mNavigationBars.get(displayId);
-        if (navBar != null) {
-            navBar.transitionTo(barMode, animate);
-        }
-    }
-
-    /** @see NavigationBarFragment#disableAnimationsDuringHide(long) */
-    public void disableAnimationsDuringHide(int displayId, long delay) {
-        NavigationBarFragment navBar = mNavigationBars.get(displayId);
-        if (navBar != null) {
-            navBar.disableAnimationsDuringHide(delay);
-        }
-    }
-
-    /** @return {@link NavigationBarView} on the default display. */
-    public @Nullable NavigationBarView getDefaultNavigationBarView() {
-        return getNavigationBarView(DEFAULT_DISPLAY);
-    }
-
-    /**
-     * @param displayId the ID of display which Navigation bar is on
-     * @return {@link NavigationBarView} on the display with {@code displayId}.
-     *         {@code null} if no navigation bar on that display.
-     */
-    public @Nullable NavigationBarView getNavigationBarView(int displayId) {
-        NavigationBarFragment navBar = mNavigationBars.get(displayId);
-        return (navBar == null) ? null : (NavigationBarView) navBar.getView();
-    }
-
-    /** @return {@link NavigationBarFragment} on the default display. */
-    @Nullable
-    public NavigationBarFragment getDefaultNavigationBarFragment() {
-        return mNavigationBars.get(DEFAULT_DISPLAY);
-    }
-
-    /** @return {@link AssistHandleViewController} (only on the default display). */
-    @Nullable
-    public AssistHandleViewController getAssistHandlerViewController() {
-        NavigationBarFragment navBar = getDefaultNavigationBarFragment();
-        return navBar == null ? null : navBar.getAssistHandlerViewController();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppButtonData.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppButtonData.java
deleted file mode 100644
index f6c1062..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppButtonData.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2015 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.systemui.statusbar.phone;
-
-import android.app.ActivityManager.RecentTaskInfo;
-
-import java.util.ArrayList;
-
-/**
- * Data associated with an app button.
- */
-class AppButtonData {
-    public final AppInfo appInfo;
-    public boolean pinned;
-    // Recent tasks for this app, sorted by lastActiveTime, descending.
-    public ArrayList<RecentTaskInfo> tasks;
-
-    public AppButtonData(AppInfo appInfo, boolean pinned) {
-        this.appInfo = appInfo;
-        this.pinned = pinned;
-    }
-
-    public int getTaskCount() {
-        return tasks == null ? 0 : tasks.size();
-    }
-
-    /**
-     * Returns true if the button contains no useful information and should be removed.
-     */
-    public boolean isEmpty() {
-        return !pinned && getTaskCount() == 0;
-    }
-
-    public void addTask(RecentTaskInfo task) {
-        if (tasks == null) {
-            tasks = new ArrayList<RecentTaskInfo>();
-        }
-        tasks.add(task);
-    }
-
-    public void clearTasks() {
-        if (tasks != null) {
-            tasks.clear();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java
deleted file mode 100644
index 8f0b532..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2015 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.systemui.statusbar.phone;
-
-import android.content.ComponentName;
-import android.os.UserHandle;
-
-/**
- * Navigation bar app information.
- */
-class AppInfo {
-    private final ComponentName mComponentName;
-    private final UserHandle mUser;
-
-    public AppInfo(ComponentName componentName, UserHandle user) {
-        if (componentName == null || user == null) throw new IllegalArgumentException();
-        mComponentName = componentName;
-        mUser = user;
-    }
-
-    public ComponentName getComponentName() {
-        return mComponentName;
-    }
-
-    public UserHandle getUser() {
-        return mUser;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final AppInfo other = (AppInfo) obj;
-        return mComponentName.equals(other.mComponentName) && mUser.equals(other.mUser);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index d6039af..aeb2efd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -138,7 +138,7 @@
         mHandler.postDelayed(mAutoHide, AUTO_HIDE_TIMEOUT_MS);
     }
 
-    void checkUserAutoHide(MotionEvent event) {
+    public void checkUserAutoHide(MotionEvent event) {
         boolean shouldHide = isAnyTransientBarShown()
                 && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
                 && event.getX() == 0 && event.getY() == 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 3e5eb5f..982773a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -32,6 +32,7 @@
 import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -125,7 +126,7 @@
         updateStatus();
     }
 
-    void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged,
+    public void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged,
             int navigationBarMode, boolean navbarColorManagedByIme) {
         int diff = appearance ^ mAppearance;
         if ((diff & APPEARANCE_LIGHT_NAVIGATION_BARS) != 0 || nbModeChanged) {
@@ -144,7 +145,7 @@
         mNavbarColorManagedByIme = navbarColorManagedByIme;
     }
 
-    void onNavigationBarModeChanged(int newBarMode) {
+    public void onNavigationBarModeChanged(int newBarMode) {
         mHasLightNavigationBar = isLight(mAppearance, newBarMode, APPEARANCE_LIGHT_NAVIGATION_BARS);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 6cd33c6..5d0ae6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -159,6 +159,7 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.FalsingManager;
@@ -182,7 +183,7 @@
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyboardShortcuts;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
@@ -1502,7 +1503,7 @@
         return mStatusBarWindowController.getStatusBarHeight();
     }
 
-    protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
+    public boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
         if (!mRecentsOptional.isPresent()) {
             return false;
         }
@@ -2435,7 +2436,7 @@
         return mNotificationShadeWindowViewController.getBarTransitions();
     }
 
-    void checkBarModes() {
+    public void checkBarModes() {
         if (mDemoMode) return;
         if (mNotificationShadeWindowViewController != null && getStatusBarTransitions() != null) {
             checkBarMode(mStatusBarMode, mStatusBarWindowState, getStatusBarTransitions());
@@ -2445,7 +2446,7 @@
     }
 
     // Called by NavigationBarFragment
-    void setQsScrimEnabled(boolean scrimEnabled) {
+    public void setQsScrimEnabled(boolean scrimEnabled) {
         mNotificationPanelViewController.setQsScrimEnabled(scrimEnabled);
     }
 
@@ -2618,7 +2619,7 @@
         }
     }
 
-    static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) {
+    public static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) {
         pw.print("  "); pw.print(var); pw.print(".BarTransitions.mMode=");
         pw.println(BarTransitions.modeToString(transitions.getMode()));
     }
@@ -4132,7 +4133,7 @@
         toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
     }
 
-    void awakenDreams() {
+    public void awakenDreams() {
         mUiBgExecutor.execute(() -> {
             try {
                 mDreamManager.awaken();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 81d0699..f3a7c50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -49,6 +49,7 @@
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shared.system.QuickStepContract;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 02e0312..eb2ae71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -47,7 +47,7 @@
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index fa531b5..87d2063 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -14,18 +14,18 @@
 
 package com.android.systemui.tuner;
 
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_END;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_START;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_IMAGE_DELIM;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME_ROTATE;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAVSPACE;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_LEFT;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_RIGHT;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractButton;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractImage;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractKeycode;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.KEY;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.KEY_CODE_END;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.KEY_CODE_START;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.KEY_IMAGE_DELIM;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.MENU_IME_ROTATE;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.NAVSPACE;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.NAV_BAR_LEFT;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.NAV_BAR_RIGHT;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.NAV_BAR_VIEWS;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.extractButton;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.extractImage;
+import static com.android.systemui.navigationbar.NavigationBarInflaterView.extractKeycode;
 
 import android.annotation.Nullable;
 import android.app.AlertDialog;
@@ -51,6 +51,7 @@
 
 import java.util.ArrayList;
 
+@Deprecated
 public class NavBarTuner extends TunerPreferenceFragment {
 
     private static final String LAYOUT = "layout";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
index afcd441..7567f0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
@@ -41,7 +41,7 @@
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 98a6ced..c874b1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -42,7 +42,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.DeviceConfigProxyFake;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
similarity index 94%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
index aae0757..37b7cbe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -35,6 +35,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.SysuiTestableContext;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -65,6 +66,7 @@
         mDependency.injectMockDependency(AssistManager.class);
         mDependency.injectMockDependency(OverviewProxyService.class);
         mDependency.injectMockDependency(KeyguardStateController.class);
+        mDependency.injectMockDependency(NavigationBarController.class);
         mNavBar = new NavigationBarView(context, null);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
similarity index 73%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 3c66ac6..2e4d8a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package com.android.systemui.navigationbar;
 
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
@@ -36,12 +36,32 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.util.SparseArray;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.phone.NavigationBarFragment;
+import com.android.systemui.accessibility.SystemActions;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import java.util.Optional;
 
 import org.junit.After;
 import org.junit.Before;
@@ -55,27 +75,47 @@
 public class NavigationBarControllerTest extends SysuiTestCase {
 
     private NavigationBarController mNavigationBarController;
-    private NavigationBarFragment mDefaultNavBar;
-    private NavigationBarFragment mSecondaryNavBar;
+    private NavigationBar mDefaultNavBar;
+    private NavigationBar mSecondaryNavBar;
 
     private static final int SECONDARY_DISPLAY = 1;
 
     @Before
     public void setUp() {
         mNavigationBarController = spy(
-                new NavigationBarController(mContext, Dependency.get(Dependency.MAIN_HANDLER),
-                        mock(CommandQueue.class)));
+                new NavigationBarController(mContext,
+                        mock(WindowManager.class),
+                        () -> mock(AssistManager.class),
+                        mock(AccessibilityManager.class),
+                        mock(AccessibilityManagerWrapper.class),
+                        mock(DeviceProvisionedController.class),
+                        mock(MetricsLogger.class),
+                        mock(OverviewProxyService.class), 
+                        mock(NavigationModeController.class),
+                        mock(StatusBarStateController.class),
+                        mock(SysUiState.class),
+                        mock(BroadcastDispatcher.class),
+                        mock(CommandQueue.class),
+                        mock(Divider.class),
+                        Optional.of(mock(Recents.class)),
+                        () -> mock(StatusBar.class),
+                        mock(ShadeController.class),
+                        mock(NotificationRemoteInputManager.class),
+                        mock(SystemActions.class),
+                        Dependency.get(Dependency.MAIN_HANDLER),
+                        mock(UiEventLogger.class),
+                        mock(ConfigurationController.class)));
         initializeNavigationBars();
     }
 
     private void initializeNavigationBars() {
         mNavigationBarController.mNavigationBars = mock(SparseArray.class);
-        mDefaultNavBar = mock(NavigationBarFragment.class);
+        mDefaultNavBar = mock(NavigationBar.class);
         mDefaultNavBar.mDisplayId = DEFAULT_DISPLAY;
         doReturn(mDefaultNavBar)
                 .when(mNavigationBarController.mNavigationBars).get(DEFAULT_DISPLAY);
 
-        mSecondaryNavBar = mock(NavigationBarFragment.class);
+        mSecondaryNavBar = mock(NavigationBar.class);
         mSecondaryNavBar.mDisplayId = SECONDARY_DISPLAY;
         doReturn(mSecondaryNavBar)
                 .when(mNavigationBarController.mNavigationBars).get(SECONDARY_DISPLAY);
@@ -90,22 +130,22 @@
 
     @Test
     public void testCreateNavigationBarsIncludeDefaultTrue() {
-        doNothing().when(mNavigationBarController).createNavigationBar(any(), any());
+        doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
 
         mNavigationBarController.createNavigationBars(true, null);
 
         verify(mNavigationBarController).createNavigationBar(
-                argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any());
+                argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any(), any());
     }
 
     @Test
     public void testCreateNavigationBarsIncludeDefaultFalse() {
-        doNothing().when(mNavigationBarController).createNavigationBar(any(), any());
+        doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
 
         mNavigationBarController.createNavigationBars(false, null);
 
         verify(mNavigationBarController, never()).createNavigationBar(
-                argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any());
+                argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any(), any());
     }
 
     // Tests if NPE occurs when call checkNavBarModes() with invalid display.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarInflaterViewTest.java
similarity index 90%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarInflaterViewTest.java
index 80e33fb..7369c82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarInflaterViewTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.doNothing;
@@ -32,6 +32,9 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
+import com.android.systemui.navigationbar.NavigationBarInflaterView;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.recents.OverviewProxyService;
 
 import org.junit.After;
@@ -54,6 +57,7 @@
         mDependency.injectMockDependency(AssistManager.class);
         mDependency.injectMockDependency(OverviewProxyService.class);
         mDependency.injectMockDependency(NavigationModeController.class);
+        mDependency.injectMockDependency(NavigationBarController.class);
 
         mNavBarInflaterView = spy(new NavigationBarInflaterView(mContext, null));
         doNothing().when(mNavBarInflaterView).createInflaters();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
similarity index 94%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
index f665241..51cf501 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -30,7 +30,9 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.SysuiTestableContext;
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
+import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
+import com.android.systemui.navigationbar.RotationButton;
+import com.android.systemui.navigationbar.RotationButtonController;
 import com.android.systemui.statusbar.policy.RotationLockController;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
new file mode 100644
index 0000000..a643c2d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2020 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.systemui.navigationbar;
+
+import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
+import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT;
+import static android.inputmethodservice.InputMethodService.IME_VISIBLE;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+
+import static com.android.systemui.navigationbar.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.hardware.display.DisplayManagerGlobal;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.SysuiTestableContext;
+import com.android.systemui.accessibility.SystemActions;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.utils.leaks.LeakCheckedTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class NavigationBarTest extends SysuiTestCase {
+    private static final int EXTERNAL_DISPLAY_ID = 2;
+
+    private NavigationBar mNavigationBar;
+    private NavigationBar mExternalDisplayNavigationBar;
+
+    private SysuiTestableContext mSysuiTestableContextExternal;
+    private OverviewProxyService mOverviewProxyService;
+    private CommandQueue mCommandQueue;
+    private SysUiState mMockSysUiState;
+    private Handler mHandler;
+    @Mock
+    private BroadcastDispatcher mBroadcastDispatcher;
+    @Mock
+    private UiEventLogger mUiEventLogger;
+
+    @Rule
+    public final LeakCheckedTest.SysuiLeakCheck mLeakCheck = new LeakCheckedTest.SysuiLeakCheck();
+    private AccessibilityManagerWrapper mAccessibilityWrapper =
+            new AccessibilityManagerWrapper(mContext);
+
+    @Before
+    public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mCommandQueue = new CommandQueue(mContext);
+        setupSysuiDependency();
+        mDependency.injectMockDependency(AssistManager.class);
+        mDependency.injectMockDependency(KeyguardStateController.class);
+        mDependency.injectMockDependency(StatusBarStateController.class);
+        mDependency.injectMockDependency(NavigationBarController.class);
+        mDependency.injectMockDependency(Divider.class);
+        mOverviewProxyService = mDependency.injectMockDependency(OverviewProxyService.class);
+        TestableLooper.get(this).runWithLooper(() -> {
+            mHandler = new Handler();
+            mNavigationBar = createNavBar(mContext);
+            mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
+        });
+    }
+
+    private void setupSysuiDependency() {
+        Display display = new Display(DisplayManagerGlobal.getInstance(), EXTERNAL_DISPLAY_ID,
+                new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
+        mSysuiTestableContextExternal = (SysuiTestableContext) getContext().createDisplayContext(
+                display);
+
+        WindowManager windowManager = mock(WindowManager.class);
+        Display defaultDisplay = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
+        when(windowManager.getDefaultDisplay()).thenReturn(
+                defaultDisplay);
+        WindowMetrics metrics = mContext.getSystemService(WindowManager.class)
+                .getMaximumWindowMetrics();
+        when(windowManager.getMaximumWindowMetrics()).thenReturn(metrics);
+        doNothing().when(windowManager).addView(any(), any());
+        mContext.addMockSystemService(Context.WINDOW_SERVICE, windowManager);
+        mSysuiTestableContextExternal.addMockSystemService(Context.WINDOW_SERVICE, windowManager);
+
+        mDependency.injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
+        mDependency.injectTestDependency(AccessibilityManagerWrapper.class, mAccessibilityWrapper);
+
+        mMockSysUiState = mock(SysUiState.class);
+        when(mMockSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mMockSysUiState);
+    }
+
+    @Test
+    public void testHomeLongPress() {
+        mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null));
+        mNavigationBar.onHomeLongClick(mNavigationBar.getView());
+
+        verify(mUiEventLogger, times(1)).log(NAVBAR_ASSIST_LONGPRESS);
+    }
+
+    @Test
+    public void testRegisteredWithDispatcher() {
+        mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null));
+        verify(mBroadcastDispatcher).registerReceiverWithHandler(
+                any(BroadcastReceiver.class),
+                any(IntentFilter.class),
+                any(Handler.class),
+                any(UserHandle.class));
+    }
+
+    @Test
+    public void testSetImeWindowStatusWhenImeSwitchOnDisplay() {
+        // Create default & external NavBar fragment.
+        NavigationBar defaultNavBar = mNavigationBar;
+        NavigationBar externalNavBar = mExternalDisplayNavigationBar;
+        doNothing().when(defaultNavBar).checkNavBarModes();
+        doNothing().when(externalNavBar).checkNavBarModes();
+        defaultNavBar.createView(null);
+        externalNavBar.createView(null);
+
+        // Set IME window status for default NavBar.
+        mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+                BACK_DISPOSITION_DEFAULT, true, false);
+        processAllMessages();
+
+        // Verify IME window state will be updated in default NavBar & external NavBar state reset.
+        assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN,
+                defaultNavBar.getNavigationIconHints());
+        assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
+        assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
+
+        // Set IME window status for external NavBar.
+        mCommandQueue.setImeWindowStatus(EXTERNAL_DISPLAY_ID, null,
+                IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true, false);
+        processAllMessages();
+
+        // Verify IME window state will be updated in external NavBar & default NavBar state reset.
+        assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN,
+                externalNavBar.getNavigationIconHints());
+        assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
+        assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
+    }
+
+    private NavigationBar createNavBar(Context context) {
+        DeviceProvisionedController deviceProvisionedController =
+                mock(DeviceProvisionedController.class);
+        when(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
+        assertNotNull(mAccessibilityWrapper);
+        return spy(new NavigationBar(context,
+                mock(WindowManager.class),
+                () -> mock(AssistManager.class),
+                mock(AccessibilityManager.class),
+                context.getDisplayId() == DEFAULT_DISPLAY ? mAccessibilityWrapper
+                        : mock(AccessibilityManagerWrapper.class),
+                deviceProvisionedController,
+                new MetricsLogger(),
+                mOverviewProxyService,
+                mock(NavigationModeController.class),
+                mock(StatusBarStateController.class),
+                mMockSysUiState,
+                mBroadcastDispatcher,
+                mCommandQueue,
+                mock(Divider.class),
+                Optional.of(mock(Recents.class)),
+                () -> mock(StatusBar.class),
+                mock(ShadeController.class),
+                mock(NotificationRemoteInputManager.class),
+                mock(SystemActions.class),
+                mHandler,
+                mUiEventLogger));
+    }
+
+    private void processAllMessages() {
+        TestableLooper.get(this).processAllMessages();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
similarity index 76%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
index 14c6e9f9..7e0920c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
@@ -1,18 +1,20 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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
+ * 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.
+ * 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.systemui.statusbar.phone;
+package com.android.systemui.navigationbar;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -30,9 +32,13 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.navigationbar.NavigationBarTransitions;
+import com.android.systemui.navigationbar.NavigationBarView;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.BarTransitions;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.Before;
@@ -53,6 +59,7 @@
         mDependency.injectMockDependency(OverviewProxyService.class);
         mDependency.injectMockDependency(StatusBarStateController.class);
         mDependency.injectMockDependency(KeyguardStateController.class);
+        mDependency.injectMockDependency(NavigationBarController.class);
         doReturn(mContext)
                 .when(mDependency.injectMockDependency(NavigationModeController.class))
                 .getCurrentUserContext();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/KeyButtonViewTest.java
similarity index 79%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/KeyButtonViewTest.java
index d52d686..3f10c8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/KeyButtonViewTest.java
@@ -1,18 +1,20 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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
+ * 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.
+ * 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.systemui.statusbar.policy;
+package com.android.systemui.navigationbar.buttons;
 
 import static android.view.KeyEvent.ACTION_DOWN;
 import static android.view.KeyEvent.ACTION_UP;
@@ -23,12 +25,12 @@
 import static android.view.KeyEvent.KEYCODE_BACK;
 import static android.view.KeyEvent.KEYCODE_HOME;
 
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_BACK_BUTTON_LONGPRESS;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_BACK_BUTTON_TAP;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_HOME_BUTTON_LONGPRESS;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_HOME_BUTTON_TAP;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_OVERVIEW_BUTTON_LONGPRESS;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_OVERVIEW_BUTTON_TAP;
+import static com.android.systemui.navigationbar.buttons.KeyButtonView.NavBarButtonEvent.NAVBAR_BACK_BUTTON_LONGPRESS;
+import static com.android.systemui.navigationbar.buttons.KeyButtonView.NavBarButtonEvent.NAVBAR_BACK_BUTTON_TAP;
+import static com.android.systemui.navigationbar.buttons.KeyButtonView.NavBarButtonEvent.NAVBAR_HOME_BUTTON_LONGPRESS;
+import static com.android.systemui.navigationbar.buttons.KeyButtonView.NavBarButtonEvent.NAVBAR_HOME_BUTTON_TAP;
+import static com.android.systemui.navigationbar.buttons.KeyButtonView.NavBarButtonEvent.NAVBAR_OVERVIEW_BUTTON_LONGPRESS;
+import static com.android.systemui.navigationbar.buttons.KeyButtonView.NavBarButtonEvent.NAVBAR_OVERVIEW_BUTTON_TAP;
 
 import static junit.framework.Assert.assertEquals;
 
@@ -52,6 +54,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.navigationbar.buttons.KeyButtonView;
 import com.android.systemui.recents.OverviewProxyService;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
similarity index 95%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
index 1fb28f0..d56aa77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,10 +11,10 @@
  * 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
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -35,7 +35,9 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.assist.AssistManager;
-import com.android.systemui.statusbar.policy.KeyButtonDrawable;
+import com.android.systemui.navigationbar.buttons.ContextualButton;
+import com.android.systemui.navigationbar.buttons.ContextualButtonGroup;
+import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
 
 import org.junit.Before;
 import org.junit.Ignore;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
similarity index 91%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
index a04bcc0..0320103 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
@@ -1,18 +1,20 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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
+ * 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.
+ * 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.systemui.statusbar.phone;
+package com.android.systemui.navigationbar.buttons;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
@@ -31,6 +33,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
index f4c0700..7d84de5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
@@ -31,7 +31,7 @@
 
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.wm.shell.common.DisplayController;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
index 15881a2..8c1634e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
@@ -29,7 +29,7 @@
 
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.wm.shell.common.DisplayController;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
index f2b77a0..9e6d797 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
@@ -26,7 +26,7 @@
 
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.wm.shell.common.DisplayController;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
index 3e46907..ccdc69a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.policy.BatteryController;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
deleted file mode 100644
index 00cbddc..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2017 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.systemui.statusbar.phone;
-
-import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
-import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT;
-import static android.inputmethodservice.InputMethodService.IME_VISIBLE;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-
-import static com.android.systemui.statusbar.phone.NavigationBarFragment.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.annotation.LayoutRes;
-import android.annotation.Nullable;
-import android.app.Fragment;
-import android.app.FragmentController;
-import android.app.FragmentHostCallback;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.IntentFilter;
-import android.hardware.display.DisplayManagerGlobal;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.testing.AndroidTestingRunner;
-import android.testing.LeakCheck.Tracker;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.Display;
-import android.view.DisplayInfo;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.Dependency;
-import com.android.systemui.SysuiBaseFragmentTest;
-import com.android.systemui.SysuiTestableContext;
-import com.android.systemui.accessibility.SystemActions;
-import com.android.systemui.assist.AssistManager;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Optional;
-
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-@SmallTest
-public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
-    private static final int EXTERNAL_DISPLAY_ID = 2;
-    private static final int NAV_BAR_VIEW_ID = 43;
-
-    private Fragment mFragmentExternalDisplay;
-    private FragmentController mControllerExternalDisplay;
-
-    private SysuiTestableContext mSysuiTestableContextExternal;
-    private OverviewProxyService mOverviewProxyService;
-    private CommandQueue mCommandQueue;
-    private SysUiState mMockSysUiState;
-    @Mock
-    private BroadcastDispatcher mBroadcastDispatcher;
-    @Mock
-    private Divider mDivider;
-    @Mock
-    private Recents mRecents;
-    @Mock
-    private SystemActions mSystemActions;
-    @Mock
-    private UiEventLogger mUiEventLogger;
-
-    private AccessibilityManagerWrapper mAccessibilityWrapper =
-            new AccessibilityManagerWrapper(mContext) {
-                Tracker mTracker = mLeakCheck.getTracker("accessibility_manager");
-
-                @Override
-                public void addCallback(AccessibilityServicesStateChangeListener listener) {
-                    mTracker.getLeakInfo(listener).addAllocation(new Throwable());
-                }
-
-                @Override
-                public void removeCallback(AccessibilityServicesStateChangeListener listener) {
-                    mTracker.getLeakInfo(listener).clearAllocations();
-                }
-            };
-
-    public NavigationBarFragmentTest() {
-        super(NavigationBarFragment.class);
-    }
-
-    protected void createRootView() {
-        mView = new NavigationBarFrame(mSysuiContext);
-        mView.setId(NAV_BAR_VIEW_ID);
-    }
-
-    @Before
-    public void setupFragment() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        mCommandQueue = new CommandQueue(mContext);
-        setupSysuiDependency();
-        createRootView();
-        mOverviewProxyService =
-                mDependency.injectMockDependency(OverviewProxyService.class);
-        TestableLooper.get(this).runWithLooper(() -> {
-            mHandler = new Handler();
-
-            mFragment = instantiate(mSysuiContext, NavigationBarFragment.class.getName(), null);
-            mFragments = FragmentController.createController(
-                    new HostCallbacksForExternalDisplay(mSysuiContext));
-            mFragments.attachHost(null);
-            mFragments.getFragmentManager().beginTransaction()
-                    .replace(NAV_BAR_VIEW_ID, mFragment)
-                    .commit();
-            mControllerExternalDisplay = FragmentController.createController(
-                    new HostCallbacksForExternalDisplay(mSysuiTestableContextExternal));
-            mControllerExternalDisplay.attachHost(null);
-            mFragmentExternalDisplay = instantiate(mSysuiTestableContextExternal,
-                    NavigationBarFragment.class.getName(), null);
-            mControllerExternalDisplay.getFragmentManager().beginTransaction()
-                    .replace(NAV_BAR_VIEW_ID, mFragmentExternalDisplay)
-                    .commit();
-        });
-    }
-
-    private void setupSysuiDependency() {
-        Display display = new Display(DisplayManagerGlobal.getInstance(), EXTERNAL_DISPLAY_ID,
-                new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
-        mSysuiTestableContextExternal = (SysuiTestableContext) mSysuiContext.createDisplayContext(
-                display);
-
-        injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
-        WindowManager windowManager = mock(WindowManager.class);
-        Display defaultDisplay = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
-        when(windowManager.getDefaultDisplay()).thenReturn(
-                defaultDisplay);
-        mContext.addMockSystemService(Context.WINDOW_SERVICE, windowManager);
-
-        mDependency.injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
-        mDependency.injectTestDependency(AccessibilityManagerWrapper.class, mAccessibilityWrapper);
-
-        mMockSysUiState = mock(SysUiState.class);
-        when(mMockSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mMockSysUiState);
-    }
-
-    @Test
-    public void testHomeLongPress() {
-        NavigationBarFragment navigationBarFragment = (NavigationBarFragment) mFragment;
-
-        mFragments.dispatchResume();
-        processAllMessages();
-        navigationBarFragment.onHomeLongClick(navigationBarFragment.getView());
-
-        verify(mUiEventLogger, times(1)).log(NAVBAR_ASSIST_LONGPRESS);
-    }
-
-    @Test
-    public void testRegisteredWithDispatcher() {
-        mFragments.dispatchResume();
-        processAllMessages();
-
-        verify(mBroadcastDispatcher).registerReceiverWithHandler(
-                any(BroadcastReceiver.class),
-                any(IntentFilter.class),
-                any(Handler.class),
-                any(UserHandle.class));
-    }
-
-    @Test
-    public void testSetImeWindowStatusWhenImeSwitchOnDisplay() {
-        // Create default & external NavBar fragment.
-        NavigationBarFragment defaultNavBar = (NavigationBarFragment) mFragment;
-        NavigationBarFragment externalNavBar = (NavigationBarFragment) mFragmentExternalDisplay;
-        mFragments.dispatchCreate();
-        processAllMessages();
-        mFragments.dispatchResume();
-        processAllMessages();
-        mControllerExternalDisplay.dispatchCreate();
-        processAllMessages();
-        mControllerExternalDisplay.dispatchResume();
-        processAllMessages();
-
-        // Set IME window status for default NavBar.
-        mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
-                BACK_DISPOSITION_DEFAULT, true, false);
-        processAllMessages();
-
-        // Verify IME window state will be updated in default NavBar & external NavBar state reset.
-        assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN,
-                defaultNavBar.getNavigationIconHints());
-        assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
-        assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
-
-        // Set IME window status for external NavBar.
-        mCommandQueue.setImeWindowStatus(EXTERNAL_DISPLAY_ID, null,
-                IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true, false);
-        processAllMessages();
-
-        // Verify IME window state will be updated in external NavBar & default NavBar state reset.
-        assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN,
-                externalNavBar.getNavigationIconHints());
-        assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
-        assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
-    }
-
-    @Override
-    protected Fragment instantiate(Context context, String className, Bundle arguments) {
-        DeviceProvisionedController deviceProvisionedController =
-                mock(DeviceProvisionedController.class);
-        when(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
-        assertNotNull(mAccessibilityWrapper);
-        return new NavigationBarFragment(
-                context.getDisplayId() == DEFAULT_DISPLAY ? mAccessibilityWrapper
-                        : mock(AccessibilityManagerWrapper.class),
-                deviceProvisionedController,
-                new MetricsLogger(),
-                mock(AssistManager.class),
-                mOverviewProxyService,
-                mock(NavigationModeController.class),
-                mock(StatusBarStateController.class),
-                mMockSysUiState,
-                mBroadcastDispatcher,
-                mCommandQueue,
-                mDivider,
-                Optional.of(mRecents),
-                () -> mock(StatusBar.class),
-                mock(ShadeController.class),
-                mock(NotificationRemoteInputManager.class),
-                mock(SystemActions.class),
-                mHandler,
-                mUiEventLogger);
-    }
-
-    private class HostCallbacksForExternalDisplay extends
-            FragmentHostCallback<NavigationBarFragmentTest> {
-        private Context mDisplayContext;
-
-        HostCallbacksForExternalDisplay(Context context) {
-            super(context, mHandler, 0);
-            mDisplayContext = context;
-        }
-
-        @Override
-        public NavigationBarFragmentTest onGetHost() {
-            return NavigationBarFragmentTest.this;
-        }
-
-        @Override
-        public Fragment instantiate(Context context, String className, Bundle arguments) {
-            return NavigationBarFragmentTest.this.instantiate(context, className, arguments);
-        }
-
-        @Override
-        public View onFindViewById(int id) {
-            return mView.findViewById(id);
-        }
-
-        @Override
-        public LayoutInflater onGetLayoutInflater() {
-            return new LayoutInflaterWrapper(mDisplayContext);
-        }
-    }
-
-    private static class LayoutInflaterWrapper extends LayoutInflater {
-        protected LayoutInflaterWrapper(Context context) {
-            super(context);
-        }
-
-        @Override
-        public LayoutInflater cloneInContext(Context newContext) {
-            return null;
-        }
-
-        @Override
-        public View inflate(@LayoutRes int resource, @Nullable ViewGroup root,
-                boolean attachToRoot) {
-            NavigationBarView view = mock(NavigationBarView.class);
-            when(view.getDisplay()).thenReturn(mContext.getDisplay());
-            when(view.getBackButton()).thenReturn(mock(ButtonDispatcher.class));
-            when(view.getHomeButton()).thenReturn(mock(ButtonDispatcher.class));
-            when(view.getRecentsButton()).thenReturn(mock(ButtonDispatcher.class));
-            when(view.getAccessibilityButton()).thenReturn(mock(ButtonDispatcher.class));
-            when(view.getRotateSuggestionButton()).thenReturn(mock(RotationContextButton.class));
-            when(view.getBarTransitions()).thenReturn(mock(NavigationBarTransitions.class));
-            when(view.getLightTransitionsController()).thenReturn(
-                    mock(LightBarTransitionsController.class));
-            when(view.getRotationButtonController()).thenReturn(
-                    mock(RotationButtonController.class));
-            when(view.isRecentsButtonVisible()).thenReturn(true);
-            return view;
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 675a2df..50d891e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 5a08c9c..2ee60c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -97,7 +97,7 @@
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;