[automerger skipped] Empty merge of sc-v2-dev-plus-aosp-without-vendor@8084891 am: aa095e3c78 -s ours am: dc54a23edc -s ours

am skip reason: Merged-In Ief9b3b3cf5f64d8b9c7596cf04e5267fe0152be8 with SHA-1 834d74bbf0 is already in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/opt/car/setupwizard/+/16843717

Change-Id: I4ca7f24959c06f354bb9fba2e9e195223aa2f7af
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..9f39796
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        google()
+        mavenCentral()
+
+    }
+    dependencies {
+        // Before upgrading this version, make sure you can close android
+        // studio, run git clean -fxd, and then reopen this folder in android
+        // studio and have it work. Sometimes android studio's built in gradle
+        // wrapper seems to lag behind the version required by the android
+        // plugin.
+        classpath 'com.android.tools.build:gradle:4.1.3'
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..2a103f9
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2021 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.
+
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
diff --git a/library/main/Android.bp b/library/main/Android.bp
index f99ecdd..506dee5 100644
--- a/library/main/Android.bp
+++ b/library/main/Android.bp
@@ -22,7 +22,11 @@
     srcs: ["src/**/*.java"],
     resource_dirs: ["res"],
     libs: ["android.car-system-stubs"],
-    static_libs: ["androidx.car_car-resources-partially-dejetified"],
+    static_libs: [
+        "androidx.car_car-resources-partially-dejetified",
+        "car-ui-lib",
+        "androidx.test.core"
+    ],
     optimize: {
         enabled: false,
     },
diff --git a/library/main/build.gradle b/library/main/build.gradle
index 412e3b0..17ab59a 100644
--- a/library/main/build.gradle
+++ b/library/main/build.gradle
@@ -78,6 +78,7 @@
     implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
     implementation 'androidx.core:core:1.3.2'
     implementation 'androidx.annotation:annotation:1.2.0'
+    implementation 'androidx.test:core:1.4.0'
 
     testImplementation 'com.google.truth:truth:0.41'
     testImplementation 'org.mockito:mockito-core:3.6.0'
diff --git a/library/main/tests/robotests/Android.bp b/library/main/tests/robotests/Android.bp
index d5cf533..9d91639 100644
--- a/library/main/tests/robotests/Android.bp
+++ b/library/main/tests/robotests/Android.bp
@@ -14,7 +14,7 @@
 
     privileged: true,
 
-    libs: ["android.car"],
+    libs: ["android.car-system-stubs"],
 
     static_libs: ["car-setup-wizard-lib"],
 }
@@ -30,7 +30,7 @@
     java_resource_dirs: ["config"],
 
     libs: [
-        "android.car",
+        "android.car-system-stubs",
     ],
 
     instrumentation_for: "CarSetupWizardLib",
diff --git a/library/main/tests/robotests/res/layout/car_setup_wizard_layout_test_activity.xml b/library/main/tests/robotests/res/layout/car_setup_wizard_layout_test_activity.xml
index a9bcfbe..4509b0a 100644
--- a/library/main/tests/robotests/res/layout/car_setup_wizard_layout_test_activity.xml
+++ b/library/main/tests/robotests/res/layout/car_setup_wizard_layout_test_activity.xml
@@ -16,7 +16,9 @@
 -->
 <com.android.car.setupwizardlib.CarSetupWizardCompatLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/car_setup_wizard_layout"
     android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"/>
+    android:layout_height="match_parent"
+    app:supportsSplitNavLayout="true"/>
diff --git a/library/main/tests/robotests/src/com/android/car/setupwizardlib/BaseCompatActivityTest.java b/library/main/tests/robotests/src/com/android/car/setupwizardlib/BaseCompatActivityTest.java
index 7209fc9..b504625 100644
--- a/library/main/tests/robotests/src/com/android/car/setupwizardlib/BaseCompatActivityTest.java
+++ b/library/main/tests/robotests/src/com/android/car/setupwizardlib/BaseCompatActivityTest.java
@@ -19,8 +19,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.doReturn;
+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.app.Activity;
 import android.car.Car;
@@ -28,8 +30,11 @@
 import android.car.drivingstate.CarUxRestrictions;
 import android.car.drivingstate.CarUxRestrictionsManager;
 import android.os.Bundle;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewStub;
 import android.widget.Button;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 
 import androidx.annotation.StyleRes;
@@ -38,7 +43,6 @@
 import com.android.car.setupwizardlib.robolectric.BaseRobolectricTest;
 import com.android.car.setupwizardlib.robolectric.TestHelper;
 import com.android.car.setupwizardlib.shadows.ShadowCar;
-import com.android.car.setupwizardlib.test.R;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -194,6 +198,7 @@
                 .isEqualTo(0);
         // Verify that onContentFragmentSet is called with the test fragment
         verify(spyBaseCompatActivity).onContentFragmentSet(fragment);
+        verify(spyBaseCompatActivity).getFragmentContainerViewId();
     }
 
     /**
@@ -213,6 +218,7 @@
                 .isEqualTo(0);
         // Verify that onContentFragmentSet is not called
         verify(spyBaseCompatActivity, times(0)).onContentFragmentSet(fragment);
+        verify(spyBaseCompatActivity, times(0)).getFragmentContainerViewId();
     }
 
     /**
@@ -232,6 +238,7 @@
                 .isEqualTo(1);
         // Verify that onContentFragmentSet is called with the test fragment
         verify(spyBaseCompatActivity).onContentFragmentSet(fragment);
+        verify(spyBaseCompatActivity).getFragmentContainerViewId();
     }
 
     /**
@@ -251,6 +258,7 @@
                 .isEqualTo(0);
         // Verify that onContentFragmentSet is not called
         verify(spyBaseCompatActivity, times(0)).onContentFragmentSet(fragment);
+        verify(spyBaseCompatActivity, times(0)).getFragmentContainerViewId();
     }
 
     /**
@@ -294,12 +302,50 @@
      */
     @Test
     public void testSetContentLayout() {
-        mBaseCompatActivity.setContentLayout(R.layout.base_activity_test_layout);
-        View contentLayout = mBaseCompatActivity.findViewById(R.id.content_layout);
+        BaseCompatActivity spyBaseCompatActivity = Mockito.spy(mBaseCompatActivity);
+
+        spyBaseCompatActivity.setContentLayout(R.layout.base_activity_test_layout);
+        View contentLayout = spyBaseCompatActivity.findViewById(R.id.content_layout);
+
         assertThat(contentLayout).isNotNull();
     }
 
     /**
+     * Test that {@link BaseSetupWizardActivity#setContentLayout(int)} adds the specified layout
+     * to the main content when layout_content_stub is null.
+     */
+    @Test
+    public void testSetContentLayoutWhenViewStubIsNull() {
+        BaseCompatActivity spyBaseCompatActivity = Mockito.spy(mBaseCompatActivity);
+        LayoutInflater mockLayoutInflater = mock(LayoutInflater.class);
+        when(spyBaseCompatActivity.findViewById(R.id.layout_content_stub)).thenReturn(null);
+        when(spyBaseCompatActivity.getLayoutInflater()).thenReturn(mockLayoutInflater);
+
+        spyBaseCompatActivity.setContentLayout(R.layout.base_activity_test_layout);
+
+        verify(mockLayoutInflater, times(1))
+                .inflate(R.layout.base_activity_test_layout,
+                        mBaseCompatActivity.getCarSetupWizardLayout());
+    }
+
+    /**
+     * Test that {@link BaseCompatActivity#setContentLayout(int)} adds the specified layout to
+     * the main content when layout_content_stub is not null.
+     */
+    @Test
+    public void testSetContentLayoutWhenViewStubNotNull() {
+        BaseCompatActivity spyBaseCompatActivity = Mockito.spy(mBaseCompatActivity);
+        ViewStub mockViewStub = mock(ViewStub.class);
+        when(spyBaseCompatActivity.findViewById(R.id.layout_content_stub)).thenReturn(mockViewStub);
+
+        spyBaseCompatActivity.setContentLayout(R.layout.base_activity_test_layout);
+
+        verify(mockViewStub, times(1))
+                .setLayoutResource(R.layout.base_activity_test_layout);
+        verify(mockViewStub, times(1)).inflate();
+    }
+
+    /**
      * Test that {@link BaseCompatActivity#finishAction()} results in a call to
      * {@link BaseCompatActivity#finish}.
      */
@@ -581,4 +627,61 @@
         spyBaseCompatActivity.nextAction(Activity.RESULT_OK);
         verify(spyBaseCompatActivity, times(2)).startActivity(Mockito.any());
     }
+
+    /**
+     * Test that {@link BaseCompatActivity#getFragmentContainerViewId()} returns
+     * layout_content_fragment when split-nav is enabled and view stub is not inflated yet.
+     */
+    @Test
+    public void testGetFragmentContainerViewId_viewStubNotInflated() {
+        BaseCompatActivity spyBaseCompatActivity = createSpyBaseCompatActivity();
+        FrameLayout mockFrameLayout = mock(FrameLayout.class);
+        ViewStub mockViewStub = mock(ViewStub.class);
+        when(spyBaseCompatActivity.findViewById(R.id.empty_fragment_frame_layout))
+                .thenReturn(mockFrameLayout);
+        when(spyBaseCompatActivity.findViewById(R.id.layout_content_stub)).thenReturn(mockViewStub);
+
+        int fragmentContainerViewId = spyBaseCompatActivity.getFragmentContainerViewId();
+
+        verify(mockViewStub, times(1)).inflate();
+        assertThat(fragmentContainerViewId).isEqualTo(R.id.empty_fragment_frame_layout);
+    }
+
+    /**
+     * Test that {@link BaseCompatActivity#getFragmentContainerViewId()} returns
+     * layout_content_fragment when split-nav is enabled and view stub is already inflated
+     * with frame layout for fragment attachment.
+     */
+    @Test
+    public void testGetFragmentContainerViewId_viewStubInflatedFrameLayout() {
+        BaseCompatActivity spyBaseCompatActivity = createSpyBaseCompatActivity();
+        FrameLayout mockFrameLayout = mock(FrameLayout.class);
+        when(spyBaseCompatActivity.findViewById(R.id.empty_fragment_frame_layout))
+                .thenReturn(mockFrameLayout);
+        when(spyBaseCompatActivity.findViewById(R.id.layout_content_stub))
+                .thenReturn(null);
+
+        int fragmentContainerViewId = spyBaseCompatActivity.getFragmentContainerViewId();
+
+        assertThat(fragmentContainerViewId).isEqualTo(R.id.empty_fragment_frame_layout);
+    }
+
+    /**
+     * Test that {@link BaseCompatActivity#getFragmentContainerViewId()} returns
+     * layout_content_fragment when split-nav is enabled and view stub is already inflated
+     * with some other view than fragment layout. The frame layout is not available for fragment
+     * attachment.
+     */
+    @Test
+    public void testGetFragmentContainerViewId_frameLayoutNotAvailable() {
+        BaseCompatActivity spyBaseCompatActivity = createSpyBaseCompatActivity();
+        when(spyBaseCompatActivity.findViewById(R.id.layout_content_stub))
+                .thenReturn(null);
+        when(spyBaseCompatActivity.findViewById(R.id.empty_fragment_frame_layout))
+                .thenReturn(null);
+
+        int fragmentContainerViewId = spyBaseCompatActivity.getFragmentContainerViewId();
+
+        assertThat(fragmentContainerViewId).isEqualTo(R.id.car_setup_wizard_layout);
+    }
 }
diff --git a/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java b/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java
index 3ed02c0..9371947 100644
--- a/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java
+++ b/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java
@@ -24,6 +24,7 @@
 import android.content.res.ColorStateList;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;
@@ -65,6 +66,7 @@
     private static final Locale LOCALE_IW_IL = new Locale("iw", "IL");
 
     private CarSetupWizardCompatLayout mCarSetupWizardCompatLayout;
+    private CarSetupWizardLayoutInterface mCarSetupWizardLayoutInterface;
 
     private static final String TEST_PACKAGE_NAME = "test.packageName";
 
@@ -85,9 +87,11 @@
         }
 
         mCarSetupWizardCompatLayout = createCarSetupWizardCompatLayout();
-        // Have to make this call first to ensure secondaryToolbar button is created from stub.
-        mCarSetupWizardCompatLayout.setSecondaryToolbarButtonVisible(true);
-        mCarSetupWizardCompatLayout.setSecondaryToolbarButtonVisible(false);
+        mCarSetupWizardLayoutInterface =
+                (CarSetupWizardLayoutInterface) mCarSetupWizardCompatLayout;
+        // Have to make this call first to ensure secondaryActionButton is created from stub.
+        mCarSetupWizardLayoutInterface.setSecondaryActionButtonVisible(true);
+        mCarSetupWizardLayoutInterface.setSecondaryActionButtonVisible(false);
     }
 
     /**
@@ -240,75 +244,108 @@
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setPrimaryToolbarButtonVisible} does set the view
+     * Test that any call to setToolbarTitle calls toolbar's setText when split-nav is enabled.
+     */
+    @Test
+    public void testSetToolbarTitleWhenSplitNavEnabled() {
+        CarSetupWizardCompatLayout spyCarSetupWizardCompatLayout =
+                Mockito.spy(mCarSetupWizardCompatLayout);
+        TextView spyToolbar = Mockito.spy(mCarSetupWizardCompatLayout.getToolbarTitle());
+        spyCarSetupWizardCompatLayout.setToolbarTitle(null);
+
+        spyCarSetupWizardCompatLayout.setToolbarTitleText("test title");
+
+        Mockito.verify(spyToolbar, Mockito.never()).setText("test title");
+    }
+
+    /**
+     * Test that any call to setToolbarTitleStyle calls toolbar's setTextAppearance when split-nav
+     * is enabled.
+     */
+    @Test
+    public void testSetToolbarStyleWhenSplitNavEnabled() {
+        @StyleRes int newStyle = R.style.TextAppearance_Car_Body2;
+        CarSetupWizardCompatLayout spyCarSetupWizardCompatLayout =
+                Mockito.spy(mCarSetupWizardCompatLayout);
+        TextView spyToolbar = Mockito.spy(mCarSetupWizardCompatLayout.getToolbarTitle());
+        spyCarSetupWizardCompatLayout.setToolbarTitle(null);
+
+        spyCarSetupWizardCompatLayout.setToolbarTitleStyle(newStyle);
+
+        Mockito.verify(spyToolbar, Mockito.never()).setTextAppearance(newStyle);
+    }
+
+    /**
+     * Test that {@link CarSetupWizardCompatLayout#setPrimaryActionButtonVisible} does set the view
      * visible/not visible.
      */
     @Test
-    public void testSetPrimaryToolbarButtonVisibleTrue() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getPrimaryToolbarButton();
+    public void testSetPrimaryActionButtonVisibleTrue() {
+        View primaryButton = mCarSetupWizardLayoutInterface.getPrimaryActionButton();
 
-        mCarSetupWizardCompatLayout.setPrimaryToolbarButtonVisible(true);
-        TestHelper.assertViewVisible(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setPrimaryActionButtonVisible(true);
+        TestHelper.assertViewVisible(primaryButton);
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setPrimaryToolbarButtonVisible} does set the view
+     * Test that {@link CarSetupWizardCompatLayout#setPrimaryActionButtonVisible} does set the view
      * visible/not visible.
      */
     @Test
-    public void testSetPrimaryToolbarButtonVisibleFalse() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getPrimaryToolbarButton();
+    public void testSetPrimaryActionButtonVisibleFalse() {
+        View primaryButton = mCarSetupWizardLayoutInterface.getPrimaryActionButton();
 
-        mCarSetupWizardCompatLayout.setPrimaryToolbarButtonVisible(false);
-        TestHelper.assertViewNotVisible(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setPrimaryActionButtonVisible(false);
+        TestHelper.assertViewNotVisible(primaryButton);
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setPrimaryToolbarButtonEnabled} does set the view
+     * Test that {@link CarSetupWizardCompatLayout#setPrimaryActionButtonEnabled} does set the view
      * enabled/not enabled.
      */
     @Test
-    public void testSetPrimaryToolbarButtonEnabledTrue() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getPrimaryToolbarButton();
+    public void testSetPrimaryActionButtonEnabledTrue() {
+        View primaryButton = mCarSetupWizardLayoutInterface.getPrimaryActionButton();
 
-        mCarSetupWizardCompatLayout.setPrimaryToolbarButtonEnabled(true);
-        TestHelper.assertViewEnabled(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setPrimaryActionButtonEnabled(true);
+        TestHelper.assertViewEnabled(primaryButton);
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setPrimaryToolbarButtonEnabled} does set the view
+     * Test that {@link CarSetupWizardCompatLayout#setPrimaryActionButtonEnabled} does set the view
      * enabled/not enabled.
      */
     @Test
-    public void testSetPrimaryToolbarButtonEnabledFalse() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getPrimaryToolbarButton();
+    public void testSetPrimaryActionButtonEnabledFalse() {
+        View primaryButton = mCarSetupWizardLayoutInterface.getPrimaryActionButton();
 
-        mCarSetupWizardCompatLayout.setPrimaryToolbarButtonEnabled(false);
-        TestHelper.assertViewNotEnabled(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setPrimaryActionButtonEnabled(false);
+        TestHelper.assertViewNotEnabled(primaryButton);
     }
 
     /**
-     * Tests that {@link CarSetupWizardCompatLayout#setPrimaryToolbarButtonText(String)} does set
-     * the primary toolbar button text.
+     * Tests that {@link CarSetupWizardCompatLayout#setPrimaryActionButtonText(String)} does set
+     * the primary action button text.
      */
     @Test
-    public void testSetPrimaryToolbarButtonText() {
-        mCarSetupWizardCompatLayout.setPrimaryToolbarButtonText("test title");
+    public void testSetPrimaryActionButtonText() {
+        mCarSetupWizardLayoutInterface.setPrimaryActionButtonText("test title");
         TestHelper.assertTextEqual(
-                mCarSetupWizardCompatLayout.getPrimaryToolbarButton(), "test title");
+                mCarSetupWizardLayoutInterface.getPrimaryActionButton(), "test title");
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setPrimaryToolbarButtonListener} does set the
-     * primary toolbar button listener.
+     * Test that {@link CarSetupWizardCompatLayout#setPrimaryActionButtonListener} does set the
+     * primary action button listener.
      */
     @Test
-    public void testSetPrimaryToolbarButtonListener() {
+    public void testSetPrimaryActionButtonListener() {
         View.OnClickListener spyListener = TestHelper.createSpyListener();
 
-        mCarSetupWizardCompatLayout.setPrimaryToolbarButtonListener(spyListener);
-        mCarSetupWizardCompatLayout.getPrimaryToolbarButton().performClick();
-        Mockito.verify(spyListener).onClick(mCarSetupWizardCompatLayout.getPrimaryToolbarButton());
+        mCarSetupWizardLayoutInterface.setPrimaryActionButtonListener(spyListener);
+        mCarSetupWizardLayoutInterface.getPrimaryActionButton().performClick();
+        Mockito.verify(spyListener).onClick(
+                mCarSetupWizardLayoutInterface.getPrimaryActionButton());
     }
 
     /**
@@ -317,89 +354,89 @@
      */
     @Test
     public void testCreatePrimaryButtonTrue() {
-        Button currPrimaryToolbarButton = mCarSetupWizardCompatLayout.getPrimaryToolbarButton();
-        Button primaryToolbarButton = mCarSetupWizardCompatLayout.createPrimaryToolbarButton(true);
+        Button currPrimaryActionButton = mCarSetupWizardLayoutInterface.getPrimaryActionButton();
+        Button primaryActionButton = mCarSetupWizardCompatLayout.createPrimaryToolbarButton(true);
 
-        assertThat(primaryToolbarButton.getVisibility()).isEqualTo(
-                currPrimaryToolbarButton.getVisibility());
-        assertThat(primaryToolbarButton.isEnabled()).isEqualTo(
-                currPrimaryToolbarButton.isEnabled());
-        assertThat(primaryToolbarButton.getText()).isEqualTo(currPrimaryToolbarButton.getText());
-        assertThat(primaryToolbarButton.getLayoutParams()).isEqualTo(
-                currPrimaryToolbarButton.getLayoutParams());
+        assertThat(primaryActionButton.getVisibility()).isEqualTo(
+                currPrimaryActionButton.getVisibility());
+        assertThat(primaryActionButton.isEnabled()).isEqualTo(
+                currPrimaryActionButton.isEnabled());
+        assertThat(primaryActionButton.getText()).isEqualTo(currPrimaryActionButton.getText());
+        assertThat(primaryActionButton.getLayoutParams()).isEqualTo(
+                currPrimaryActionButton.getLayoutParams());
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setSecondaryToolbarButtonVisible} does set the
+     * Test that {@link CarSetupWizardCompatLayout#setSecondaryActionButtonVisible} does set the
      * view visible/not visible.
      */
     @Test
-    public void testSetSecondaryToolbarButtonVisibleTrue() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getSecondaryToolbarButton();
+    public void testSetSecondaryActionButtonVisibleTrue() {
+        View secondaryButton = mCarSetupWizardLayoutInterface.getSecondaryActionButton();
 
-        mCarSetupWizardCompatLayout.setSecondaryToolbarButtonVisible(true);
-        TestHelper.assertViewVisible(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setSecondaryActionButtonVisible(true);
+        TestHelper.assertViewVisible(secondaryButton);
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setSecondaryToolbarButtonVisible} does set the
+     * Test that {@link CarSetupWizardCompatLayout#setSecondaryActionButtonVisible} does set the
      * view visible/not visible.
      */
     @Test
-    public void testSetSecondaryToolbarButtonVisibleFalse() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getSecondaryToolbarButton();
+    public void testSetSecondaryActionButtonVisibleFalse() {
+        View secondaryButton = mCarSetupWizardLayoutInterface.getSecondaryActionButton();
 
-        mCarSetupWizardCompatLayout.setSecondaryToolbarButtonVisible(false);
-        TestHelper.assertViewNotVisible(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setSecondaryActionButtonVisible(false);
+        TestHelper.assertViewNotVisible(secondaryButton);
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setSecondaryToolbarButtonEnabled} does set the
+     * Test that {@link CarSetupWizardCompatLayout#setSecondaryActionButtonEnabled} does set the
      * view enabled/not enabled.
      */
     @Test
-    public void testSetSecondaryToolbarButtonEnabledTrue() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getSecondaryToolbarButton();
+    public void testSetSecondaryActionButtonEnabledTrue() {
+        View secondaryButton = mCarSetupWizardLayoutInterface.getSecondaryActionButton();
 
-        mCarSetupWizardCompatLayout.setSecondaryToolbarButtonEnabled(true);
-        TestHelper.assertViewEnabled(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setSecondaryActionButtonEnabled(true);
+        TestHelper.assertViewEnabled(secondaryButton);
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setSecondaryToolbarButtonEnabled} does set the
+     * Test that {@link CarSetupWizardCompatLayout#setSecondaryActionButtonEnabled} does set the
      * view enabled/not enabled.
      */
     @Test
-    public void testSetSecondaryToolbarButtonEnabledFalse() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getSecondaryToolbarButton();
+    public void testSetSecondaryActionButtonEnabledFalse() {
+        View secondaryButton = mCarSetupWizardLayoutInterface.getSecondaryActionButton();
 
-        mCarSetupWizardCompatLayout.setSecondaryToolbarButtonEnabled(false);
-        TestHelper.assertViewNotEnabled(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setSecondaryActionButtonEnabled(false);
+        TestHelper.assertViewNotEnabled(secondaryButton);
     }
 
     /**
-     * Tests that {@link CarSetupWizardCompatLayout#setSecondaryToolbarButtonText(String)} does set
-     * the secondary toolbar button text.
+     * Tests that {@link CarSetupWizardCompatLayout#setSecondaryActionButtonText(String)} does set
+     * the secondary action button text.
      */
     @Test
-    public void testSetSecondaryToolbarButtonText() {
-        mCarSetupWizardCompatLayout.setSecondaryToolbarButtonText("test title");
+    public void testSetSecondaryActionButtonText() {
+        mCarSetupWizardLayoutInterface.setSecondaryActionButtonText("test title");
         TestHelper.assertTextEqual(
-                mCarSetupWizardCompatLayout.getSecondaryToolbarButton(), "test title");
+                mCarSetupWizardLayoutInterface.getSecondaryActionButton(), "test title");
     }
 
     /**
-     * Test that {@link CarSetupWizardCompatLayout#setSecondaryToolbarButtonListener} does set the
-     * secondary toolbar button listener.
+     * Test that {@link CarSetupWizardCompatLayout#setSecondaryActionButtonListener} does set the
+     * secondary action button listener.
      */
     @Test
-    public void testSetSecondaryToolbarButtonListener() {
+    public void testSetSecondaryActionButtonListener() {
         View.OnClickListener spyListener = TestHelper.createSpyListener();
 
-        mCarSetupWizardCompatLayout.setSecondaryToolbarButtonListener(spyListener);
-        mCarSetupWizardCompatLayout.getSecondaryToolbarButton().performClick();
+        mCarSetupWizardLayoutInterface.setSecondaryActionButtonListener(spyListener);
+        mCarSetupWizardLayoutInterface.getSecondaryActionButton().performClick();
         Mockito.verify(spyListener)
-                .onClick(mCarSetupWizardCompatLayout.getSecondaryToolbarButton());
+                .onClick(mCarSetupWizardLayoutInterface.getSecondaryActionButton());
     }
 
     /**
@@ -408,10 +445,10 @@
      */
     @Test
     public void testSetProgressBarVisibleTrue() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getProgressBar();
+        View progressBar = mCarSetupWizardCompatLayout.getProgressBar();
 
-        mCarSetupWizardCompatLayout.setProgressBarVisible(true);
-        TestHelper.assertViewVisible(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setProgressBarVisible(true);
+        TestHelper.assertViewVisible(progressBar);
     }
 
     /**
@@ -420,10 +457,10 @@
      */
     @Test
     public void testSetProgressBarVisibleFalse() {
-        View toolbarTitle = mCarSetupWizardCompatLayout.getProgressBar();
+        View progressBar = mCarSetupWizardCompatLayout.getProgressBar();
 
-        mCarSetupWizardCompatLayout.setProgressBarVisible(false);
-        TestHelper.assertViewNotVisible(toolbarTitle);
+        mCarSetupWizardLayoutInterface.setProgressBarVisible(false);
+        TestHelper.assertViewNotVisible(progressBar);
     }
 
     /**
@@ -432,7 +469,7 @@
      */
     @Test
     public void testSetProgressBarIndeterminateTrue() {
-        mCarSetupWizardCompatLayout.setProgressBarIndeterminate(true);
+        mCarSetupWizardLayoutInterface.setProgressBarIndeterminate(true);
         assertThat(mCarSetupWizardCompatLayout.getProgressBar().isIndeterminate()).isTrue();
     }
 
@@ -442,7 +479,7 @@
      */
     @Test
     public void testSetProgressBarIndeterminateFalse() {
-        mCarSetupWizardCompatLayout.setProgressBarIndeterminate(false);
+        mCarSetupWizardLayoutInterface.setProgressBarIndeterminate(false);
         assertThat(mCarSetupWizardCompatLayout.getProgressBar().isIndeterminate()).isFalse();
     }
 
@@ -451,7 +488,7 @@
      */
     @Test
     public void testSetProgressBarProgress() {
-        mCarSetupWizardCompatLayout.setProgressBarProgress(80);
+        mCarSetupWizardLayoutInterface.setProgressBarProgress(80);
         assertThat(mCarSetupWizardCompatLayout.getProgressBar().getProgress()).isEqualTo(80);
     }
 
@@ -459,22 +496,36 @@
     public void testApplyUpdatedLocale() {
         mCarSetupWizardCompatLayout.applyLocale(LOCALE_IW_IL);
         TextView toolbarTitle = mCarSetupWizardCompatLayout.getToolbarTitle();
-        Button primaryToolbarButton = mCarSetupWizardCompatLayout.getPrimaryToolbarButton();
-        Button secondaryToolbarButton = mCarSetupWizardCompatLayout.getSecondaryToolbarButton();
+        Button primaryActionButton = mCarSetupWizardLayoutInterface.getPrimaryActionButton();
+        Button secondaryActionButton = mCarSetupWizardLayoutInterface.getSecondaryActionButton();
 
         assertThat(toolbarTitle.getTextLocale()).isEqualTo(LOCALE_IW_IL);
-        assertThat(primaryToolbarButton.getTextLocale()).isEqualTo(LOCALE_IW_IL);
-        assertThat(secondaryToolbarButton.getTextLocale()).isEqualTo(LOCALE_IW_IL);
+        assertThat(primaryActionButton.getTextLocale()).isEqualTo(LOCALE_IW_IL);
+        assertThat(secondaryActionButton.getTextLocale()).isEqualTo(LOCALE_IW_IL);
 
         mCarSetupWizardCompatLayout.applyLocale(LOCALE_EN_US);
         assertThat(toolbarTitle.getTextLocale()).isEqualTo(LOCALE_EN_US);
-        assertThat(primaryToolbarButton.getTextLocale()).isEqualTo(LOCALE_EN_US);
-        assertThat(secondaryToolbarButton.getTextLocale()).isEqualTo(LOCALE_EN_US);
+        assertThat(primaryActionButton.getTextLocale()).isEqualTo(LOCALE_EN_US);
+        assertThat(secondaryActionButton.getTextLocale()).isEqualTo(LOCALE_EN_US);
+    }
+
+    @Test
+    public void testApplyUpdatedLocaleWhenSplitNavEnabled() {
+        CarSetupWizardCompatLayout spyCarSetupWizardCompatLayout =
+                Mockito.spy(mCarSetupWizardCompatLayout);
+        TextView spyToolbar = Mockito.spy(mCarSetupWizardCompatLayout.getToolbarTitle());
+        spyCarSetupWizardCompatLayout.setToolbarTitle(null);
+
+        spyCarSetupWizardCompatLayout.applyLocale(LOCALE_EN_US);
+
+        Mockito.verify(spyToolbar, Mockito.never()).setTextLocale(LOCALE_EN_US);
+        Mockito.verify(spyToolbar, Mockito.never())
+                .setLayoutDirection(TextUtils.getLayoutDirectionFromLocale(LOCALE_EN_US));
     }
 
     @Test
     public void testGetBackButton() {
-        assertThat(mCarSetupWizardCompatLayout.getPrimaryToolbarButton()).isEqualTo(
+        assertThat(mCarSetupWizardLayoutInterface.getPrimaryActionButton()).isEqualTo(
                 mCarSetupWizardCompatLayout.findViewById(R.id.primary_toolbar_button));
     }
 
@@ -485,14 +536,14 @@
     }
 
     @Test
-    public void testGetPrimaryToolBarButton() {
-        assertThat(mCarSetupWizardCompatLayout.getPrimaryToolbarButton()).isEqualTo(
+    public void testGetPrimaryActionButton() {
+        assertThat(mCarSetupWizardLayoutInterface.getPrimaryActionButton()).isEqualTo(
                 mCarSetupWizardCompatLayout.findViewById(R.id.primary_toolbar_button));
     }
 
     @Test
-    public void testGetSecondaryToolBarButton() {
-        assertThat(mCarSetupWizardCompatLayout.getSecondaryToolbarButton()).isEqualTo(
+    public void testGetSecondaryActionButton() {
+        assertThat(mCarSetupWizardLayoutInterface.getSecondaryActionButton()).isEqualTo(
                 mCarSetupWizardCompatLayout.findViewById(R.id.secondary_toolbar_button));
     }
 
@@ -509,10 +560,10 @@
         CarSetupWizardCompatLayout layout = createCarSetupWizardCompatLayout();
 
         // Verify primary button background
-        Button primary = layout.getPrimaryToolbarButton();
+        Button primary = layout.getPrimaryActionButton();
         Drawable expected = application.getResources().getDrawable(R.drawable.button_ripple_bg);
-        assertThat(getDrawbleDefaultColor(primary.getBackground()))
-                .isEqualTo(getDrawbleDefaultColor(expected));
+        assertThat(getDrawableDefaultColor(primary.getBackground()))
+                .isEqualTo(getDrawableDefaultColor(expected));
 
         // Verify primary button text size
         assertThat(primary.getTextSize())
@@ -538,14 +589,15 @@
         CarSetupWizardCompatLayout layout = createCarSetupWizardCompatLayout();
 
         ColorDrawable bg = (ColorDrawable) layout.getBackground();
-        assertThat(bg).isNull();
+        assertThat(bg.getColor()).isEqualTo(
+                application.getResources().getColor(R.color.suw_color_background));
     }
 
     @Test
     public void testSetButtonTextColor() {
         setupFakeContentProvider();
         CarSetupWizardCompatLayout layout = createCarSetupWizardCompatLayout();
-        Button primary = layout.getPrimaryToolbarButton();
+        Button primary = layout.getPrimaryActionButton();
 
         layout.setButtonTextColor(
                 primary, PartnerConfig.CONFIG_LAYOUT_BG_COLOR);
@@ -558,8 +610,8 @@
     public void testSetBackground() {
         setupFakeContentProvider();
         CarSetupWizardCompatLayout layout = createCarSetupWizardCompatLayout();
-        layout.setSecondaryToolbarButtonVisible(true);
-        Button secondary = layout.getSecondaryToolbarButton();
+        layout.setSecondaryActionButtonVisible(true);
+        Button secondary = layout.getSecondaryActionButton();
 
         layout.setBackground(
                 secondary,
@@ -567,14 +619,14 @@
                 PartnerConfig.CONFIG_TOOLBAR_SECONDARY_BUTTON_BG_COLOR);
 
         Drawable expected = application.getResources().getDrawable(R.drawable.button_ripple_bg);
-        assertThat(getDrawbleDefaultColor(secondary.getBackground()))
-                .isEqualTo(getDrawbleDefaultColor(expected));
+        assertThat(getDrawableDefaultColor(secondary.getBackground()))
+                .isEqualTo(getDrawableDefaultColor(expected));
     }
 
     @Test
     public void test_bothButtons_areStyled_inDefaultLayout() {
-        Button primaryButton = mCarSetupWizardCompatLayout.getPrimaryToolbarButton();
-        Button secondaryButton = mCarSetupWizardCompatLayout.getSecondaryToolbarButton();
+        Button primaryButton = mCarSetupWizardLayoutInterface.getPrimaryActionButton();
+        Button secondaryButton = mCarSetupWizardLayoutInterface.getSecondaryActionButton();
 
         assertThat(primaryButton.getTextSize()).isWithin(TOLERANCE).of(EXCEPTED_TEXT_SIZE);
         assertThat(secondaryButton.getTextSize()).isWithin(TOLERANCE).of(EXCEPTED_TEXT_SIZE);
@@ -588,8 +640,8 @@
                 .get();
         CarSetupWizardCompatLayout layout = activity.findViewById(R.id.car_setup_wizard_layout);
 
-        Button primaryButton = layout.getPrimaryToolbarButton();
-        Button secondaryButton = layout.getSecondaryToolbarButton();
+        Button primaryButton = layout.getPrimaryActionButton();
+        Button secondaryButton = layout.getSecondaryActionButton();
 
         assertThat(primaryButton.getTextSize()).isWithin(TOLERANCE).of(EXCEPTED_TEXT_SIZE);
         assertThat(secondaryButton.getTextSize()).isWithin(TOLERANCE).of(EXCEPTED_TEXT_SIZE);
@@ -615,7 +667,7 @@
 
         CarSetupWizardCompatLayout layout = activity.findViewById(R.id.car_setup_wizard_layout);
         View toolbar = layout.findViewById(R.id.application_bar);
-        assertThat(toolbar.getTextDirection()).isEqualTo(View.TEXT_DIRECTION_LTR);
+        assertThat(toolbar.getLayoutDirection()).isEqualTo(View.LAYOUT_DIRECTION_LTR);
         assertThat(layout.shouldMirrorNavIcons()).isTrue();
     }
 
@@ -632,7 +684,7 @@
         return activity.findViewById(R.id.car_setup_wizard_layout);
     }
 
-    private @ColorRes int getDrawbleDefaultColor(Drawable drawable) {
+    private @ColorRes int getDrawableDefaultColor(Drawable drawable) {
         Drawable.ConstantState state = drawable.getConstantState();
         ColorStateList colorStateList = ReflectionHelpers.getField(state, "mColor");
         return colorStateList.getDefaultColor();
diff --git a/library/main/tests/robotests/src/com/android/car/setupwizardlib/FakeFeatureManagementProvider.java b/library/main/tests/robotests/src/com/android/car/setupwizardlib/FakeFeatureManagementProvider.java
new file mode 100644
index 0000000..273f88e
--- /dev/null
+++ b/library/main/tests/robotests/src/com/android/car/setupwizardlib/FakeFeatureManagementProvider.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 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.car.setupwizardlib;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import org.robolectric.Robolectric;
+
+/**
+ * An implementation of
+ * {@link com.google.android.car.setupwizard.common.config.FeatureManagementProvider} for
+ * Robolectric tests.
+ */
+public class FakeFeatureManagementProvider extends ContentProvider {
+    private static final String SUW_AUTHORITY =
+            "com.google.android.car.setupwizard.feature_management";
+    private static final String GET_FEATURE_VERSION_METHOD = "getFeatureVersion";
+    private static final String SPLIT_NAV_LAYOUT = "split_nav_layout";
+    private static final String TYPE = "type";
+    private static final String BOOLEAN_TYPE = "BOOLEAN";
+    private static final String VALUE = "value";
+
+    public static FakeFeatureManagementProvider installProvider() {
+        return Robolectric.setupContentProvider(FakeFeatureManagementProvider.class, SUW_AUTHORITY);
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(
+            Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        throw new UnsupportedOperationException("query operation not supported currently.");
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        throw new UnsupportedOperationException("getType operation not supported currently.");
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        throw new UnsupportedOperationException("insert operation not supported currently.");
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException("delete operation not supported currently.");
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException("update operation not supported currently.");
+    }
+
+    @Override
+    public Bundle call(String method, String feature, Bundle extras) {
+        Bundle bundle = new Bundle();
+        if (!GET_FEATURE_VERSION_METHOD.equals(method)) {
+            return bundle;
+        }
+
+        switch(feature) {
+            case SPLIT_NAV_LAYOUT:
+                bundle.putString(TYPE, BOOLEAN_TYPE);
+                bundle.putBoolean(VALUE, true);
+                break;
+            default:
+                // Do nothing
+        }
+        return bundle;
+    }
+}
diff --git a/library/main/tests/robotests/src/com/android/car/setupwizardlib/SplitNavLayoutTest.java b/library/main/tests/robotests/src/com/android/car/setupwizardlib/SplitNavLayoutTest.java
new file mode 100644
index 0000000..34f5a46
--- /dev/null
+++ b/library/main/tests/robotests/src/com/android/car/setupwizardlib/SplitNavLayoutTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2021 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.car.setupwizardlib;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.car.setupwizardlib.partner.ExternalResources;
+import com.android.car.setupwizardlib.partner.FakeOverrideContentProvider;
+import com.android.car.setupwizardlib.partner.PartnerConfig;
+import com.android.car.setupwizardlib.partner.ResourceEntry;
+import com.android.car.setupwizardlib.robolectric.BaseRobolectricTest;
+import com.android.car.setupwizardlib.shadows.ShadowConfiguration;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tests for split-nav layout
+ */
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowConfiguration.class)
+public class SplitNavLayoutTest extends BaseRobolectricTest {
+    private static final String TEST_PACKAGE_NAME = "test.packageName";
+
+    private static final PartnerConfig ULTRA_WIDE_SCREEN_CONTENT_WIDTH_RESOURCE_NAME =
+            PartnerConfig.CONFIG_ULTRA_WIDE_SCREEN_CONTENT_WIDTH;
+
+    private static final int PARTNER_CONTENT_WIDTH = 1500;
+
+    private FakeOverrideContentProvider mFakeOverrideContentProvider;
+
+    @Before
+    public void setUp() {
+        mFakeOverrideContentProvider = FakeOverrideContentProvider.installEmptyProvider();
+        FakeFeatureManagementProvider.installProvider();
+    }
+
+    @Test
+    @Config(qualifiers = "w1760dp-land")
+    public void test_UltraWideContentWidth_isSetToCustomWidth() {
+        List<ResourceEntry> resourceEntries = prepareCustomContentWidth();
+        for (ResourceEntry entry : resourceEntries) {
+            mFakeOverrideContentProvider.injectResourceEntry(entry);
+        }
+
+        Activity activity = Robolectric.buildActivity(CarSetupWizardLayoutTestActivity.class)
+                .create()
+                .get();
+        View contentContainer = activity.findViewById(R.id.ultra_wide_content_container);
+        ViewGroup.LayoutParams layoutParams = contentContainer.getLayoutParams();
+        assertThat(layoutParams.width).isEqualTo(PARTNER_CONTENT_WIDTH);
+    }
+
+    @Test
+    @Config(qualifiers = "w1760dp-land")
+    public void test_UltraWideContentWidthIsSetTo0_withoutCustomValue() {
+        Activity activity = Robolectric.buildActivity(CarSetupWizardLayoutTestActivity.class)
+                .create()
+                .get();
+
+        View contentContainer = activity.findViewById(R.id.ultra_wide_content_container);
+        ViewGroup.LayoutParams layoutParams = contentContainer.getLayoutParams();
+        assertThat(layoutParams.width).isEqualTo(0);
+    }
+
+    @Test
+    @Config(qualifiers = "iw-w1250dp-land")
+    public void test_layoutDirectionIsLtr_inRtrLocale() {
+        Activity activity = Robolectric.buildActivity(CarSetupWizardLayoutTestActivity.class)
+                .create()
+                .get();
+
+        View layout = activity.findViewById(R.id.car_setup_wizard_layout);
+        assertThat(layout.getLayoutDirection()).isEqualTo(View.LAYOUT_DIRECTION_LTR);
+
+        View buttonContainer = activity.findViewById(R.id.button_container);
+        assertThat(buttonContainer.getLayoutDirection()).isEqualTo(View.LAYOUT_DIRECTION_LTR);
+    }
+
+    @Test
+    @Config(qualifiers = "iw-w1760dp-land")
+    public void test_layoutDirectionIsLtrInUltraWide_isRtrLocale() {
+        Activity activity = Robolectric.buildActivity(CarSetupWizardLayoutTestActivity.class)
+                .create()
+                .get();
+
+        View layout = activity.findViewById(R.id.car_setup_wizard_layout);
+        assertThat(layout.getLayoutDirection()).isEqualTo(View.LAYOUT_DIRECTION_LTR);
+
+        View buttonContainer = activity.findViewById(R.id.button_container);
+        assertThat(buttonContainer.getLayoutDirection()).isEqualTo(View.LAYOUT_DIRECTION_LTR);
+    }
+
+    private List<ResourceEntry> prepareCustomContentWidth() {
+        ExternalResources.Resources testResources =
+                ExternalResources.injectExternalResources(TEST_PACKAGE_NAME);
+
+        testResources.putDimension(
+                ULTRA_WIDE_SCREEN_CONTENT_WIDTH_RESOURCE_NAME.getResourceName(),
+                PARTNER_CONTENT_WIDTH);
+
+        return Arrays.asList(
+                new ResourceEntry(
+                        TEST_PACKAGE_NAME,
+                        ULTRA_WIDE_SCREEN_CONTENT_WIDTH_RESOURCE_NAME.getResourceName(),
+                        testResources.getIdentifier(
+                                ULTRA_WIDE_SCREEN_CONTENT_WIDTH_RESOURCE_NAME.getResourceName(),
+                                /* defType= */ "dimen",
+                                TEST_PACKAGE_NAME))
+        );
+    }
+}
diff --git a/library/main/tests/robotests/src/com/android/car/setupwizardlib/util/FeatureResolverTest.java b/library/main/tests/robotests/src/com/android/car/setupwizardlib/util/FeatureResolverTest.java
new file mode 100644
index 0000000..6951030
--- /dev/null
+++ b/library/main/tests/robotests/src/com/android/car/setupwizardlib/util/FeatureResolverTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2021 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.car.setupwizardlib.util;
+
+import static com.android.car.setupwizardlib.util.FeatureResolver.VALUE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.car.setupwizardlib.robolectric.BaseRobolectricTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.robolectric.RobolectricTestRunner;
+
+import java.lang.reflect.Constructor;
+
+@RunWith(RobolectricTestRunner.class)
+public class FeatureResolverTest extends BaseRobolectricTest {
+
+    @Mock
+    private ContentResolver mContentResolver;
+
+    private FeatureResolver mFeatureResolver;
+    private Context mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        Constructor<FeatureResolver> constructor = FeatureResolver.class
+                .getDeclaredConstructor(Context.class);
+        constructor.setAccessible(true);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mFeatureResolver = constructor.newInstance(mContext);
+        doReturn(mContentResolver).when(mContext).getContentResolver();
+    }
+
+    @Test
+    public void testFeatureResolverInstance() {
+        assertThat(FeatureResolver.get(mContext)).isNotNull();
+    }
+
+    @Test
+    public void testFeatureResolverSingletonInstance() {
+        FeatureResolver instance = FeatureResolver.get(mContext);
+
+        assertThat(instance).isEqualTo(FeatureResolver.get(mContext));
+    }
+
+    @Test
+    public void testIsSplitNavLayoutFeatureEnabled_whenReturnsTrue() {
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(VALUE, true);
+        doReturn(bundle).when(mContentResolver).call((Uri) any(), any(), any(), any());
+
+        boolean isSplitNavLayoutFeatureEnabled = mFeatureResolver.isSplitNavLayoutFeatureEnabled();
+
+        assertThat(isSplitNavLayoutFeatureEnabled).isTrue();
+    }
+
+    @Test
+    public void testIsSplitNavLayoutFeatureEnabled_whenReturnsFalse() {
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(VALUE, false);
+        doReturn(bundle).when(mContentResolver).call((Uri) any(), any(), any(), any());
+
+        boolean isSplitNavLayoutFeatureEnabled = mFeatureResolver.isSplitNavLayoutFeatureEnabled();
+
+        assertThat(isSplitNavLayoutFeatureEnabled).isFalse();
+    }
+
+    @Test
+    public void testIsSplitNavLayoutFeatureEnabled_whenReturnsBundleNull() {
+        doReturn(null).when(mContentResolver).call((Uri) any(), any(), any(), any());
+
+        boolean isSplitNavLayoutFeatureEnabled = mFeatureResolver.isSplitNavLayoutFeatureEnabled();
+
+        assertThat(isSplitNavLayoutFeatureEnabled).isFalse();
+    }
+
+    @Test
+    public void testGetGModalVersion_whenVersionNumber1() {
+        Bundle bundle = new Bundle();
+        bundle.putInt(VALUE, 1);
+        doReturn(bundle).when(mContentResolver).call((Uri) any(), any(), any(), any());
+
+        int splitNavLayoutFeatureVersion = mFeatureResolver.getGModalVersion();
+
+        assertThat(splitNavLayoutFeatureVersion).isEqualTo(1);
+    }
+
+    @Test
+    public void testGModalVersion_whenVersionNumber0() {
+        Bundle bundle = new Bundle();
+        bundle.putInt(VALUE, 0);
+        doReturn(bundle).when(mContentResolver).call((Uri) any(), any(), any(), any());
+
+        int splitNavLayoutFeatureVersion = mFeatureResolver.getGModalVersion();
+
+        assertThat(splitNavLayoutFeatureVersion).isEqualTo(0);
+    }
+
+    @Test
+    public void testGetGModalVersion_whenReturnsBundleNull() {
+        doReturn(null).when(mContentResolver).call((Uri) any(), any(), any(), any());
+
+        int splitNavLayoutFeatureVersion = mFeatureResolver.getGModalVersion();
+
+        assertThat(splitNavLayoutFeatureVersion).isEqualTo(0);
+    }
+}
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..d8c51f0
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+include ':car-setup-wizard-lib'
+project(':car-setup-wizard-lib').projectDir = new File('./library/main')
+
+rootProject.name='CarSetupWizard'