Merge "Revert "call getName() from CachedBluetoothDevice, not CachedBluetoothDeviceManager""
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0c1ce65..71840b1 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -124,7 +124,7 @@
                 android:value="true" />
         </activity>
 
-        <activity android:name=".SettingsHomepageActivity"
+        <activity android:name=".homepage.SettingsHomepageActivity"
                   android:taskAffinity="com.android.settings.root"
                   android:label="@string/settings_label_launcher"
                   android:theme="@style/Theme.Settings.Home"
@@ -136,7 +136,7 @@
                 android:taskAffinity="com.android.settings.root"
                 android:label="@string/settings_label_launcher"
                 android:launchMode="singleTask"
-                android:targetActivity=".SettingsHomepageActivity">
+                android:targetActivity=".homepage.SettingsHomepageActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -1128,12 +1128,12 @@
             </intent-filter>
         </activity-alias>
 
-        <activity android:name=".applications.InstalledAppOpenByDefaultPage"
+        <activity android:name=".applications.InstalledAppOpenByDefaultActivity"
                   android:label="@string/application_info_label"
-                  android:permission="android.permission.OPEN_APPLICATION_DETAILS_OPEN_BY_DEFAULT_PAGE"
+                  android:permission="android.permission.OPEN_APP_OPEN_BY_DEFAULT_SETTINGS"
                   android:exported="true">
             <intent-filter android:priority="1">
-                <action android:name="android.settings.APPLICATION_DETAILS_SETTINGS_OPEN_BY_DEFAULT_PAGE" />
+                <action android:name="com.android.settings.APP_OPEN_BY_DEFAULT_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="package" />
             </intent-filter>
@@ -2709,8 +2709,7 @@
         <activity
             android:name="Settings$WifiCallingSettingsActivity"
             android:label="@string/wifi_calling_settings_title"
-            android:taskAffinity="com.android.settings"
-            android:parentActivityName="Settings">
+            android:taskAffinity="com.android.settings">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <action android:name="android.settings.WIFI_CALLING_SETTINGS" />
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index d72aaa8..4b36b50 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -37,22 +37,6 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="        app:barPredictionColor=&quot;@color/material_empty_color_light&quot;"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/layout/battery_history_chart.xml"
-            line="38"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="            android:textColor=&quot;@color/bluetooth_dialog_text_color&quot;  />"
         errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -2425,7 +2409,7 @@
         errorLine2="                                                                                                                                                                       ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rXC/strings.xml"
-            line="2559"
+            line="2524"
             column="168"/>
     </issue>
 
@@ -2441,7 +2425,7 @@
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rAU/strings.xml"
-            line="2560"
+            line="2525"
             column="64"/>
     </issue>
 
@@ -2457,7 +2441,7 @@
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rCA/strings.xml"
-            line="2560"
+            line="2525"
             column="64"/>
     </issue>
 
@@ -2473,7 +2457,7 @@
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rGB/strings.xml"
-            line="2560"
+            line="2525"
             column="64"/>
     </issue>
 
@@ -2489,7 +2473,7 @@
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rIN/strings.xml"
-            line="2560"
+            line="2525"
             column="64"/>
     </issue>
 
@@ -2505,7 +2489,7 @@
         errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/strings.xml"
-            line="5898"
+            line="5865"
             column="36"/>
     </issue>
 
@@ -2709,6 +2693,22 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="        &lt;item name=&quot;android:navigationBarDividerColor&quot;>#1f000000&lt;/item>"
+        errorLine2="                                                       ^">
+        <location
+            file="res/values/themes.xml"
+            line="175"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="        &lt;item name=&quot;wifi_signal_color&quot;>@color/setup_wizard_wifi_color_dark&lt;/item>"
         errorLine2="                                       ^">
         <location
diff --git a/res/color/bottom_navigation_colors.xml b/res/color/bottom_navigation_colors.xml
new file mode 100644
index 0000000..659ef50
--- /dev/null
+++ b/res/color/bottom_navigation_colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_checked="true"
+        android:color="?android:attr/colorAccent" />
+    <item
+        android:state_checked="false"
+        android:color="?android:attr/textColorPrimary" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable-nodpi/gesture_ambient_reach b/res/drawable-nodpi/gesture_ambient_reach
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/drawable-nodpi/gesture_ambient_reach
diff --git a/res/drawable/ic_list_24dp.xml b/res/drawable/ic_list_24dp.xml
deleted file mode 100644
index 03f4af0..0000000
--- a/res/drawable/ic_list_24dp.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:fillColor="?android:attr/colorAccent"
-      android:pathData="M4,13L4,13c0.55,0 1,-0.45 1,-1v0c0,-0.55 -0.45,-1 -1,-1h0c-0.55,0 -1,0.45 -1,1v0C3,12.55 3.45,13 4,13zM4,17L4,17c0.55,0 1,-0.45 1,-1v0c0,-0.55 -0.45,-1 -1,-1h0c-0.55,0 -1,0.45 -1,1v0C3,16.55 3.45,17 4,17zM4,9L4,9c0.55,0 1,-0.45 1,-1v0c0,-0.55 -0.45,-1 -1,-1h0C3.45,7 3,7.45 3,8v0C3,8.55 3.45,9 4,9zM7,13h14v-2H7V13zM7,17h14v-2H7V17zM7,7v2h14V7H7z"/>
-</vector>
diff --git a/res/drawable/ic_settings_all.xml b/res/drawable/ic_settings_all.xml
new file mode 100644
index 0000000..03958ab
--- /dev/null
+++ b/res/drawable/ic_settings_all.xml
@@ -0,0 +1,26 @@
+<!--
+    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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M3,12L3,3h9,9v9,9L12,21 3,21ZM19,12L19,5L12,5 5,5v7,7h7,7zM7,16c0,-0.55 0.45,-1 1,-1 0.55,0 1,0.45 1,1 0,0.55 -0.45,1 -1,1 -0.55,0 -1,-0.45 -1,-1zM11,16c0,-0.55 1.35,-1 3,-1 1.65,0 3,0.45 3,1 0,0.55 -1.35,1 -3,1 -1.65,0 -3,-0.45 -3,-1zM7,12c0,-0.55 0.45,-1 1,-1 0.55,0 1,0.45 1,1 0,0.55 -0.45,1 -1,1 -0.55,0 -1,-0.45 -1,-1zM11,12c0,-0.55 1.35,-1 3,-1 1.65,0 3,0.45 3,1 0,0.55 -1.35,1 -3,1 -1.65,0 -3,-0.45 -3,-1zM7,8C7,7.45 7.45,7 8,7 8.55,7 9,7.45 9,8 9,8.55 8.55,9 8,9 7.45,9 7,8.55 7,8ZM11,8c0,-0.55 1.35,-1 3,-1 1.65,0 3,0.45 3,1 0,0.55 -1.35,1 -3,1 -1.65,0 -3,-0.45 -3,-1z"
+      android:fillColor="#000000"/>
+</vector>
+
diff --git a/res/drawable/ic_settings_personal.xml b/res/drawable/ic_settings_personal.xml
new file mode 100644
index 0000000..5139405
--- /dev/null
+++ b/res/drawable/ic_settings_personal.xml
@@ -0,0 +1,28 @@
+<!--
+    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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M13.85,22.24h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.52c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.89 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73C7.91,5.2 8.17,5.05 8.43,4.91L8.7,3.01c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.7 14.59,22.24 13.85,22.24zM13.32,20.72c0,0.01 0,0.01 0,0.02V20.72zM10.68,20.69v0.02C10.69,20.72 10.69,20.7 10.68,20.69zM10.62,20.24h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96L15.6,7.28c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.69 8.84,6.94 8.38,7.3L7.93,7.62L5.55,6.67L4.16,9.06l2.03,1.58L6.12,11.2c-0.03,0.26 -0.06,0.53 -0.06,0.79s0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.24zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.7l0.01,0.02C5.78,17.72 5.77,17.7 5.77,17.7zM3.93,9.47L3.93,9.47L3.93,9.47zM18.22,6.26c0,0.01 0.01,0.02 0.01,0.02L18.22,6.26zM5.79,6.24L5.78,6.26C5.78,6.26 5.79,6.26 5.79,6.24zM13.31,3.27c0,0.01 0,0.01 0,0.02V3.27zM10.69,3.25v0.02C10.69,3.26 10.69,3.26 10.69,3.25z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M13.56,10.44l-1.56,-3.44l-1.56,3.44l-3.44,1.56l3.44,1.56l1.56,3.44l1.56,-3.44l3.44,-1.56z"/>
+</vector>
diff --git a/res/layout/homepage_condition_tile.xml b/res/layout/homepage_condition_tile.xml
new file mode 100644
index 0000000..50ef3c2
--- /dev/null
+++ b/res/layout/homepage_condition_tile.xml
@@ -0,0 +1,29 @@
+<!--
+     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.
+-->
+
+<androidx.cardview.widget.CardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    style="@style/SuggestionConditionStyle"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    app:cardUseCompatPadding="true"
+    app:cardElevation="@dimen/condition_card_elevation"
+    app:cardCornerRadius="@dimen/suggestion_card_corner_radius">
+
+    <include layout="@layout/condition_tile"/>
+
+</androidx.cardview.widget.CardView>
diff --git a/res/layout/master_clear.xml b/res/layout/master_clear.xml
index 9f89961..921347e 100644
--- a/res/layout/master_clear.xml
+++ b/res/layout/master_clear.xml
@@ -23,8 +23,8 @@
             android:id="@+id/master_clear_scrollview"
             android:layout_width="match_parent"
             android:layout_height="0dip"
-            android:layout_marginStart="@dimen/preference_no_icon_padding_start"
-            android:layout_marginEnd="12dp"
+            android:layout_marginStart="@dimen/reset_master_clear_margin_start"
+            android:layout_marginEnd="@dimen/reset_master_clear_margin_end"
             android:layout_marginTop="12dp"
             android:layout_weight="1">
         <LinearLayout
diff --git a/res/layout/reset_network.xml b/res/layout/reset_network.xml
index 1850bb2..7eb5d2a 100644
--- a/res/layout/reset_network.xml
+++ b/res/layout/reset_network.xml
@@ -23,8 +23,8 @@
     <ScrollView
         android:layout_width="match_parent"
         android:layout_height="0dip"
-        android:layout_marginStart="@dimen/preference_no_icon_padding_start"
-        android:layout_marginEnd="12dp"
+        android:layout_marginStart="@dimen/reset_network_margin_start"
+        android:layout_marginEnd="@dimen/reset_network_margin_end"
         android:layout_marginTop="12dp"
         android:layout_weight="1">
 
diff --git a/res/layout/screen_pinning_instructions.xml b/res/layout/screen_pinning_instructions.xml
index 80fec3c..fea5ed8 100644
--- a/res/layout/screen_pinning_instructions.xml
+++ b/res/layout/screen_pinning_instructions.xml
@@ -31,8 +31,8 @@
         android:paddingTop="@dimen/screen_pinning_textview_padding"
         android:text="@string/screen_pinning_description"
         android:textAppearance="@style/TextAppearance.Medium"
-        android:paddingStart="@dimen/screen_margin_sides"
-        android:paddingEnd="@dimen/screen_margin_sides"
+        android:paddingStart="@dimen/screen_pinning_padding_start"
+        android:paddingEnd="@dimen/screen_pinning_padding_end"
         />
 
 </ScrollView>
diff --git a/res/layout/settings_homepage.xml b/res/layout/settings_homepage.xml
index f1555ee..035e8b4 100644
--- a/res/layout/settings_homepage.xml
+++ b/res/layout/settings_homepage.xml
@@ -15,62 +15,8 @@
      limitations under the License.
 -->
 
-<androidx.coordinatorlayout.widget.CoordinatorLayout
+<androidx.recyclerview.widget.RecyclerView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/card_container"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/card_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-
-    <RelativeLayout
-        android:id="@+id/bottom_sheet"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="?android:attr/windowBackground"
-        android:minHeight="@dimen/homepage_bottomsheet_height"
-        app:layout_behavior="@string/bottom_sheet_behavior"
-        app:behavior_peekHeight="@dimen/homepage_bottomsheet_height">
-
-        <androidx.coordinatorlayout.widget.CoordinatorLayout
-            android:id="@+id/bottom_area"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <com.google.android.material.floatingactionbutton.FloatingActionButton
-                android:id="@+id/search_fab"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_search_floating_24dp"
-                app:backgroundTint="@android:color/white"
-                app:layout_anchor="@id/bar"/>
-
-            <com.google.android.material.bottomappbar.BottomAppBar
-                android:id="@+id/bar"
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/homepage_bottombar_height"
-                android:layout_alignParentTop="true"
-                android:layout_marginTop="@dimen/homepage_bottombar_top_margin"
-                android:clickable="true"
-                app:fabAttached="true"
-                app:fabAlignmentMode="end"
-                app:fabCradleDiameter="@dimen/homepage_bottombar_fab_cradle"
-                app:navigationIcon="@drawable/ic_list_24dp"
-                style="@style/Widget.MaterialComponents.BottomAppBar"/>
-        </androidx.coordinatorlayout.widget.CoordinatorLayout>
-
-        <include layout="@layout/search_bar"
-                 android:visibility="invisible"/>
-
-        <FrameLayout
-            android:id="@+id/bottom_sheet_fragment"
-            android:layout_below="@id/bottom_area"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"/>
-
-    </RelativeLayout>
-
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
+    android:layout_height="wrap_content" />
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 84511f2..b35b4ce 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -15,8 +15,38 @@
      limitations under the License.
 -->
 
-<FrameLayout
+<RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@id/main_content"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent"/>
\ No newline at end of file
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.google.android.material.bottomnavigation.BottomNavigationView
+        android:id="@+id/bottom_nav"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="0dp"
+        android:layout_marginStart="0dp"
+        android:background="?android:attr/windowBackground"
+        android:layout_alignParentBottom="true"
+        app:itemIconTint="@color/bottom_navigation_colors"
+        app:itemTextColor="@color/bottom_navigation_colors"
+        app:menu="@menu/home_bottom_navigation" />
+
+    <FrameLayout
+        android:id="@id/main_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_above="@+id/bottom_nav" />
+
+    <com.google.android.material.floatingactionbutton.FloatingActionButton
+        android:id="@+id/search_fab"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_search_24dp"
+        android:layout_margin="24dp"
+        android:layout_above="@id/bottom_nav"
+        android:layout_alignParentRight="true"
+        app:backgroundTint="?android:attr/colorAccent"
+        app:tint="@android:color/white" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/menu/home_bottom_navigation.xml b/res/menu/home_bottom_navigation.xml
new file mode 100644
index 0000000..c58efd7
--- /dev/null
+++ b/res/menu/home_bottom_navigation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/homepage_personal_settings"
+        android:icon="@drawable/ic_settings_personal"
+        android:title="@string/homepage_personal_settings" />
+    <item
+        android:id="@+id/homepage_all_settings"
+        android:icon="@drawable/ic_settings_all"
+        android:title="@string/homepage_all_settings" />
+</menu>
diff --git a/res/raw/gesture_ambient_reach.mp4 b/res/raw/gesture_ambient_reach.mp4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/raw/gesture_ambient_reach.mp4
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
index d5ea762..afdcd0e 100755
--- a/res/values-sw600dp-land/dimens.xml
+++ b/res/values-sw600dp-land/dimens.xml
@@ -29,4 +29,8 @@
 
     <dimen name="confirm_credentials_top_padding">20dp</dimen>
     <dimen name="confirm_credentials_top_margin">24dp</dimen>
+
+    <!-- Padding for screen pinning -->
+    <dimen name="screen_pinning_padding_start">128dp</dimen>
+    <dimen name="screen_pinning_padding_end">128dp</dimen>
 </resources>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 273225e..241471c 100755
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -62,4 +62,8 @@
     <dimen name="confirm_credentials_top_padding">48dp</dimen>
     <dimen name="confirm_credentials_side_margin">0dp</dimen>
     <dimen name="confirm_credentials_top_margin">64dp</dimen>
+
+    <!-- Padding for screen pinning -->
+    <dimen name="screen_pinning_padding_start">40dp</dimen>
+    <dimen name="screen_pinning_padding_end">40dp</dimen>
 </resources>
diff --git a/res/values-xlarge/dimens.xml b/res/values-xlarge/dimens.xml
index b6b4591..df9d56f 100755
--- a/res/values-xlarge/dimens.xml
+++ b/res/values-xlarge/dimens.xml
@@ -18,4 +18,8 @@
     <dimen name="screen_margin_sides">128dip</dimen>
     <dimen name="datetime_margin_top">154dip</dimen>
     <dimen name="datetime_margin_bottom">96dip</dimen>
+
+    <!-- Padding for screen pinning -->
+    <dimen name="screen_pinning_padding_start">128dp</dimen>
+    <dimen name="screen_pinning_padding_end">128dp</dimen>
 </resources>
diff --git a/res/values/bools.xml b/res/values/bools.xml
index f1abe9d..8bd11c7 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -174,6 +174,9 @@
     <!-- Whether wifi_mac_address should be shown or not. -->
     <bool name="config_show_wifi_mac_address">true</bool>
 
-    <!-- Whether to disable "Uninstall Updates" menu item for System apps or not.. -->
+    <!-- Whether to disable "Uninstall Updates" menu item for System apps or not. -->
     <bool name="config_disable_uninstall_update">false</bool>
+
+    <!-- Whether or not extra preview panels should be used for screen zoom setting. -->
+    <bool name="config_enable_extra_screen_zoom_preview">true</bool>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index acb895b..16d9f96 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -297,6 +297,16 @@
     <dimen name="battery_meter_width">66dp</dimen>
     <dimen name="battery_meter_height">100dp</dimen>
 
+    <!-- Margin for the reset screens -->
+    <dimen name="reset_network_margin_start">72dp</dimen>
+    <dimen name="reset_network_margin_end">12dp</dimen>
+    <dimen name="reset_master_clear_margin_start">72dp</dimen>
+    <dimen name="reset_master_clear_margin_end">12dp</dimen>
+
+    <!-- Padding for screen pinning -->
+    <dimen name="screen_pinning_padding_start">64dp</dimen>
+    <dimen name="screen_pinning_padding_end">64dp</dimen>
+
     <!-- Suggestion/condition header padding -->
     <dimen name="suggestion_condition_header_padding_collapsed">10dp</dimen>
     <dimen name="suggestion_condition_header_padding_expanded">5dp</dimen>
@@ -312,6 +322,9 @@
     <dimen name="suggestion_card_button_top_margin">16dp</dimen>
     <dimen name="suggestion_card_button_bottom_margin">18dp</dimen>
 
+    <!-- Condition cards size and padding -->
+    <dimen name="condition_card_elevation">2dp</dimen>
+
     <!-- Padding for the reset screens -->
     <dimen name="reset_checkbox_padding_end">8dp</dimen>
     <dimen name="reset_checkbox_title_padding_top">12dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 53abd54..c99d7ad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8193,7 +8193,7 @@
     <string name="encrypt_talkback_dialog_message_password">When you enter your password to start this device, accessibility services like <xliff:g id="service" example="TalkBack">%1$s</xliff:g> won\u2019t yet be available.</string>
 
     <!-- [CHAR LIMIT=NONE] Dialog body explaining that the app just selected by the user will not work after a reboot until until after the user enters their credentials, such as a PIN or password. -->
-    <string name="direct_boot_unaware_dialog_message">Note: After a reboot, this app can\'t start until you unlock your phone</string>
+    <string name="direct_boot_unaware_dialog_message">Note: If you restart your phone and have a screen lock set, this app can\'t start until you unlock your phone</string>
 
     <!-- Title and summary for SIM Status -->
     <string name="imei_information_title">IMEI information</string>
@@ -8948,8 +8948,6 @@
     <string name="disabled_by_policy_title_camera">Camera not allowed</string>
     <!-- Title for dialog displayed to tell user that screenshots are disabled by an admin [CHAR LIMIT=50] -->
     <string name="disabled_by_policy_title_screen_capture">Screenshot not allowed</string>
-    <!-- Title for dialog displayed to tell user that turning off backups is disallowed by an admin [CHAR LIMIT=50] -->
-    <string name="disabled_by_policy_title_turn_off_backups">Can’t turn off backups</string>
     <!-- Title for dialog displayed to tell user that the app was suspended by an admin [CHAR LIMIT=50] -->
     <string name="disabled_by_policy_title_suspend_packages">Can’t open this app</string>
     <!-- Shown when the user tries to change a settings locked by an admin [CHAR LIMIT=200] -->
@@ -9459,11 +9457,11 @@
     <!-- [CHAR LIMIT=60] Name of dev option called "System UI demo mode" -->
     <string name="demo_mode">System UI demo mode</string>
 
-    <!-- [CHAR LIMIT=60] Name of dev option that changes the UI Mode -->
-    <string name="dark_ui_mode">Night mode</string>
+    <!-- [CHAR LIMIT=60] Name of setting that changes the UI to dark -->
+    <string name="dark_ui_mode">Dark mode</string>
 
     <!-- [CHAR LIMIT=60] Name of dev option that changes the color of the UI -->
-    <string name="dark_ui_mode_title">Set Night mode</string>
+    <string name="dark_ui_mode_title">Set Dark mode</string>
 
     <!-- [CHAR LIMIT=60] Name of dev option to enable extra quick settings tiles -->
     <string name="quick_settings_developer_tiles">Quick settings developer tiles</string>
@@ -9471,9 +9469,6 @@
     <!-- [CHAR LIMIT=25] Title of developer tile to toggle winscope trace -->
     <string name="winscope_trace_quick_settings_title">Winscope Trace</string>
 
-    <!-- Template for formatting country and language. eg Canada - French [CHAR LIMIT=NONE]-->
-    <string name="support_country_format"><xliff:g id="country" example="Canada">%1$s</xliff:g> - <xliff:g id="language" example="French">%2$s</xliff:g></string>
-
     <!-- [CHAR LIMIT=60] Title of work profile setting page -->
     <string name="managed_profile_settings_title">Work profile settings</string>
     <!-- [CHAR LIMIT=60] The preference title for enabling cross-profile remote contact search -->
@@ -9584,19 +9579,10 @@
     <!-- Summary text for ambient display (device) [CHAR LIMIT=NONE]-->
     <string name="ambient_display_pickup_summary" product="device">To check time, notifications, and other info, pick up your device.</string>
 
-    <!-- Preference and settings suggestion title text for reach gesture (phone) [CHAR LIMIT=60]-->
-    <string name="ambient_display_reach_title" product="default">Reach to check phone</string>
-    <!-- Preference and settings suggestion title text for reach gesture (tablet) [CHAR LIMIT=60]-->
-    <string name="ambient_display_reach_title" product="tablet">Reach to check tablet</string>
-    <!-- Preference and settings suggestion title text for reach gesture (device) [CHAR LIMIT=60]-->
-    <string name="ambient_display_reach_title" product="device">Reach to check device</string>
-
-    <!-- Summary text for ambient display (phone) [CHAR LIMIT=NONE]-->
-    <string name="ambient_display_reach_summary" product="default">To check time, notifications, and other info, reach for your phone.</string>
-    <!-- Summary text for ambient display (tablet) [CHAR LIMIT=NONE]-->
-    <string name="ambient_display_reach_summary" product="tablet">To check time, notifications, and other info, reach for your tablet.</string>
-    <!-- Summary text for ambient display (device) [CHAR LIMIT=NONE]-->
-    <string name="ambient_display_reach_summary" product="device">To check time, notifications, and other info, reach for your device.</string>
+    <!-- Preference and settings suggestion title text for reach gesture [CHAR LIMIT=60]-->
+    <string name="ambient_display_reach_title">Reach gesture</string>
+    <!-- Summary text for ambient display [CHAR LIMIT=NONE]-->
+    <string name="ambient_display_reach_summary" product="default"></string>
 
     <!-- Title text for swiping downwards on fingerprint sensor for notifications [CHAR LIMIT=80]-->
     <string name="fingerprint_swipe_for_notifications_title">Swipe fingerprint for notifications</string>
@@ -9761,8 +9747,6 @@
         <item quantity="one"><xliff:g id="count">%d</xliff:g> attempt</item>
         <item quantity="other"><xliff:g id="count">%d</xliff:g> attempts</item>
     </plurals>
-    <!-- List item in a work device's settings. This text lets the user know that their IT administrator requires their device's data to be backed up. The user can't change this setting. [CHAR LIMIT=NONE] -->
-    <string name="enterprise_privacy_backups_enabled">This device\'s data is being backed up</string>
     <!-- Message indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=NONE] -->
     <string name="do_disclosure_generic">This device is managed by your organization.</string>
     <!-- Message indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=NONE] -->
@@ -10078,4 +10062,10 @@
     <!-- UI debug setting: Enable High Refresh Rate virtual panel [CHAR LIMIT=50] -->
     <string name="high_frequency_display_device_summary">Enable Virtual High Frequency Panel</string>
 
+    <!-- Homepage bottom menu. Title for display all Settings [CHAR LIMIT=30] -->
+    <string name="homepage_all_settings">All Settings</string>
+
+    <!-- Homepage bottom menu. Title for display personalized Settings [CHAR LIMIT=30] -->
+    <string name="homepage_personal_settings">Your Settings</string>
+
 </resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 7fd0dcc..4bd6f52 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -167,6 +167,7 @@
 
     <style name="Theme.Settings.Home" parent="Theme.AppCompat.DayNight.NoActionBar">
         <!-- Color names copied from frameworks/base/core/res/res/values/themes_device_defaults.xml -->
+        <!-- TODO (b/113964702) : fix theme color -->
         <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
         <item name="colorPrimaryDark">@*android:color/primary_dark_device_default_settings_light</item>
         <item name="colorAccent">@*android:color/accent_device_default_light</item>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 95dba41..a76bef7 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -47,7 +47,7 @@
             android:title="@string/display_category_title">
 
         <Preference
-            android:fragment="com.android.settings.accessibility.ToggleFontSizePreferenceFragment"
+            android:fragment="com.android.settings.display.ToggleFontSizePreferenceFragment"
             android:key="font_size_preference_screen"
             android:title="@string/title_font_size"
             settings:searchable="false"/>
diff --git a/res/xml/accessibility_settings_for_setup_wizard.xml b/res/xml/accessibility_settings_for_setup_wizard.xml
index c1141ab..738bb8e 100644
--- a/res/xml/accessibility_settings_for_setup_wizard.xml
+++ b/res/xml/accessibility_settings_for_setup_wizard.xml
@@ -33,7 +33,7 @@
 
     <Preference
         android:fragment=
-                "com.android.settings.accessibility.FontSizePreferenceFragmentForSetupWizard"
+                "com.android.settings.display.FontSizePreferenceFragmentForSetupWizard"
         android:key="font_size_preference"
         android:title="@string/title_font_size"
         android:summary="@string/short_summary_font_size" />
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 54769cf..db4e7d8 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -83,7 +83,7 @@
     <Preference
         android:key="font_size"
         android:title="@string/title_font_size"
-        android:fragment="com.android.settings.accessibility.ToggleFontSizePreferenceFragment"
+        android:fragment="com.android.settings.display.ToggleFontSizePreferenceFragment"
         settings:controller="com.android.settings.display.FontSizePreferenceController" />
 
     <com.android.settings.display.ScreenZoomPreference
diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml
index 0aa1415..4fa50e7 100644
--- a/res/xml/enterprise_privacy_settings.xml
+++ b/res/xml/enterprise_privacy_settings.xml
@@ -83,9 +83,6 @@
         <Preference android:key="ca_certs_managed_profile"
                     android:title="@string/enterprise_privacy_ca_certs_work"
                     android:selectable="false"/>
-        <Preference android:key="backups_enabled"
-                    android:title="@string/enterprise_privacy_backups_enabled"
-                    android:selectable="false"/>
     </PreferenceCategory>
 
     <PreferenceCategory android:key="device_access_category"
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index 9f69102..aa99446 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -28,6 +28,12 @@
         settings:controller="com.android.settings.gestures.AssistGestureSettingsPreferenceController" />
 
     <Preference
+        android:key="gesture_reach_summary"
+        android:title="@string/ambient_display_reach_title"
+        android:fragment="com.android.settings.gestures.ReachGestureSettings"
+        settings:controller="com.android.settings.gestures.ReachGesturePreferenceController" />
+
+    <Preference
         android:key="gesture_swipe_down_fingerprint_input_summary"
         android:title="@string/fingerprint_swipe_for_notifications_title"
         android:fragment="com.android.settings.gestures.SwipeToNotificationSettings"
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 957ba81..535f61a 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -72,10 +72,18 @@
         <intent android:action="android.settings.SHOW_REGULATORY_INFO"/>
     </Preference>
 
+    <!-- Safety & regulatory manual -->
+    <Preference
+        android:key="safety_info"
+        android:order="7"
+        android:title="@string/safety_and_regulatory_info">
+        <intent android:action="android.settings.SHOW_SAFETY_AND_REGULATORY_INFO"/>
+    </Preference>
+
     <!-- SIM status -->
     <Preference
         android:key="sim_status"
-        android:order="7"
+        android:order="8"
         android:title="@string/sim_status_title"
         settings:keywords="@string/keywords_sim_status"
         android:summary="@string/summary_placeholder"
@@ -142,14 +150,6 @@
         android:summary="@string/summary_placeholder"
         android:selectable="false" />
 
-    <!-- Safety & regulatory manual -->
-    <Preference
-        android:key="safety_info"
-        android:order="39"
-        android:title="@string/safety_and_regulatory_info">
-        <intent android:action="android.settings.SHOW_SAFETY_AND_REGULATORY_INFO"/>
-    </Preference>
-
     <!-- Manual -->
     <Preference
         android:key="manual"
diff --git a/res/xml/reach_gesture_settings.xml b/res/xml/reach_gesture_settings.xml
index 1acc364..e933e15 100644
--- a/res/xml/reach_gesture_settings.xml
+++ b/res/xml/reach_gesture_settings.xml
@@ -23,8 +23,8 @@
 
     <com.android.settings.widget.VideoPreference
         android:key="gesture_reach_video"
-        app:animation="@raw/gesture_ambient_lift"
-        app:preview="@drawable/gesture_ambient_lift" />
+        app:animation="@raw/gesture_ambient_reach"
+        app:preview="@drawable/gesture_ambient_reach" />
 
     <SwitchPreference
         android:key="gesture_reach"
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java
index c553e34..319d599 100644
--- a/src/com/android/settings/CredentialStorage.java
+++ b/src/com/android/settings/CredentialStorage.java
@@ -106,6 +106,7 @@
     private static final int CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST = 2;
 
     private final KeyStore mKeyStore = KeyStore.getInstance();
+    private LockPatternUtils mUtils;
 
     /**
      * When non-null, the bundle containing credentials to install.
@@ -113,6 +114,12 @@
     private Bundle mInstallBundle;
 
     @Override
+    protected void onCreate(Bundle savedState) {
+        super.onCreate(savedState);
+        mUtils = new LockPatternUtils(this);
+    }
+
+    @Override
     protected void onResume() {
         super.onResume();
 
@@ -160,7 +167,7 @@
                 return;
             }
             case UNLOCKED: {
-                if (isActivePasswordQualityInsufficient()) {
+                if (!mUtils.isSecure(UserHandle.myUserId())) {
                     final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
                     dialog.show(getSupportFragmentManager(), ConfigureKeyGuardDialog.TAG);
                     return;
@@ -179,7 +186,7 @@
      * case after unlocking with an old-style password).
      */
     private void ensureKeyGuard() {
-        if (isActivePasswordQualityInsufficient()) {
+        if (!mUtils.isSecure(UserHandle.myUserId())) {
             // key guard not setup, doing so will initialize keystore
             final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
             dialog.show(getSupportFragmentManager(), ConfigureKeyGuardDialog.TAG);
@@ -194,16 +201,6 @@
         finish();
     }
 
-    /**
-     * Returns true if the currently set key guard violates our minimum quality requirements.
-     */
-    private boolean isActivePasswordQualityInsufficient() {
-        final int credentialOwner =
-                UserManager.get(this).getCredentialOwnerProfile(UserHandle.myUserId());
-        final int quality = new LockPatternUtils(this).getActivePasswordQuality(credentialOwner);
-        return (quality >= MIN_PASSWORD_QUALITY);
-    }
-
     private boolean isHardwareBackedKey(byte[] keyData) {
         try {
             final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
@@ -350,7 +347,7 @@
         protected Boolean doInBackground(Void... unused) {
 
             // Clear all the users credentials could have been installed in for this user.
-            new LockPatternUtils(CredentialStorage.this).resetKeyStore(UserHandle.myUserId());
+            mUtils.resetKeyStore(UserHandle.myUserId());
 
             try {
                 final KeyChainConnection keyChainConnection = KeyChain.bind(CredentialStorage.this);
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 6c084ab..c8ec448 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -62,6 +62,7 @@
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settings.password.ConfirmLockPattern;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.util.List;
 
@@ -499,11 +500,12 @@
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
         final Context context = getContext();
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(context,
+        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
                 UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId());
         final UserManager um = UserManager.get(context);
-        final boolean disallow = !um.isAdminUser() || RestrictedLockUtils.hasBaseUserRestriction(
-                context, UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId());
+        final boolean disallow = !um.isAdminUser() || RestrictedLockUtilsInternal
+                .hasBaseUserRestriction(context, UserManager.DISALLOW_FACTORY_RESET,
+                        UserHandle.myUserId());
         if (disallow && !Utils.isDemoUser(context)) {
             return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
         } else if (admin != null) {
diff --git a/src/com/android/settings/MasterClearConfirm.java b/src/com/android/settings/MasterClearConfirm.java
index 0ea7250..cfd20eb 100644
--- a/src/com/android/settings/MasterClearConfirm.java
+++ b/src/com/android/settings/MasterClearConfirm.java
@@ -38,6 +38,7 @@
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 /**
  * Confirm and execute a reset of the device to a clean "just out of the box"
@@ -146,9 +147,9 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 getActivity(), UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId());
-        if (RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
+        if (RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(),
                 UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId())) {
             return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
         } else if (admin != null) {
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index 22e5716..c1eca16 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -50,6 +50,7 @@
 import com.android.settings.password.ConfirmLockPattern;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -240,9 +241,9 @@
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
         final UserManager um = UserManager.get(getActivity());
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 getActivity(), UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
-        if (!um.isAdminUser() || RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
+        if (!um.isAdminUser() || RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(),
                 UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
             return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
         } else if (admin != null) {
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index e3bd8f1..2044af5 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -50,6 +50,7 @@
 import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settings.network.ApnSettings;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 /**
  * Confirm and execute a reset of the network settings to a clean "just out of the box"
@@ -204,9 +205,9 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 getActivity(), UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
-        if (RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
+        if (RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(),
                 UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
             return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
         } else if (admin != null) {
diff --git a/src/com/android/settings/RestrictedCheckBox.java b/src/com/android/settings/RestrictedCheckBox.java
index 2d45880..828c443 100644
--- a/src/com/android/settings/RestrictedCheckBox.java
+++ b/src/com/android/settings/RestrictedCheckBox.java
@@ -24,6 +24,7 @@
 import android.widget.CheckBox;
 
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 /**
  * A checkbox that can be restricted by device policy, in which case it shows a dialog explaining
@@ -57,7 +58,8 @@
         mEnforcedAdmin = admin;
         if (mDisabledByAdmin != disabled) {
             mDisabledByAdmin = disabled;
-            RestrictedLockUtils.setTextViewAsDisabledByAdmin(mContext, this, mDisabledByAdmin);
+            RestrictedLockUtilsInternal.setTextViewAsDisabledByAdmin(mContext, this,
+                    mDisabledByAdmin);
             if (mDisabledByAdmin) {
                 getButtonDrawable().setColorFilter(mContext.getColor(R.color.disabled_text_color),
                         PorterDuff.Mode.MULTIPLY);
diff --git a/src/com/android/settings/RestrictedRadioButton.java b/src/com/android/settings/RestrictedRadioButton.java
index 7efba4f..20c2872 100644
--- a/src/com/android/settings/RestrictedRadioButton.java
+++ b/src/com/android/settings/RestrictedRadioButton.java
@@ -25,6 +25,7 @@
 import android.widget.TextView;
 
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 public class RestrictedRadioButton extends RadioButton {
     private Context mContext;
@@ -63,7 +64,7 @@
         mEnforcedAdmin = admin;
         if (mDisabledByAdmin != disabled) {
             mDisabledByAdmin = disabled;
-            RestrictedLockUtils.setTextViewAsDisabledByAdmin(mContext,
+            RestrictedLockUtilsInternal.setTextViewAsDisabledByAdmin(mContext,
                     (TextView) this, mDisabledByAdmin);
             if (mDisabledByAdmin) {
                 getButtonDrawable().setColorFilter(mContext.getColor(R.color.disabled_text_color),
diff --git a/src/com/android/settings/RestrictedSettingsFragment.java b/src/com/android/settings/RestrictedSettingsFragment.java
index 7fab528..df438d5 100644
--- a/src/com/android/settings/RestrictedSettingsFragment.java
+++ b/src/com/android/settings/RestrictedSettingsFragment.java
@@ -37,6 +37,7 @@
 import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 /**
  * Base class for settings screens that should be pin protected when in restricted mode or
@@ -219,7 +220,7 @@
     }
 
     public EnforcedAdmin getRestrictionEnforcedAdmin() {
-        mEnforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(),
+        mEnforcedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(getActivity(),
                 mRestrictionKey, UserHandle.myUserId());
         if (mEnforcedAdmin != null && mEnforcedAdmin.userId == UserHandle.USER_NULL) {
             mEnforcedAdmin.userId = UserHandle.myUserId();
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 4ca1c2c..ffce321 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -62,6 +62,8 @@
 import com.android.settings.core.gateway.SettingsGateway;
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.DashboardSummary;
+import com.android.settings.homepage.SettingsHomepageActivity;
+import com.android.settings.homepage.TopLevelSettings;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DeviceIndexFeatureProvider;
 import com.android.settings.wfd.WifiDisplaySettings;
@@ -403,8 +405,13 @@
             // Show search icon as up affordance if we are displaying the main Dashboard
             mInitialTitleResId = R.string.dashboard_title;
 
-            switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
-                    mInitialTitleResId, mInitialTitle, false);
+            if (SettingsHomepageActivity.isDynamicHomepageEnabled(this)) {
+                switchToFragment(TopLevelSettings.class.getName(), null /* args */, false, false,
+                        mInitialTitleResId, mInitialTitle, false);
+            } else {
+                switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
+                        mInitialTitleResId, mInitialTitle, false);
+            }
         }
     }
 
diff --git a/src/com/android/settings/SettingsHomepageActivity.java b/src/com/android/settings/SettingsHomepageActivity.java
deleted file mode 100644
index 6e583c7..0000000
--- a/src/com/android/settings/SettingsHomepageActivity.java
+++ /dev/null
@@ -1,65 +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.settings;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.FeatureFlagUtils;
-
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
-import androidx.fragment.app.FragmentManager;
-
-import com.android.settings.core.FeatureFlags;
-import com.android.settings.core.SettingsBaseActivity;
-import com.android.settings.homepage.HomepageFragment;
-
-public class SettingsHomepageActivity extends SettingsBaseActivity {
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        if (!isDynamicHomepageEnabled(this)) {
-            final Intent settings = new Intent();
-            settings.setAction("android.settings.SETTINGS");
-            startActivity(settings);
-            finish();
-            return;
-        }
-        setContentView(R.layout.settings_homepage_container);
-        if (savedInstanceState == null) {
-            switchToFragment(this, R.id.main_content, HomepageFragment.class.getName());
-        }
-    }
-
-    public static boolean isDynamicHomepageEnabled(Context context) {
-        return FeatureFlagUtils.isEnabled(context, FeatureFlags.DYNAMIC_HOMEPAGE);
-    }
-
-    /**
-     * Switch to a specific Fragment
-     */
-    public static void switchToFragment(FragmentActivity activity, int id, String fragmentName) {
-        final Fragment f = Fragment.instantiate(activity, fragmentName, null /* args */);
-
-        FragmentManager manager = activity.getSupportFragmentManager();
-        manager.beginTransaction().replace(id, f).commitAllowingStateLoss();
-        manager.executePendingTransactions();
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 4197e2f..87a3511 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -541,10 +541,6 @@
         private DialogInterface.OnCancelListener mOnCancelListener;
         private DialogInterface.OnDismissListener mOnDismissListener;
 
-        public SettingsDialogFragment() {
-            /* do nothing */
-        }
-
         public SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
             super(fragment, dialogId);
             if (!(fragment instanceof Fragment)) {
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 02f9cc5..d32e387 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -423,9 +423,6 @@
                 startTethering(TETHERING_BLUETOOTH);
             } else {
                 mCm.stopTethering(TETHERING_BLUETOOTH);
-                // No ACTION_TETHER_STATE_CHANGED is fired or bluetooth unless a device is
-                // connected. Need to update state manually.
-                updateState();
             }
         }
 
diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java
index abd8641..b1f9fe7 100644
--- a/src/com/android/settings/UserCredentialsSettings.java
+++ b/src/com/android/settings/UserCredentialsSettings.java
@@ -53,6 +53,7 @@
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.security.UnrecoverableKeyException;
 import java.util.ArrayList;
@@ -137,11 +138,12 @@
 
             final String restriction = UserManager.DISALLOW_CONFIG_CREDENTIALS;
             final int myUserId = UserHandle.myUserId();
-            if (!RestrictedLockUtils.hasBaseUserRestriction(getContext(), restriction, myUserId)) {
+            if (!RestrictedLockUtilsInternal.hasBaseUserRestriction(getContext(), restriction,
+                    myUserId)) {
                 DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
                     @Override public void onClick(DialogInterface dialog, int id) {
-                        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
-                                getContext(), restriction, myUserId);
+                        final EnforcedAdmin admin = RestrictedLockUtilsInternal
+                                .checkIfRestrictionEnforced(getContext(), restriction, myUserId);
                         if (admin != null) {
                             RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
                                     admin);
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 5744703..9a8ef54 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -55,9 +55,10 @@
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
+import com.android.settings.display.ToggleFontSizePreferenceFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.accessibility.AccessibilityUtils;
 import com.android.settingslib.search.SearchIndexable;
@@ -584,7 +585,7 @@
                     permittedServices == null || permittedServices.contains(packageName);
             if (!serviceAllowed && !serviceEnabled) {
                 final EnforcedAdmin admin =
-                        RestrictedLockUtils.checkIfAccessibilityServiceDisallowed(
+                        RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed(
                                 getActivity(), packageName, UserHandle.myUserId());
                 if (admin != null) {
                     preference.setDisabledByAdmin(admin);
diff --git a/src/com/android/settings/accounts/AccountRestrictionHelper.java b/src/com/android/settings/accounts/AccountRestrictionHelper.java
index 5fa83b3..05b27aa 100644
--- a/src/com/android/settings/accounts/AccountRestrictionHelper.java
+++ b/src/com/android/settings/accounts/AccountRestrictionHelper.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 
 import com.android.settings.AccessiblePreferenceCategory;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 
 import java.util.ArrayList;
@@ -51,7 +51,8 @@
     }
 
     public boolean hasBaseUserRestriction(String userRestriction, @UserIdInt int userId) {
-        return RestrictedLockUtils.hasBaseUserRestriction(mContext, userRestriction, userId);
+        return RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext, userRestriction,
+                userId);
     }
 
     public AccessiblePreferenceCategory createAccessiblePreferenceCategory(Context context) {
diff --git a/src/com/android/settings/accounts/ChooseAccountPreferenceController.java b/src/com/android/settings/accounts/ChooseAccountPreferenceController.java
index 5ac5bc0..a217f01 100644
--- a/src/com/android/settings/accounts/ChooseAccountPreferenceController.java
+++ b/src/com/android/settings/accounts/ChooseAccountPreferenceController.java
@@ -39,6 +39,7 @@
 
 import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import com.google.android.collect.Maps;
 
@@ -167,7 +168,7 @@
             // There's only one provider that matches. If it is disabled by admin show the
             // support dialog otherwise run it.
             final RestrictedLockUtils.EnforcedAdmin admin =
-                    RestrictedLockUtils.checkIfAccountManagementDisabled(
+                    RestrictedLockUtilsInternal.checkIfAccountManagementDisabled(
                             context, mProviderList.get(0).getType(), mUserHandle.getIdentifier());
             if (admin != null) {
                 mActivity.setResult(RESULT_CANCELED,
diff --git a/src/com/android/settings/accounts/ContactSearchPreferenceController.java b/src/com/android/settings/accounts/ContactSearchPreferenceController.java
index e0ddf24..8b94ba1 100644
--- a/src/com/android/settings/accounts/ContactSearchPreferenceController.java
+++ b/src/com/android/settings/accounts/ContactSearchPreferenceController.java
@@ -24,6 +24,7 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.slices.SliceData;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 
 public class ContactSearchPreferenceController extends BasePreferenceController implements
@@ -52,7 +53,7 @@
             pref.setChecked(isChecked());
             if (mManagedUser != null) {
                 final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
-                        RestrictedLockUtils.checkIfRemoteContactSearchDisallowed(
+                        RestrictedLockUtilsInternal.checkIfRemoteContactSearchDisallowed(
                                 mContext, mManagedUser.getIdentifier());
                 pref.setDisabledByAdmin(enforcedAdmin);
             }
diff --git a/src/com/android/settings/accounts/ProviderPreference.java b/src/com/android/settings/accounts/ProviderPreference.java
index 1143f8d..b39f561 100644
--- a/src/com/android/settings/accounts/ProviderPreference.java
+++ b/src/com/android/settings/accounts/ProviderPreference.java
@@ -21,7 +21,7 @@
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 
 /**
@@ -47,7 +47,7 @@
     }
 
     public void checkAccountManagementAndSetDisabled(int userId) {
-        EnforcedAdmin admin = RestrictedLockUtils.checkIfAccountManagementDisabled(
+        EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfAccountManagementDisabled(
                 getContext(), getAccountType(), userId);
         setDisabledByAdmin(admin);
     }
diff --git a/src/com/android/settings/accounts/RemoveAccountPreferenceController.java b/src/com/android/settings/accounts/RemoveAccountPreferenceController.java
index 7753f81..2494664 100644
--- a/src/com/android/settings/accounts/RemoveAccountPreferenceController.java
+++ b/src/com/android/settings/accounts/RemoveAccountPreferenceController.java
@@ -44,6 +44,7 @@
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 import java.io.IOException;
@@ -84,8 +85,8 @@
     @Override
     public void onClick(View v) {
         if (mUserHandle != null) {
-            final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
-                    UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle.getIdentifier());
+            final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+                    mContext, UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle.getIdentifier());
             if (admin != null) {
                 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, admin);
                 return;
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 815d0ed..fd870d6 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -48,7 +48,7 @@
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 
@@ -107,10 +107,10 @@
     @Override
     public void onResume() {
         super.onResume();
-        mAppsControlDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(),
-                UserManager.DISALLOW_APPS_CONTROL, mUserId);
-        mAppsControlDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
-                UserManager.DISALLOW_APPS_CONTROL, mUserId);
+        mAppsControlDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+                getActivity(), UserManager.DISALLOW_APPS_CONTROL, mUserId);
+        mAppsControlDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction(
+                getActivity(), UserManager.DISALLOW_APPS_CONTROL, mUserId);
 
         if (!refreshUi()) {
             setIntentAndFinish(true, true);
diff --git a/src/com/android/settings/applications/InstalledAppOpenByDefaultPage.java b/src/com/android/settings/applications/InstalledAppOpenByDefaultActivity.java
similarity index 93%
rename from src/com/android/settings/applications/InstalledAppOpenByDefaultPage.java
rename to src/com/android/settings/applications/InstalledAppOpenByDefaultActivity.java
index 40eef25..cd30d79 100644
--- a/src/com/android/settings/applications/InstalledAppOpenByDefaultPage.java
+++ b/src/com/android/settings/applications/InstalledAppOpenByDefaultActivity.java
@@ -20,7 +20,7 @@
 
 import com.android.settings.SettingsActivity;
 
-public class InstalledAppOpenByDefaultPage extends SettingsActivity {
+public class InstalledAppOpenByDefaultActivity extends SettingsActivity {
 
     @Override
     public Intent getIntent() {
diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
index d6dfe64..12c4d9d 100644
--- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
@@ -55,6 +55,7 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.ActionButtonPreference;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -181,10 +182,10 @@
     @Override
     public void onResume() {
         if (isAvailable() && !mFinishing) {
-            mAppsControlDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(mActivity,
-                    UserManager.DISALLOW_APPS_CONTROL, mUserId);
-            mAppsControlDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(mActivity,
-                    UserManager.DISALLOW_APPS_CONTROL, mUserId);
+            mAppsControlDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction(
+                    mActivity, UserManager.DISALLOW_APPS_CONTROL, mUserId);
+            mAppsControlDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+                    mActivity, UserManager.DISALLOW_APPS_CONTROL, mUserId);
 
             if (!refreshUi()) {
                 setIntentAndFinish(true);
@@ -214,10 +215,11 @@
                 return;
             }
             RestrictedLockUtils.EnforcedAdmin admin =
-                    RestrictedLockUtils.checkIfUninstallBlocked(mActivity,
+                    RestrictedLockUtilsInternal.checkIfUninstallBlocked(mActivity,
                             packageName, mUserId);
             boolean uninstallBlockedBySystem = mAppsControlDisallowedBySystem ||
-                    RestrictedLockUtils.hasBaseUserRestriction(mActivity, packageName, mUserId);
+                    RestrictedLockUtilsInternal.hasBaseUserRestriction(mActivity, packageName,
+                            mUserId);
             if (admin != null && !uninstallBlockedBySystem) {
                 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mActivity, admin);
             } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 422c305..7b9cc79 100755
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -50,7 +50,7 @@
         .PictureInPictureDetailPreferenceController;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -185,17 +185,23 @@
         mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
         mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
         mPm = activity.getPackageManager();
-
         if (!ensurePackageInfoAvailable(activity)) {
             return;
         }
-
         startListeningToPackageRemove();
 
         setHasOptionsMenu(true);
     }
 
     @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        if (!ensurePackageInfoAvailable(getActivity())) {
+            return;
+        }
+        super.onCreatePreferences(savedInstanceState, rootKey);
+    }
+
+    @Override
     public void onDestroy() {
         stopListeningToPackageRemove();
         super.onDestroy();
@@ -210,10 +216,10 @@
     public void onResume() {
         super.onResume();
         final Activity activity = getActivity();
-        mAppsControlDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(activity,
-                UserManager.DISALLOW_APPS_CONTROL, mUserId);
-        mAppsControlDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(activity,
-                UserManager.DISALLOW_APPS_CONTROL, mUserId);
+        mAppsControlDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+                activity, UserManager.DISALLOW_APPS_CONTROL, mUserId);
+        mAppsControlDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction(
+                activity, UserManager.DISALLOW_APPS_CONTROL, mUserId);
 
         if (!refreshUi()) {
             setIntentAndFinish(true, true);
@@ -338,7 +344,7 @@
                 && !mAppsControlDisallowedBySystem
                 && !uninstallUpdateDisabled);
         if (uninstallUpdatesItem.isVisible()) {
-            RestrictedLockUtils.setMenuItemAsDisabledByAdmin(getActivity(),
+            RestrictedLockUtilsInternal.setMenuItemAsDisabledByAdmin(getActivity(),
                     uninstallUpdatesItem, mAppsControlDisallowedAdmin);
         }
     }
diff --git a/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
index ec6ea8c..9e76ff5 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
@@ -111,7 +111,7 @@
         final List<ResolveInfo> candidates = new ArrayList<>();
         // Resolve that intent and check that the handleAllWebDataURI boolean is set
         final List<ResolveInfo> list = packageManager.queryIntentActivitiesAsUser(
-            BROWSE_PROBE, PackageManager.MATCH_ALL, userId);
+            BROWSE_PROBE, 0 /* flags */, userId);
         if (list != null) {
             final Set<String> addedPackages = new ArraySet<>();
             for (ResolveInfo info : list) {
@@ -181,13 +181,12 @@
      * Whether or not the pkg is the default browser
      */
     public boolean isBrowserDefault(String pkg, int userId) {
-        String defaultPackage = mPackageManager.getDefaultBrowserPackageNameAsUser(userId);
+        final String defaultPackage = mPackageManager.getDefaultBrowserPackageNameAsUser(userId);
         if (defaultPackage != null) {
             return defaultPackage.equals(pkg);
         }
 
-        final List<ResolveInfo> list = mPackageManager.queryIntentActivitiesAsUser(BROWSE_PROBE,
-                PackageManager.MATCH_ALL, userId);
+        final List<ResolveInfo> list = getCandidates(mPackageManager, userId);
         // There is only 1 app, it must be the default browser.
         return list != null && list.size() == 1;
     }
diff --git a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
index 021a953..e46f294 100644
--- a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
+++ b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
@@ -73,8 +73,8 @@
     static View newView(ViewGroup parent, boolean twoTarget) {
         ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext())
                 .inflate(R.layout.preference_app, parent, false);
+        final ViewGroup widgetFrame = view.findViewById(android.R.id.widget_frame);
         if (twoTarget) {
-            final ViewGroup widgetFrame = view.findViewById(android.R.id.widget_frame);
             if (widgetFrame != null) {
                LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.preference_widget_master_switch, widgetFrame, true);
@@ -84,6 +84,8 @@
                // second to last, before widget frame
                view.addView(divider, view.getChildCount() - 1);
             }
+        } else if (widgetFrame != null) {
+            widgetFrame.setVisibility(View.GONE);
         }
         return view;
     }
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
index 553680f..7c05bab 100644
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
@@ -67,6 +67,7 @@
 import com.android.settings.users.UserDialogs;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -645,12 +646,12 @@
     private EnforcedAdmin getAdminEnforcingCantRemoveProfile() {
         // Removing a managed profile is disallowed if DISALLOW_REMOVE_MANAGED_PROFILE
         // is set in the parent rather than the user itself.
-        return RestrictedLockUtils.checkIfRestrictionEnforced(this,
+        return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(this,
                 UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, getParentUserId());
     }
 
     private boolean hasBaseCantRemoveProfileRestriction() {
-        return RestrictedLockUtils.hasBaseUserRestriction(this,
+        return RestrictedLockUtilsInternal.hasBaseUserRestriction(this,
                 UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, getParentUserId());
     }
 
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index cd04b22..c718dde 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -28,7 +28,7 @@
 import com.android.settings.Utils;
 import com.android.settings.biometrics.BiometricEnrollIntroduction;
 import com.android.settings.password.ChooseLockSettingsHelper;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.setupwizardlib.span.LinkSpan;
 
 public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
@@ -45,7 +45,7 @@
 
     @Override
     protected boolean isDisabledByAdmin() {
-        return RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+        return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                 this, DevicePolicyManager.KEYGUARD_DISABLE_FACE, mUserId) != null;
     }
 
diff --git a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
index 9a14660..cd27dbb 100644
--- a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
@@ -46,7 +46,7 @@
 
     @Override
     protected boolean hasEnrolledBiometrics() {
-        return mFaceManager.hasEnrolledFaces(mUserId);
+        return mFaceManager.hasEnrolledTemplates(mUserId);
     }
 
     @Override
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 41bf86f..241545d 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -31,7 +31,7 @@
 import com.android.settings.biometrics.BiometricEnrollIntroduction;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settingslib.HelpUtils;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.setupwizardlib.span.LinkSpan;
 
 public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
@@ -48,7 +48,7 @@
 
     @Override
     protected boolean isDisabledByAdmin() {
-        return RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+        return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                 this, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId) != null;
     }
 
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index b7c5506..c3bd043 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -58,6 +58,7 @@
 import com.android.settingslib.HelpUtils;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.TwoTargetPreference;
 import com.android.settingslib.widget.FooterPreference;
 
@@ -319,7 +320,7 @@
             }
 
             final FooterPreference pref = mFooterPreferenceMixin.createFooterPreference();
-            final EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+            final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                     activity, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId);
             final AnnotationSpan.LinkInfo adminLinkInfo = new AnnotationSpan.LinkInfo(
                     ANNOTATION_ADMIN_DETAILS, (view) -> {
diff --git a/src/com/android/settings/bluetooth/RestrictionUtils.java b/src/com/android/settings/bluetooth/RestrictionUtils.java
index 9c0c481..21b00cd 100644
--- a/src/com/android/settings/bluetooth/RestrictionUtils.java
+++ b/src/com/android/settings/bluetooth/RestrictionUtils.java
@@ -19,8 +19,8 @@
 import android.content.Context;
 import android.os.UserHandle;
 
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 /**
  * A utility class to aid testing.
@@ -36,7 +36,7 @@
      * API.
      */
     public EnforcedAdmin checkIfRestrictionEnforced(Context context, String restriction) {
-        return RestrictedLockUtils.checkIfRestrictionEnforced(
+        return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 context, restriction, UserHandle.myUserId());
     }
 
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsFragment.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsFragment.java
index 4b717e0..936a4c0 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsFragment.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsFragment.java
@@ -17,7 +17,6 @@
 package com.android.settings.connecteddevice.usb;
 
 import android.content.Context;
-import android.os.Bundle;
 import android.provider.SearchIndexableResource;
 
 import androidx.annotation.VisibleForTesting;
@@ -71,15 +70,6 @@
     }
 
     @Override
-    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
-        super.onCreatePreferences(savedInstanceState, rootKey);
-    }
-
-    public boolean isConnected() {
-        return mUsbReceiver.isConnected();
-    }
-
-    @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         mUsbBackend = new UsbBackend(context);
         mControllers = createControllerList(context, mUsbBackend, this);
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index 08b4e82..0fe37e9 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -20,10 +20,10 @@
  * This class keeps track of all feature flags in Settings.
  */
 public class FeatureFlags {
-    public static final String BATTERY_DISPLAY_APP_LIST = "settings_battery_display_app_list";
     public static final String BLUETOOTH_WHILE_DRIVING = "settings_bluetooth_while_driving";
     public static final String AUDIO_SWITCHER_SETTINGS = "settings_audio_switcher";
     public static final String DYNAMIC_HOMEPAGE = "settings_dynamic_homepage";
     public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
     public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
+    public static final String DATA_USAGE_V2 = "settings_data_usage_v2";
 }
diff --git a/src/com/android/settings/dashboard/RestrictedDashboardFragment.java b/src/com/android/settings/dashboard/RestrictedDashboardFragment.java
index ab4127a..ca30247 100644
--- a/src/com/android/settings/dashboard/RestrictedDashboardFragment.java
+++ b/src/com/android/settings/dashboard/RestrictedDashboardFragment.java
@@ -36,7 +36,7 @@
 import com.android.settings.R;
 import com.android.settings.RestrictedSettingsFragment;
 import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 /**
  * Base class for settings screens that should be pin protected when in restricted mode or
@@ -213,7 +213,7 @@
     }
 
     public EnforcedAdmin getRestrictionEnforcedAdmin() {
-        mEnforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(),
+        mEnforcedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(getActivity(),
                 mRestrictionKey, UserHandle.myUserId());
         if (mEnforcedAdmin != null && mEnforcedAdmin.userId == UserHandle.USER_NULL) {
             mEnforcedAdmin.userId = UserHandle.myUserId();
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index ff89a11..fcb6b72 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -40,6 +40,7 @@
 import androidx.loader.app.LoaderManager;
 import androidx.loader.content.Loader;
 import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
 import androidx.preference.PreferenceCategory;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -47,15 +48,15 @@
 import com.android.settings.applications.AppInfoBase;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.AppItem;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.net.ChartData;
 import com.android.settingslib.net.ChartDataLoaderCompat;
 import com.android.settingslib.net.UidDetail;
 import com.android.settingslib.net.UidDetailProvider;
 
-public class AppDataUsage extends DataUsageBase implements Preference.OnPreferenceChangeListener,
+public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceChangeListener,
         DataSaverBackend.Listener {
 
     private static final String TAG = "AppDataUsage";
@@ -137,7 +138,6 @@
                 addUid(mAppItem.uids.keyAt(i));
             }
         }
-        addPreferencesFromResource(R.xml.app_data_usage);
 
         mTotalUsage = findPreference(KEY_TOTAL_USAGE);
         mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
@@ -258,13 +258,23 @@
         return super.onPreferenceTreeClick(preference);
     }
 
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.app_data_usage;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
     @VisibleForTesting
     void updatePrefs() {
         updatePrefs(getAppRestrictBackground(), getUnrestrictData());
     }
 
     private void updatePrefs(boolean restrictBackground, boolean unrestrictData) {
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfMeteredDataRestricted(
+        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted(
                 getContext(), mPackageName, UserHandle.getUserId(mAppItem.key));
         if (mRestrictBackground != null) {
             mRestrictBackground.setChecked(!restrictBackground);
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index de71572..2d96fe9 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -52,7 +52,7 @@
 import java.util.List;
 
 @SearchIndexable
-public class BillingCycleSettings extends DataUsageBase implements
+public class BillingCycleSettings extends DataUsageBaseFragment implements
         Preference.OnPreferenceChangeListener, DataUsageEditController {
 
     private static final String TAG = "BillingCycleSettings";
@@ -105,7 +105,6 @@
         Bundle args = getArguments();
         mNetworkTemplate = args.getParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE);
 
-        addPreferencesFromResource(R.xml.billing_cycle);
         mBillingCycle = findPreference(KEY_BILLING_CYCLE);
         mEnableDataWarning = (SwitchPreference) findPreference(KEY_SET_DATA_WARNING);
         mEnableDataWarning.setOnPreferenceChangeListener(this);
@@ -191,6 +190,16 @@
         return MetricsEvent.BILLING_CYCLE;
     }
 
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.billing_cycle;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
     @VisibleForTesting
     void setPolicyLimitBytes(long limitBytes) {
         if (LOGD) Log.d(TAG, "setPolicyLimitBytes()");
diff --git a/src/com/android/settings/datausage/DataUsageBase.java b/src/com/android/settings/datausage/DataUsageBase.java
deleted file mode 100644
index c5df0bb..0000000
--- a/src/com/android/settings/datausage/DataUsageBase.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2016 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.settings.datausage;
-
-import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.NetworkPolicy;
-import android.net.NetworkPolicyManager;
-import android.os.Bundle;
-import android.os.INetworkManagementService;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserManager;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settingslib.NetworkPolicyEditor;
-
-/**
- * @deprecated please use {@link DataUsageBaseFragment} instead.
- */
-@Deprecated
-public abstract class DataUsageBase extends SettingsPreferenceFragment {
-    private static final String TAG = "DataUsageBase";
-    private static final String ETHERNET = "ethernet";
-
-    protected final TemplatePreference.NetworkServices services =
-            new TemplatePreference.NetworkServices();
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        final Context context = getActivity();
-
-        services.mNetworkService = INetworkManagementService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
-        services.mStatsService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-        services.mPolicyManager = NetworkPolicyManager.from(context);
-
-        services.mPolicyEditor = new NetworkPolicyEditor(services.mPolicyManager);
-
-        services.mTelephonyManager = TelephonyManager.from(context);
-        services.mSubscriptionManager = SubscriptionManager.from(context);
-        services.mUserManager = UserManager.get(context);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        services.mPolicyEditor.read();
-    }
-
-    protected boolean isAdmin() {
-        return services.mUserManager.isAdminUser();
-    }
-
-    protected boolean isMobileDataAvailable(int subId) {
-        return services.mSubscriptionManager.getActiveSubscriptionInfo(subId) != null;
-    }
-
-    protected boolean isNetworkPolicyModifiable(NetworkPolicy policy, int subId) {
-        return policy != null && isBandwidthControlEnabled() && services.mUserManager.isAdminUser()
-                && isDataEnabled(subId);
-    }
-
-    private boolean isDataEnabled(int subId) {
-        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            return true;
-        }
-        return services.mTelephonyManager.getDataEnabled(subId);
-    }
-
-    protected boolean isBandwidthControlEnabled() {
-        try {
-            return services.mNetworkService.isBandwidthControlEnabled();
-        } catch (RemoteException e) {
-            Log.w(TAG, "problem talking with INetworkManagementService: ", e);
-            return false;
-        }
-    }
-}
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 755eee3..057cdd7 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.java
@@ -75,13 +75,18 @@
 /**
  * Panel showing data usage history across various networks, including options
  * to inspect based on usage cycle and control through {@link NetworkPolicy}.
+
+ * Deprecated in favor of {@link DataUsageListV2}
+ *
+ * @deprecated
  */
-public class DataUsageList extends DataUsageBase {
+@Deprecated
+public class DataUsageList extends DataUsageBaseFragment {
 
     public static final String EXTRA_SUB_ID = "sub_id";
     public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
 
-    private static final String TAG = "DataUsage";
+    private static final String TAG = "DataUsageList";
     private static final boolean LOGD = false;
 
     private static final String KEY_USAGE_AMOUNT = "usage_amount";
@@ -140,7 +145,6 @@
 
         mUidDetailProvider = new UidDetailProvider(context);
 
-        addPreferencesFromResource(R.xml.data_usage_list);
         mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
         mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
         mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
@@ -235,6 +239,16 @@
         super.onDestroy();
     }
 
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.data_usage_list;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
     void processArgument() {
         final Bundle args = getArguments();
         if (args != null) {
diff --git a/src/com/android/settings/datausage/DataUsageListV2.java b/src/com/android/settings/datausage/DataUsageListV2.java
new file mode 100644
index 0000000..fd20e23
--- /dev/null
+++ b/src/com/android/settings/datausage/DataUsageListV2.java
@@ -0,0 +1,615 @@
+/*
+ * 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.settings.datausage;
+
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.TrafficStats.UID_REMOVED;
+import static android.net.TrafficStats.UID_TETHERING;
+import static android.telephony.TelephonyManager.SIM_STATE_READY;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.graphics.Color;
+import android.net.ConnectivityManager;
+import android.net.INetworkStatsSession;
+import android.net.NetworkPolicy;
+import android.net.NetworkStats;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.net.TrafficStats;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.format.DateUtils;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ImageView;
+import android.widget.Spinner;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.loader.app.LoaderManager.LoaderCallbacks;
+import androidx.loader.content.Loader;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceGroup;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
+import com.android.settings.widget.LoadingViewController;
+import com.android.settingslib.AppItem;
+import com.android.settingslib.net.ChartData;
+import com.android.settingslib.net.ChartDataLoaderCompat;
+import com.android.settingslib.net.SummaryForAllUidLoaderCompat;
+import com.android.settingslib.net.UidDetailProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Panel showing data usage history across various networks, including options
+ * to inspect based on usage cycle and control through {@link NetworkPolicy}.
+ */
+public class DataUsageListV2 extends DataUsageBaseFragment {
+
+    public static final String EXTRA_SUB_ID = "sub_id";
+    public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+
+    private static final String TAG = "DataUsageListV2";
+    private static final boolean LOGD = false;
+
+    private static final String KEY_USAGE_AMOUNT = "usage_amount";
+    private static final String KEY_CHART_DATA = "chart_data";
+    private static final String KEY_APPS_GROUP = "apps_group";
+
+    private static final int LOADER_CHART_DATA = 2;
+    private static final int LOADER_SUMMARY = 3;
+
+    private final CellDataPreference.DataStateListener mDataStateListener =
+            new CellDataPreference.DataStateListener() {
+                @Override
+                public void onChange(boolean selfChange) {
+                    updatePolicy();
+                }
+            };
+
+    private INetworkStatsSession mStatsSession;
+    private ChartDataUsagePreference mChart;
+
+    @VisibleForTesting
+    NetworkTemplate mTemplate;
+    @VisibleForTesting
+    int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    private ChartData mChartData;
+
+    private LoadingViewController mLoadingViewController;
+    private UidDetailProvider mUidDetailProvider;
+    private CycleAdapter mCycleAdapter;
+    private Spinner mCycleSpinner;
+    private Preference mUsageAmount;
+    private PreferenceGroup mApps;
+    private View mHeader;
+
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.DATA_USAGE_LIST;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final Context context = getActivity();
+
+        if (!isBandwidthControlEnabled()) {
+            Log.w(TAG, "No bandwidth control; leaving");
+            getActivity().finish();
+        }
+
+        try {
+            mStatsSession = services.mStatsService.openSession();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+
+        mUidDetailProvider = new UidDetailProvider(context);
+
+        mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
+        mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
+        mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
+        processArgument();
+    }
+
+    @Override
+    public void onViewCreated(View v, Bundle savedInstanceState) {
+        super.onViewCreated(v, savedInstanceState);
+
+        mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner);
+        mHeader.findViewById(R.id.filter_settings).setOnClickListener(btn -> {
+            final Bundle args = new Bundle();
+            args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mTemplate);
+            new SubSettingLauncher(getContext())
+                    .setDestination(BillingCycleSettings.class.getName())
+                    .setTitleRes(R.string.billing_cycle)
+                    .setSourceMetricsCategory(getMetricsCategory())
+                    .setArguments(args)
+                    .launch();
+        });
+        mCycleSpinner = mHeader.findViewById(R.id.filter_spinner);
+        mCycleAdapter = new CycleAdapter(mCycleSpinner.getContext(), new SpinnerInterface() {
+            @Override
+            public void setAdapter(CycleAdapter cycleAdapter) {
+                mCycleSpinner.setAdapter(cycleAdapter);
+            }
+
+            @Override
+            public void setOnItemSelectedListener(OnItemSelectedListener listener) {
+                mCycleSpinner.setOnItemSelectedListener(listener);
+            }
+
+            @Override
+            public Object getSelectedItem() {
+                return mCycleSpinner.getSelectedItem();
+            }
+
+            @Override
+            public void setSelection(int position) {
+                mCycleSpinner.setSelection(position);
+            }
+        }, mCycleListener, true);
+
+        mLoadingViewController = new LoadingViewController(
+                getView().findViewById(R.id.loading_container), getListView());
+        mLoadingViewController.showLoadingViewDelayed();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mDataStateListener.setListener(true, mSubId, getContext());
+        updateBody();
+
+        // kick off background task to update stats
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                try {
+                    // wait a few seconds before kicking off
+                    Thread.sleep(2 * DateUtils.SECOND_IN_MILLIS);
+                    services.mStatsService.forceUpdate();
+                } catch (InterruptedException e) {
+                } catch (RemoteException e) {
+                }
+                return null;
+            }
+
+            @Override
+            protected void onPostExecute(Void result) {
+                if (isAdded()) {
+                    updateBody();
+                }
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mDataStateListener.setListener(false, mSubId, getContext());
+    }
+
+    @Override
+    public void onDestroy() {
+        mUidDetailProvider.clearCache();
+        mUidDetailProvider = null;
+
+        TrafficStats.closeQuietly(mStatsSession);
+
+        super.onDestroy();
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.data_usage_list;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    void processArgument() {
+        final Bundle args = getArguments();
+        if (args != null) {
+            mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+            mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
+        }
+        if (mTemplate == null && mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            final Intent intent = getIntent();
+            mSubId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
+                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+            mTemplate = intent.getParcelableExtra(Settings.EXTRA_NETWORK_TEMPLATE);
+        }
+    }
+
+    /**
+     * Update body content based on current tab. Loads
+     * {@link NetworkStatsHistory} and {@link NetworkPolicy} from system, and
+     * binds them to visible controls.
+     */
+    private void updateBody() {
+        if (!isAdded()) return;
+
+        final Context context = getActivity();
+
+        // kick off loader for network history
+        // TODO: consider chaining two loaders together instead of reloading
+        // network history when showing app detail.
+        getLoaderManager().restartLoader(LOADER_CHART_DATA,
+                ChartDataLoaderCompat.buildArgs(mTemplate, null), mChartDataCallbacks);
+
+        // detail mode can change visible menus, invalidate
+        getActivity().invalidateOptionsMenu();
+
+        int seriesColor = context.getColor(R.color.sim_noitification);
+        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            final SubscriptionInfo sir = services.mSubscriptionManager
+                    .getActiveSubscriptionInfo(mSubId);
+
+            if (sir != null) {
+                seriesColor = sir.getIconTint();
+            }
+        }
+
+        final int secondaryColor = Color.argb(127, Color.red(seriesColor), Color.green(seriesColor),
+                Color.blue(seriesColor));
+        mChart.setColors(seriesColor, secondaryColor);
+    }
+
+    /**
+     * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
+     * current {@link #mTemplate}.
+     */
+    private void updatePolicy() {
+        final NetworkPolicy policy = services.mPolicyEditor.getPolicy(mTemplate);
+        final View configureButton = mHeader.findViewById(R.id.filter_settings);
+        //SUB SELECT
+        if (isNetworkPolicyModifiable(policy, mSubId) && isMobileDataAvailable(mSubId)) {
+            mChart.setNetworkPolicy(policy);
+            configureButton.setVisibility(View.VISIBLE);
+            ((ImageView) configureButton).setColorFilter(android.R.color.white);
+        } else {
+            // controls are disabled; don't bind warning/limit sweeps
+            mChart.setNetworkPolicy(null);
+            configureButton.setVisibility(View.GONE);
+        }
+
+        // generate cycle list based on policy and available history
+        if (mCycleAdapter.updateCycleList(policy, mChartData)) {
+            updateDetailData();
+        }
+    }
+
+    /**
+     * Update details based on {@link #mChart} inspection range depending on
+     * current mode. Updates {@link #mAdapter} with sorted list
+     * of applications data usage.
+     */
+    private void updateDetailData() {
+        if (LOGD) Log.d(TAG, "updateDetailData()");
+
+        final long start = mChart.getInspectStart();
+        final long end = mChart.getInspectEnd();
+        final long now = System.currentTimeMillis();
+
+        final Context context = getActivity();
+
+        NetworkStatsHistory.Entry entry = null;
+        if (mChartData != null) {
+            entry = mChartData.network.getValues(start, end, now, null);
+        }
+
+        // kick off loader for detailed stats
+        getLoaderManager().restartLoader(LOADER_SUMMARY,
+                SummaryForAllUidLoaderCompat.buildArgs(mTemplate, start, end), mSummaryCallbacks);
+
+        final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
+        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(context, totalBytes);
+        mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
+    }
+
+    /**
+     * Bind the given {@link NetworkStats}, or {@code null} to clear list.
+     */
+    public void bindStats(NetworkStats stats, int[] restrictedUids) {
+        ArrayList<AppItem> items = new ArrayList<>();
+        long largest = 0;
+
+        final int currentUserId = ActivityManager.getCurrentUser();
+        UserManager userManager = UserManager.get(getContext());
+        final List<UserHandle> profiles = userManager.getUserProfiles();
+        final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
+
+        NetworkStats.Entry entry = null;
+        final int size = stats != null ? stats.size() : 0;
+        for (int i = 0; i < size; i++) {
+            entry = stats.getValues(i, entry);
+
+            // Decide how to collapse items together
+            final int uid = entry.uid;
+
+            final int collapseKey;
+            final int category;
+            final int userId = UserHandle.getUserId(uid);
+            if (UserHandle.isApp(uid)) {
+                if (profiles.contains(new UserHandle(userId))) {
+                    if (userId != currentUserId) {
+                        // Add to a managed user item.
+                        final int managedKey = UidDetailProvider.buildKeyForUser(userId);
+                        largest = accumulate(managedKey, knownItems, entry, AppItem.CATEGORY_USER,
+                                items, largest);
+                    }
+                    // Add to app item.
+                    collapseKey = uid;
+                    category = AppItem.CATEGORY_APP;
+                } else {
+                    // If it is a removed user add it to the removed users' key
+                    final UserInfo info = userManager.getUserInfo(userId);
+                    if (info == null) {
+                        collapseKey = UID_REMOVED;
+                        category = AppItem.CATEGORY_APP;
+                    } else {
+                        // Add to other user item.
+                        collapseKey = UidDetailProvider.buildKeyForUser(userId);
+                        category = AppItem.CATEGORY_USER;
+                    }
+                }
+            } else if (uid == UID_REMOVED || uid == UID_TETHERING) {
+                collapseKey = uid;
+                category = AppItem.CATEGORY_APP;
+            } else {
+                collapseKey = android.os.Process.SYSTEM_UID;
+                category = AppItem.CATEGORY_APP;
+            }
+            largest = accumulate(collapseKey, knownItems, entry, category, items, largest);
+        }
+
+        final int restrictedUidsMax = restrictedUids.length;
+        for (int i = 0; i < restrictedUidsMax; ++i) {
+            final int uid = restrictedUids[i];
+            // Only splice in restricted state for current user or managed users
+            if (!profiles.contains(new UserHandle(UserHandle.getUserId(uid)))) {
+                continue;
+            }
+
+            AppItem item = knownItems.get(uid);
+            if (item == null) {
+                item = new AppItem(uid);
+                item.total = -1;
+                items.add(item);
+                knownItems.put(item.key, item);
+            }
+            item.restricted = true;
+        }
+
+        Collections.sort(items);
+        mApps.removeAll();
+        for (int i = 0; i < items.size(); i++) {
+            final int percentTotal = largest != 0 ? (int) (items.get(i).total * 100 / largest) : 0;
+            AppDataUsagePreference preference = new AppDataUsagePreference(getContext(),
+                    items.get(i), percentTotal, mUidDetailProvider);
+            preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+                @Override
+                public boolean onPreferenceClick(Preference preference) {
+                    AppDataUsagePreference pref = (AppDataUsagePreference) preference;
+                    AppItem item = pref.getItem();
+                    startAppDataUsage(item);
+                    return true;
+                }
+            });
+            mApps.addPreference(preference);
+        }
+    }
+
+    private void startAppDataUsage(AppItem item) {
+        final Bundle args = new Bundle();
+        args.putParcelable(AppDataUsage.ARG_APP_ITEM, item);
+        args.putParcelable(AppDataUsage.ARG_NETWORK_TEMPLATE, mTemplate);
+
+        new SubSettingLauncher(getContext())
+                .setDestination(AppDataUsage.class.getName())
+                .setTitleRes(R.string.app_data_usage)
+                .setArguments(args)
+                .setSourceMetricsCategory(getMetricsCategory())
+                .launch();
+    }
+
+    /**
+     * Accumulate data usage of a network stats entry for the item mapped by the collapse key.
+     * Creates the item if needed.
+     *
+     * @param collapseKey  the collapse key used to map the item.
+     * @param knownItems   collection of known (already existing) items.
+     * @param entry        the network stats entry to extract data usage from.
+     * @param itemCategory the item is categorized on the list view by this category. Must be
+     */
+    private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
+            NetworkStats.Entry entry, int itemCategory, ArrayList<AppItem> items, long largest) {
+        final int uid = entry.uid;
+        AppItem item = knownItems.get(collapseKey);
+        if (item == null) {
+            item = new AppItem(collapseKey);
+            item.category = itemCategory;
+            items.add(item);
+            knownItems.put(item.key, item);
+        }
+        item.addUid(uid);
+        item.total += entry.rxBytes + entry.txBytes;
+        return Math.max(largest, item.total);
+    }
+
+    /**
+     * Test if device has a mobile data radio with SIM in ready state.
+     */
+    public static boolean hasReadyMobileRadio(Context context) {
+        if (DataUsageUtils.TEST_RADIOS) {
+            return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains("mobile");
+        }
+
+        final ConnectivityManager conn = ConnectivityManager.from(context);
+        final TelephonyManager tele = TelephonyManager.from(context);
+
+        final List<SubscriptionInfo> subInfoList =
+                SubscriptionManager.from(context).getActiveSubscriptionInfoList();
+        // No activated Subscriptions
+        if (subInfoList == null) {
+            if (LOGD) Log.d(TAG, "hasReadyMobileRadio: subInfoList=null");
+            return false;
+        }
+        // require both supported network and ready SIM
+        boolean isReady = true;
+        for (SubscriptionInfo subInfo : subInfoList) {
+            isReady = isReady & tele.getSimState(subInfo.getSimSlotIndex()) == SIM_STATE_READY;
+            if (LOGD) Log.d(TAG, "hasReadyMobileRadio: subInfo=" + subInfo);
+        }
+        boolean retVal = conn.isNetworkSupported(TYPE_MOBILE) && isReady;
+        if (LOGD) {
+            Log.d(TAG, "hasReadyMobileRadio:"
+                    + " conn.isNetworkSupported(TYPE_MOBILE)="
+                    + conn.isNetworkSupported(TYPE_MOBILE)
+                    + " isReady=" + isReady);
+        }
+        return retVal;
+    }
+
+    /*
+     * TODO: consider adding to TelephonyManager or SubscriptionManager.
+     */
+    public static boolean hasReadyMobileRadio(Context context, int subId) {
+        if (DataUsageUtils.TEST_RADIOS) {
+            return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains("mobile");
+        }
+
+        final ConnectivityManager conn = ConnectivityManager.from(context);
+        final TelephonyManager tele = TelephonyManager.from(context);
+        final int slotId = SubscriptionManager.getSlotIndex(subId);
+        final boolean isReady = tele.getSimState(slotId) == SIM_STATE_READY;
+
+        boolean retVal = conn.isNetworkSupported(TYPE_MOBILE) && isReady;
+        if (LOGD) {
+            Log.d(TAG, "hasReadyMobileRadio: subId=" + subId
+                    + " conn.isNetworkSupported(TYPE_MOBILE)="
+                    + conn.isNetworkSupported(TYPE_MOBILE)
+                    + " isReady=" + isReady);
+        }
+        return retVal;
+    }
+
+    private OnItemSelectedListener mCycleListener = new OnItemSelectedListener() {
+        @Override
+        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+            final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem)
+                    mCycleSpinner.getSelectedItem();
+
+            if (LOGD) {
+                Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
+                        + cycle.end + "]");
+            }
+
+            // update chart to show selected cycle, and update detail data
+            // to match updated sweep bounds.
+            mChart.setVisibleRange(cycle.start, cycle.end);
+
+            updateDetailData();
+        }
+
+        @Override
+        public void onNothingSelected(AdapterView<?> parent) {
+            // ignored
+        }
+    };
+
+    private final LoaderCallbacks<ChartData> mChartDataCallbacks = new LoaderCallbacks<
+            ChartData>() {
+        @Override
+        public Loader<ChartData> onCreateLoader(int id, Bundle args) {
+            return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
+        }
+
+        @Override
+        public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
+            mLoadingViewController.showContent(false /* animate */);
+            mChartData = data;
+            mChart.setNetworkStats(mChartData.network);
+
+            // calculate policy cycles based on available data
+            updatePolicy();
+        }
+
+        @Override
+        public void onLoaderReset(Loader<ChartData> loader) {
+            mChartData = null;
+            mChart.setNetworkStats(null);
+        }
+    };
+
+    private final LoaderCallbacks<NetworkStats> mSummaryCallbacks = new LoaderCallbacks<
+            NetworkStats>() {
+        @Override
+        public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
+            return new SummaryForAllUidLoaderCompat(getActivity(), mStatsSession, args);
+        }
+
+        @Override
+        public void onLoadFinished(Loader<NetworkStats> loader, NetworkStats data) {
+            final int[] restrictedUids = services.mPolicyManager.getUidsWithPolicy(
+                    POLICY_REJECT_METERED_BACKGROUND);
+            bindStats(data, restrictedUids);
+            updateEmptyVisible();
+        }
+
+        @Override
+        public void onLoaderReset(Loader<NetworkStats> loader) {
+            bindStats(null, new int[0]);
+            updateEmptyVisible();
+        }
+
+        private void updateEmptyVisible() {
+            if ((mApps.getPreferenceCount() != 0) !=
+                    (getPreferenceScreen().getPreferenceCount() != 0)) {
+                if (mApps.getPreferenceCount() != 0) {
+                    getPreferenceScreen().addPreference(mUsageAmount);
+                    getPreferenceScreen().addPreference(mApps);
+                } else {
+                    getPreferenceScreen().removeAll();
+                }
+            }
+        }
+    };
+}
diff --git a/src/com/android/settings/datausage/DataUsagePreference.java b/src/com/android/settings/datausage/DataUsagePreference.java
index fd5c44e..cdec619 100644
--- a/src/com/android/settings/datausage/DataUsagePreference.java
+++ b/src/com/android/settings/datausage/DataUsagePreference.java
@@ -20,6 +20,7 @@
 import android.net.NetworkTemplate;
 import android.os.Bundle;
 import android.util.AttributeSet;
+import android.util.FeatureFlagUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.core.content.res.TypedArrayUtils;
@@ -27,6 +28,7 @@
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
+import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settingslib.net.DataUsageController;
 
@@ -75,12 +77,22 @@
     @Override
     public Intent getIntent() {
         final Bundle args = new Bundle();
-        args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
-        args.putInt(DataUsageList.EXTRA_SUB_ID, mSubId);
-        final SubSettingLauncher launcher = new SubSettingLauncher(getContext())
+        final SubSettingLauncher launcher;
+        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
+            args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mTemplate);
+            args.putInt(DataUsageListV2.EXTRA_SUB_ID, mSubId);
+            launcher = new SubSettingLauncher(getContext())
+                .setArguments(args)
+                .setDestination(DataUsageListV2.class.getName())
+                .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
+        } else {
+            args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
+            args.putInt(DataUsageList.EXTRA_SUB_ID, mSubId);
+            launcher = new SubSettingLauncher(getContext())
                 .setArguments(args)
                 .setDestination(DataUsageList.class.getName())
                 .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
+        }
         if (mTemplate.isMatchRuleMobile()) {
             launcher.setTitleRes(R.string.app_cellular_data_usage);
         } else {
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java b/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
index 2fefe01..824c102 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
@@ -13,7 +13,7 @@
  */
 package com.android.settings.datausage;
 
-import static com.android.settingslib.RestrictedLockUtils.checkIfMeteredDataRestricted;
+import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfMeteredDataRestricted;
 
 import android.content.Context;
 import android.os.UserHandle;
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java b/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
index e47c7f8..efc20f0 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
@@ -13,7 +13,7 @@
  */
 package com.android.settings.datausage;
 
-import static com.android.settingslib.RestrictedLockUtils.checkIfMeteredDataRestricted;
+import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfMeteredDataRestricted;
 
 import android.app.Application;
 import android.content.Context;
diff --git a/src/com/android/settings/datetime/AutoTimePreferenceController.java b/src/com/android/settings/datetime/AutoTimePreferenceController.java
index 3916ef2..bf6ecb4 100644
--- a/src/com/android/settings/datetime/AutoTimePreferenceController.java
+++ b/src/com/android/settings/datetime/AutoTimePreferenceController.java
@@ -23,6 +23,7 @@
 
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 
@@ -74,6 +75,6 @@
     }
 
     private RestrictedLockUtils.EnforcedAdmin getEnforcedAdminProperty() {
-        return RestrictedLockUtils.checkIfAutoTimeRequired(mContext);
+        return RestrictedLockUtilsInternal.checkIfAutoTimeRequired(mContext);
     }
 }
diff --git a/src/com/android/settings/development/StayAwakePreferenceController.java b/src/com/android/settings/development/StayAwakePreferenceController.java
index 7d67b9e..4091537 100644
--- a/src/com/android/settings/development/StayAwakePreferenceController.java
+++ b/src/com/android/settings/development/StayAwakePreferenceController.java
@@ -30,6 +30,7 @@
 
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -130,7 +131,7 @@
         // will lock...  in this case we can't allow the user to turn
         // on "stay awake when plugged in" because that would defeat the
         // restriction.
-        return RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext);
+        return RestrictedLockUtilsInternal.checkIfMaximumTimeToLockIsSet(mContext);
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/development/VerifyAppsOverUsbPreferenceController.java b/src/com/android/settings/development/VerifyAppsOverUsbPreferenceController.java
index 29653a0..20b8f1f 100644
--- a/src/com/android/settings/development/VerifyAppsOverUsbPreferenceController.java
+++ b/src/com/android/settings/development/VerifyAppsOverUsbPreferenceController.java
@@ -28,8 +28,8 @@
 import androidx.preference.Preference;
 
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
 
@@ -57,7 +57,8 @@
     class RestrictedLockUtilsDelegate {
         public EnforcedAdmin checkIfRestrictionEnforced(
                 Context context, String userRestriction, int userId) {
-            return RestrictedLockUtils.checkIfRestrictionEnforced(context, userRestriction, userId);
+            return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context, userRestriction,
+                    userId);
         }
     }
 
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index f6ef632..6256e23 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -40,6 +40,7 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -104,9 +105,9 @@
 
     @Override
     public void onResume() {
-        mDebuggingFeaturesDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(
+        mDebuggingFeaturesDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 mContext, UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.myUserId());
-        mDebuggingFeaturesDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
+        mDebuggingFeaturesDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction(
                 mContext, UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.myUserId());
         mDevHitCountdown = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)
                 ? -1 : TAPS_TO_BE_A_DEVELOPER;
diff --git a/src/com/android/settings/deviceinfo/DeviceNamePreferenceController.java b/src/com/android/settings/deviceinfo/DeviceNamePreferenceController.java
index 2720979..0d7b1d3 100644
--- a/src/com/android/settings/deviceinfo/DeviceNamePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/DeviceNamePreferenceController.java
@@ -39,10 +39,10 @@
 
 public class DeviceNamePreferenceController extends BasePreferenceController
         implements ValidatedEditTextPreference.Validator,
-                Preference.OnPreferenceChangeListener,
-                LifecycleObserver,
-                OnSaveInstanceState,
-                OnCreate {
+        Preference.OnPreferenceChangeListener,
+        LifecycleObserver,
+        OnSaveInstanceState,
+        OnCreate {
     private static final String PREF_KEY = "device_name";
     public static final int DEVICE_NAME_SET_WARNING_ID = 1;
     private static final String KEY_PENDING_DEVICE_NAME = "key_pending_device_name";
@@ -116,9 +116,11 @@
         return mWifiDeviceNameTextValidator.isTextValid(deviceName);
     }
 
-    public void confirmDeviceName() {
-        if (mPendingDeviceName != null) {
+    public void updateDeviceName(boolean update) {
+        if (update && mPendingDeviceName != null) {
             setDeviceName(mPendingDeviceName);
+        } else {
+            mPreference.setText(getSummary().toString());
         }
     }
 
@@ -153,7 +155,8 @@
      * For more information, see {@link com.android.settings.bluetooth.BluetoothNameDialogFragment}.
      */
     private static final String getFilteredBluetoothString(final String deviceName) {
-        CharSequence filteredSequence = new BluetoothLengthDeviceNameFilter().filter(deviceName, 0, deviceName.length(),
+        CharSequence filteredSequence = new BluetoothLengthDeviceNameFilter().filter(deviceName, 0,
+                deviceName.length(),
                 new SpannedString(""),
                 0, 0);
         // null -> use the original
diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
index 415af58..58188f1 100644
--- a/src/com/android/settings/deviceinfo/StorageSettings.java
+++ b/src/com/android/settings/deviceinfo/StorageSettings.java
@@ -56,6 +56,7 @@
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.deviceinfo.PrivateStorageInfo;
 import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
 import com.android.settingslib.search.SearchIndexable;
@@ -460,10 +461,11 @@
                          * @return {@code true} iff a intent was shown.
                          */
                         private boolean wasAdminSupportIntentShown(@NonNull String restriction) {
-                            EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
-                                    getActivity(), restriction, UserHandle.myUserId());
+                            EnforcedAdmin admin = RestrictedLockUtilsInternal
+                                    .checkIfRestrictionEnforced(getActivity(), restriction,
+                                            UserHandle.myUserId());
                             boolean hasBaseUserRestriction =
-                                    RestrictedLockUtils.hasBaseUserRestriction(
+                                    RestrictedLockUtilsInternal.hasBaseUserRestriction(
                                             getActivity(), restriction, UserHandle.myUserId());
                             if (admin != null && !hasBaseUserRestriction) {
                                 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(),
diff --git a/src/com/android/settings/deviceinfo/aboutphone/DeviceNameWarningDialog.java b/src/com/android/settings/deviceinfo/aboutphone/DeviceNameWarningDialog.java
index 5633c11..a6b1dec 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/DeviceNameWarningDialog.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/DeviceNameWarningDialog.java
@@ -66,7 +66,9 @@
     public void onClick(DialogInterface dialog, int which) {
         final MyDeviceInfoFragment host = (MyDeviceInfoFragment) getTargetFragment();
         if (which == DialogInterface.BUTTON_POSITIVE) {
-            host.onSetDeviceNameConfirm();
+            host.onSetDeviceNameConfirm(true);
+        } else {
+            host.onSetDeviceNameConfirm(false);
         }
     }
 }
diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
index 3de46e01..5503ea9 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
@@ -178,9 +178,9 @@
         DeviceNameWarningDialog.show(this);
     }
 
-    public void onSetDeviceNameConfirm() {
+    public void onSetDeviceNameConfirm(boolean confirm) {
         final DeviceNamePreferenceController controller = use(DeviceNamePreferenceController.class);
-        controller.confirmDeviceName();
+        controller.updateDeviceName(confirm);
     }
 
     private static class SummaryProvider implements SummaryLoader.SummaryProvider {
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogController.java b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogController.java
index 17415cc..8c29f7b 100644
--- a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogController.java
+++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogController.java
@@ -29,6 +29,7 @@
 
 import com.android.settings.R;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 public class FirmwareVersionDialogController implements View.OnClickListener {
 
@@ -105,9 +106,9 @@
 
     @VisibleForTesting
     void initializeAdminPermissions() {
-        mFunDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(
+        mFunDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 mContext, UserManager.DISALLOW_FUN, UserHandle.myUserId());
-        mFunDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
+        mFunDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction(
                 mContext, UserManager.DISALLOW_FUN, UserHandle.myUserId());
     }
 }
diff --git a/src/com/android/settings/display/FontSizePreferenceController.java b/src/com/android/settings/display/FontSizePreferenceController.java
index a55d577..680e378 100644
--- a/src/com/android/settings/display/FontSizePreferenceController.java
+++ b/src/com/android/settings/display/FontSizePreferenceController.java
@@ -18,7 +18,6 @@
 import android.provider.Settings;
 
 import com.android.settings.R;
-import com.android.settings.accessibility.ToggleFontSizePreferenceFragment;
 import com.android.settings.core.BasePreferenceController;
 
 public class FontSizePreferenceController extends BasePreferenceController {
diff --git a/src/com/android/settings/accessibility/FontSizePreferenceFragmentForSetupWizard.java b/src/com/android/settings/display/FontSizePreferenceFragmentForSetupWizard.java
similarity index 92%
rename from src/com/android/settings/accessibility/FontSizePreferenceFragmentForSetupWizard.java
rename to src/com/android/settings/display/FontSizePreferenceFragmentForSetupWizard.java
index 8dfb2b4..703ec9c 100644
--- a/src/com/android/settings/accessibility/FontSizePreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/display/FontSizePreferenceFragmentForSetupWizard.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.accessibility;
+package com.android.settings.display;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
diff --git a/src/com/android/settings/PreviewPagerAdapter.java b/src/com/android/settings/display/PreviewPagerAdapter.java
similarity index 82%
rename from src/com/android/settings/PreviewPagerAdapter.java
rename to src/com/android/settings/display/PreviewPagerAdapter.java
index 8d83cb4..4d5b47a 100644
--- a/src/com/android/settings/PreviewPagerAdapter.java
+++ b/src/com/android/settings/display/PreviewPagerAdapter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.settings;
+package com.android.settings.display;
 
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
@@ -32,6 +32,8 @@
 
 import androidx.viewpager.widget.PagerAdapter;
 
+import com.android.settings.support.actionbar.HelpResourceProvider;
+
 /**
  * A PagerAdapter used by PreviewSeekBarPreferenceFragment that for showing multiple preview screen
  * regarding a single setting and allowing the user to swipe across them.
@@ -76,16 +78,12 @@
                 final Context configContext = context.createConfigurationContext(configurations[j]);
                 configContext.getTheme().setTo(context.getTheme());
 
-                final LayoutInflater configInflater = LayoutInflater.from(configContext);
                 final ViewStub sampleViewStub = new ViewStub(configContext);
                 sampleViewStub.setLayoutResource(previewSampleResIds[i]);
                 final int fi = i, fj = j;
-                sampleViewStub.setOnInflateListener(new OnInflateListener() {
-                    @Override
-                    public void onInflate(ViewStub stub, View inflated) {
-                        inflated.setVisibility(stub.getVisibility());
-                        mViewStubInflated[fi][fj] = true;
-                    }
+                sampleViewStub.setOnInflateListener((stub, inflated) -> {
+                    inflated.setVisibility(stub.getVisibility());
+                    mViewStubInflated[fi][fj] = true;
                 });
 
                 mPreviewFrames[p].addView(sampleViewStub);
@@ -94,7 +92,7 @@
     }
 
     @Override
-    public void destroyItem (ViewGroup container, int position, Object object) {
+    public void destroyItem(ViewGroup container, int position, Object object) {
         container.removeView((View) object);
     }
 
@@ -164,29 +162,29 @@
             if (visibility == View.VISIBLE) {
                 // Fade in animation.
                 view.animate()
-                .alpha(alpha)
-                .setInterpolator(FADE_IN_INTERPOLATOR)
-                .setDuration(CROSS_FADE_DURATION_MS)
-                .setListener(new PreviewFrameAnimatorListener())
-                .withStartAction(new Runnable() {
-                    @Override
-                    public void run() {
-                        view.setVisibility(visibility);
-                    }
-                });
+                        .alpha(alpha)
+                        .setInterpolator(FADE_IN_INTERPOLATOR)
+                        .setDuration(CROSS_FADE_DURATION_MS)
+                        .setListener(new PreviewFrameAnimatorListener())
+                        .withStartAction(new Runnable() {
+                            @Override
+                            public void run() {
+                                view.setVisibility(visibility);
+                            }
+                        });
             } else {
                 // Fade out animation.
                 view.animate()
-                .alpha(alpha)
-                .setInterpolator(FADE_OUT_INTERPOLATOR)
-                .setDuration(CROSS_FADE_DURATION_MS)
-                .setListener(new PreviewFrameAnimatorListener())
-                .withEndAction(new Runnable() {
-                    @Override
-                    public void run() {
-                        view.setVisibility(visibility);
-                    }
-                });
+                        .alpha(alpha)
+                        .setInterpolator(FADE_OUT_INTERPOLATOR)
+                        .setDuration(CROSS_FADE_DURATION_MS)
+                        .setListener(new PreviewFrameAnimatorListener())
+                        .withEndAction(new Runnable() {
+                            @Override
+                            public void run() {
+                                view.setVisibility(visibility);
+                            }
+                        });
             }
         }
     }
diff --git a/src/com/android/settings/PreviewSeekBarPreferenceFragment.java b/src/com/android/settings/display/PreviewSeekBarPreferenceFragment.java
similarity index 79%
rename from src/com/android/settings/PreviewSeekBarPreferenceFragment.java
rename to src/com/android/settings/display/PreviewSeekBarPreferenceFragment.java
index 164648f..bb9e3d7 100644
--- a/src/com/android/settings/PreviewSeekBarPreferenceFragment.java
+++ b/src/com/android/settings/display/PreviewSeekBarPreferenceFragment.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.settings;
+package com.android.settings.display;
 
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.SeekBar;
@@ -31,6 +30,8 @@
 import androidx.viewpager.widget.ViewPager;
 import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
 
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.widget.DotsPageIndicator;
 import com.android.settings.widget.LabeledSeekBar;
 
@@ -48,12 +49,6 @@
     /** Index of the entry corresponding to current value of the settings. */
     protected int mCurrentIndex;
 
-    /** Resource id of the layout for this preference fragment. */
-    protected int mActivityLayoutResId;
-
-    /** Resource id of the layout that defines the contents inside preview screen. */
-    protected int[] mPreviewSampleResIds;
-
     private ViewPager mPreviewPager;
     private PreviewPagerAdapter mPreviewPagerAdapter;
     private DotsPageIndicator mPageIndicator;
@@ -82,12 +77,7 @@
         @Override
         public void onStopTrackingTouch(SeekBar seekBar) {
             if (mPreviewPagerAdapter.isAnimating()) {
-                mPreviewPagerAdapter.setAnimationEndAction(new Runnable() {
-                    @Override
-                    public void run() {
-                        commit();
-                    }
-                });
+                mPreviewPagerAdapter.setAnimationEndAction(() -> commit());
             } else {
                 commit();
             }
@@ -102,39 +92,33 @@
         final ViewGroup listContainer = root.findViewById(android.R.id.list_container);
         listContainer.removeAllViews();
 
-        final View content = inflater.inflate(mActivityLayoutResId, listContainer, false);
+        final View content = inflater.inflate(getActivityLayoutResId(), listContainer, false);
         listContainer.addView(content);
 
-        mLabel = (TextView) content.findViewById(R.id.current_label);
+        mLabel = content.findViewById(R.id.current_label);
 
         // The maximum SeekBar value always needs to be non-zero. If there's
         // only one available value, we'll handle this by disabling the
         // seek bar.
         final int max = Math.max(1, mEntries.length - 1);
 
-        mSeekBar = (LabeledSeekBar) content.findViewById(R.id.seek_bar);
+        mSeekBar = content.findViewById(R.id.seek_bar);
         mSeekBar.setLabels(mEntries);
         mSeekBar.setMax(max);
 
         mSmaller = content.findViewById(R.id.smaller);
-        mSmaller.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                final int progress = mSeekBar.getProgress();
-                if (progress > 0) {
-                    mSeekBar.setProgress(progress - 1, true);
-                }
+        mSmaller.setOnClickListener(v -> {
+            final int progress = mSeekBar.getProgress();
+            if (progress > 0) {
+                mSeekBar.setProgress(progress - 1, true);
             }
         });
 
         mLarger = content.findViewById(R.id.larger);
-        mLarger.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                final int progress = mSeekBar.getProgress();
-                if (progress < mSeekBar.getMax()) {
-                    mSeekBar.setProgress(progress + 1, true);
-                }
+        mLarger.setOnClickListener(v -> {
+            final int progress = mSeekBar.getProgress();
+            if (progress < mSeekBar.getMax()) {
+                mSeekBar.setProgress(progress + 1, true);
             }
         });
 
@@ -152,15 +136,16 @@
             configurations[i] = createConfig(origConfig, i);
         }
 
-        mPreviewPager = (ViewPager) content.findViewById(R.id.preview_pager);
+        final int[] previews = getPreviewSampleResIds();
+        mPreviewPager = content.findViewById(R.id.preview_pager);
         mPreviewPagerAdapter = new PreviewPagerAdapter(context, isLayoutRtl,
-                mPreviewSampleResIds, configurations);
+                previews, configurations);
         mPreviewPager.setAdapter(mPreviewPagerAdapter);
-        mPreviewPager.setCurrentItem(isLayoutRtl ? mPreviewSampleResIds.length - 1 : 0);
+        mPreviewPager.setCurrentItem(isLayoutRtl ? previews.length - 1 : 0);
         mPreviewPager.addOnPageChangeListener(mPreviewPageChangeListener);
 
-        mPageIndicator = (DotsPageIndicator) content.findViewById(R.id.page_indicator);
-        if (mPreviewSampleResIds.length > 1) {
+        mPageIndicator = content.findViewById(R.id.page_indicator);
+        if (previews.length > 1) {
             mPageIndicator.setViewPager(mPreviewPager);
             mPageIndicator.setVisibility(View.VISIBLE);
             mPageIndicator.setOnPageChangeListener(mPageIndicatorPageChangeListener);
@@ -187,6 +172,12 @@
         mSeekBar.setOnSeekBarChangeListener(null);
     }
 
+    /** Resource id of the layout for this preference fragment. */
+    protected abstract int getActivityLayoutResId();
+
+    /** Resource id of the layout that defines the contents inside preview screen. */
+    protected abstract int[] getPreviewSampleResIds();
+
     /**
      * Creates new configuration based on the current position of the SeekBar.
      */
@@ -210,8 +201,8 @@
 
     private void setPagerIndicatorContentDescription(int position) {
         mPageIndicator.setContentDescription(
-                getPrefContext().getString(R.string.preview_page_indicator_content_description,
-                        position + 1, mPreviewSampleResIds.length));
+                getString(R.string.preview_page_indicator_content_description,
+                        position + 1, getPreviewSampleResIds().length));
     }
 
     private OnPageChangeListener mPreviewPageChangeListener = new OnPageChangeListener() {
diff --git a/src/com/android/settings/display/ScreenZoomPreferenceFragmentForSetupWizard.java b/src/com/android/settings/display/ScreenZoomPreferenceFragmentForSetupWizard.java
index 82cb58d..e02579f 100644
--- a/src/com/android/settings/display/ScreenZoomPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/display/ScreenZoomPreferenceFragmentForSetupWizard.java
@@ -18,8 +18,7 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
-public class ScreenZoomPreferenceFragmentForSetupWizard
-        extends ScreenZoomSettings {
+public class ScreenZoomPreferenceFragmentForSetupWizard extends ScreenZoomSettings {
 
     @Override
     public int getMetricsCategory() {
diff --git a/src/com/android/settings/display/ScreenZoomSettings.java b/src/com/android/settings/display/ScreenZoomSettings.java
index dbb6353..37ac046 100644
--- a/src/com/android/settings/display/ScreenZoomSettings.java
+++ b/src/com/android/settings/display/ScreenZoomSettings.java
@@ -24,9 +24,9 @@
 import android.view.Display;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.PreviewSeekBarPreferenceFragment;
 import com.android.settings.R;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
 import com.android.settingslib.display.DisplayDensityUtils;
 import com.android.settingslib.search.SearchIndexable;
@@ -44,16 +44,25 @@
     private int[] mValues;
 
     @Override
+    protected int getActivityLayoutResId() {
+        return R.layout.screen_zoom_activity;
+    }
+
+    @Override
+    protected int[] getPreviewSampleResIds() {
+        return getContext().getResources().getBoolean(
+                R.bool.config_enable_extra_screen_zoom_preview)
+                ? new int[]{
+                        R.layout.screen_zoom_preview_1,
+                        R.layout.screen_zoom_preview_2,
+                        R.layout.screen_zoom_preview_settings}
+                : new int[]{R.layout.screen_zoom_preview_1};
+    }
+
+    @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mActivityLayoutResId = R.layout.screen_zoom_activity;
-
-        // This should be replaced once the final preview sample screen is in place.
-        mPreviewSampleResIds = new int[] {R.layout.screen_zoom_preview_1,
-                R.layout.screen_zoom_preview_2,
-                R.layout.screen_zoom_preview_settings};
-
         final DisplayDensityUtils density = new DisplayDensityUtils(getContext());
 
         final int initialIndex = density.getCurrentIndex();
@@ -62,8 +71,8 @@
             // connect to the window manager service. Just use the current
             // density and don't let the user change anything.
             final int densityDpi = getResources().getDisplayMetrics().densityDpi;
-            mValues = new int[] {densityDpi};
-            mEntries = new String[] {getString(DisplayDensityUtils.SUMMARY_DEFAULT)};
+            mValues = new int[]{densityDpi};
+            mEntries = new String[]{getString(DisplayDensityUtils.SUMMARY_DEFAULT)};
             mInitialIndex = 0;
             mDefaultDensity = densityDpi;
         } else {
@@ -108,7 +117,7 @@
     }
 
     /** Index provider used to expose this fragment in search. */
-    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
                 @Override
                 public List<SearchIndexableRaw> getRawDataToIndex(Context context,
diff --git a/src/com/android/settings/display/TimeoutPreferenceController.java b/src/com/android/settings/display/TimeoutPreferenceController.java
index c068168..60b7e24 100644
--- a/src/com/android/settings/display/TimeoutPreferenceController.java
+++ b/src/com/android/settings/display/TimeoutPreferenceController.java
@@ -28,6 +28,7 @@
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 public class TimeoutPreferenceController extends AbstractPreferenceController implements
@@ -65,7 +66,7 @@
                 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
         if (dpm != null) {
             final RestrictedLockUtils.EnforcedAdmin admin =
-                    RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext);
+                    RestrictedLockUtilsInternal.checkIfMaximumTimeToLockIsSet(mContext);
             final long maxTimeout =
                     dpm.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId());
             timeoutListPreference.removeUnusableTimeouts(maxTimeout, admin);
@@ -73,7 +74,7 @@
         updateTimeoutPreferenceDescription(timeoutListPreference,
                 Long.parseLong(timeoutListPreference.getValue()));
 
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 mContext, UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
                 UserHandle.myUserId());
         if (admin != null) {
diff --git a/src/com/android/settings/accessibility/ToggleFontSizePreferenceFragment.java b/src/com/android/settings/display/ToggleFontSizePreferenceFragment.java
similarity index 91%
rename from src/com/android/settings/accessibility/ToggleFontSizePreferenceFragment.java
rename to src/com/android/settings/display/ToggleFontSizePreferenceFragment.java
index c3100ee..4f118d5 100644
--- a/src/com/android/settings/accessibility/ToggleFontSizePreferenceFragment.java
+++ b/src/com/android/settings/display/ToggleFontSizePreferenceFragment.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.accessibility;
+package com.android.settings.display;
 
 import android.annotation.Nullable;
 import android.content.ContentResolver;
@@ -25,7 +25,6 @@
 import android.provider.Settings;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.PreviewSeekBarPreferenceFragment;
 import com.android.settings.R;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
@@ -44,13 +43,20 @@
     private float[] mValues;
 
     @Override
+    protected int getActivityLayoutResId() {
+        return R.layout.font_size_activity;
+    }
+
+    @Override
+    protected int[] getPreviewSampleResIds() {
+        return new int[]{R.layout.font_size_preview};
+    }
+
+    @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mActivityLayoutResId = R.layout.font_size_activity;
-        mPreviewSampleResIds = new int[] {R.layout.font_size_preview};
-
-        Resources res = getContext().getResources();
+        final Resources res = getContext().getResources();
         final ContentResolver resolver = getContext().getContentResolver();
         // Mark the appropriate item in the preferences list.
         mEntries = res.getStringArray(R.array.entries_font_size);
diff --git a/src/com/android/settings/display/WallpaperPreferenceController.java b/src/com/android/settings/display/WallpaperPreferenceController.java
index 8e29004..ff3be12 100644
--- a/src/com/android/settings/display/WallpaperPreferenceController.java
+++ b/src/com/android/settings/display/WallpaperPreferenceController.java
@@ -28,7 +28,7 @@
 
 import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 
@@ -80,7 +80,7 @@
         final String restriction = DISALLOW_SET_WALLPAPER;
         if (pref != null) {
             pref.setDisabledByAdmin(null);
-            if (RestrictedLockUtils.hasBaseUserRestriction(mContext,
+            if (RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
                     restriction, UserHandle.myUserId())) {
                 pref.setEnabled(false);
             } else {
diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
index 52bd4f5..ac1939c 100644
--- a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
+++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
@@ -41,6 +41,7 @@
 import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminAdd;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.util.Objects;
 
@@ -94,7 +95,7 @@
         if (admin == null) {
             return;
         }
-        if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(mActivity, admin)
+        if (!RestrictedLockUtilsInternal.isAdminInCurrentUserOrProfile(mActivity, admin)
                 || !RestrictedLockUtils.isCurrentUserOrProfile(mActivity, userId)) {
             admin = null;
         } else {
@@ -136,9 +137,6 @@
             case DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE:
                 titleView.setText(R.string.disabled_by_policy_title_screen_capture);
                 break;
-            case DevicePolicyManager.POLICY_MANDATORY_BACKUPS:
-                titleView.setText(R.string.disabled_by_policy_title_turn_off_backups);
-                break;
             case DevicePolicyManager.POLICY_SUSPEND_PACKAGES:
                 titleView.setText(R.string.disabled_by_policy_title_suspend_packages);
                 break;
@@ -156,7 +154,7 @@
         }
         final DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
-        if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(activity,
+        if (!RestrictedLockUtilsInternal.isAdminInCurrentUserOrProfile(activity,
                 enforcedAdmin.component) || !RestrictedLockUtils.isCurrentUserOrProfile(
                 activity, enforcedAdmin.userId)) {
             enforcedAdmin.component = null;
diff --git a/src/com/android/settings/enterprise/BackupsEnabledPreferenceController.java b/src/com/android/settings/enterprise/BackupsEnabledPreferenceController.java
deleted file mode 100644
index b24f8dc..0000000
--- a/src/com/android/settings/enterprise/BackupsEnabledPreferenceController.java
+++ /dev/null
@@ -1,37 +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.settings.enterprise;
-
-import android.content.Context;
-
-import com.android.settings.core.BasePreferenceController;
-import com.android.settings.overlay.FeatureFactory;
-
-public class BackupsEnabledPreferenceController extends BasePreferenceController {
-
-    private static final String KEY_BACKUPS_ENABLED = "backups_enabled";
-    private final EnterprisePrivacyFeatureProvider mFeatureProvider;
-
-    public BackupsEnabledPreferenceController(Context context) {
-        super(context, KEY_BACKUPS_ENABLED);
-        mFeatureProvider = FeatureFactory.getFactory(context)
-                .getEnterprisePrivacyFeatureProvider(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return mFeatureProvider.areBackupsMandatory() ? AVAILABLE : DISABLED_FOR_USER;
-    }
-}
-
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
index 51d125d..048782e 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
@@ -124,9 +124,4 @@
      * profile (if any).
      */
     int getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile();
-
-    /*
-     * Returns whether backups are mandatory.
-     */
-    boolean areBackupsMandatory();
 }
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index 5505683..4085988 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -234,11 +234,6 @@
         return activeAdmins;
     }
 
-    @Override
-    public boolean areBackupsMandatory() {
-        return null != mDpm.getMandatoryBackupTransport();
-    }
-
     protected static class EnterprisePrivacySpan extends ClickableSpan {
         private final Context mContext;
 
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
index f04c421..dab1395 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
@@ -84,7 +84,6 @@
         exposureChangesCategoryControllers.add(new CaCertsCurrentUserPreferenceController(context));
         exposureChangesCategoryControllers.add(new CaCertsManagedProfilePreferenceController(
                 context));
-        exposureChangesCategoryControllers.add(new BackupsEnabledPreferenceController(context));
         controllers.addAll(exposureChangesCategoryControllers);
         controllers.add(new PreferenceCategoryController(context, "exposure_changes_category")
                 .setChildren(exposureChangesCategoryControllers));
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index a2ceb67..7c21774 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -58,7 +58,9 @@
     private PowerGaugePreference(Context context, AttributeSet attrs, Drawable icon,
             CharSequence contentDescription, BatteryEntry info) {
         super(context, attrs);
-        setIcon(icon != null ? icon : new ColorDrawable(0));
+        if (icon != null) {
+            setIcon(icon);
+        }
         setWidgetLayoutResource(R.layout.preference_widget_summary);
         mInfo = info;
         mContentDescription = contentDescription;
diff --git a/src/com/android/settings/homepage/CardContentLoader.java b/src/com/android/settings/homepage/CardContentLoader.java
index 4e1e33e..9805ae3 100644
--- a/src/com/android/settings/homepage/CardContentLoader.java
+++ b/src/com/android/settings/homepage/CardContentLoader.java
@@ -17,46 +17,52 @@
 package com.android.settings.homepage;
 
 import android.content.Context;
+import android.database.Cursor;
 
-import androidx.annotation.Nullable;
+import androidx.annotation.NonNull;
 
 import com.android.settingslib.utils.AsyncLoaderCompat;
 
+import java.util.ArrayList;
 import java.util.List;
 
-//TODO(b/112521307): Implement this to make it work with the card database.
-public class CardContentLoader {
+public class CardContentLoader extends AsyncLoaderCompat<List<ContextualCard>> {
+    static final int CARD_CONTENT_LOADER_ID = 1;
 
-    private static final String TAG = "CardContentLoader";
-
-    private CardContentLoaderListener mListener;
+    private Context mContext;
 
     public interface CardContentLoaderListener {
-        void onFinishCardLoading(List<HomepageCard> homepageCards);
+        void onFinishCardLoading(List<ContextualCard> contextualCards);
     }
 
-    public CardContentLoader() {
+    CardContentLoader(Context context) {
+        super(context);
+        mContext = context.getApplicationContext();
     }
 
-    void setListener(CardContentLoaderListener listener) {
-        mListener = listener;
+    @Override
+    protected void onDiscardResult(List<ContextualCard> result) {
+
     }
 
-    private static class CardLoader extends AsyncLoaderCompat<List<HomepageCard>> {
-
-        public CardLoader(Context context) {
-            super(context);
+    @NonNull
+    @Override
+    public List<ContextualCard> loadInBackground() {
+        final List<ContextualCard> result = new ArrayList<>();
+        try (Cursor cursor = CardDatabaseHelper.getInstance(mContext).getContextualCards()) {
+            if (cursor.getCount() == 0) {
+                //TODO(b/113372471): Load Default static cards and return 3 static cards
+                return result;
+            }
+            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
+                final ContextualCard card = new ContextualCard(cursor);
+                if (card.isCustomCard()) {
+                    //TODO(b/114688391): Load and generate custom card,then add into list
+                } else {
+                    result.add(card);
+                }
+            }
         }
-
-        @Override
-        protected void onDiscardResult(List<HomepageCard> result) {
-
-        }
-
-        @Nullable
-        @Override
-        public List<HomepageCard> loadInBackground() {
-            return null;
-        }
+        return result;
     }
 }
diff --git a/src/com/android/settings/homepage/CardContentProvider.java b/src/com/android/settings/homepage/CardContentProvider.java
index 640a00b..7b08756 100644
--- a/src/com/android/settings/homepage/CardContentProvider.java
+++ b/src/com/android/settings/homepage/CardContentProvider.java
@@ -61,23 +61,38 @@
 
     @Override
     public Uri insert(Uri uri, ContentValues values) {
+        final ContentValues[] cvs = {values};
+        bulkInsert(uri, cvs);
+        return uri;
+    }
+
+    @Override
+    public int bulkInsert(Uri uri, ContentValues[] values) {
         final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
+        int numInserted = 0;
+        final SQLiteDatabase database = mDBHelper.getWritableDatabase();
+
         try {
             maybeEnableStrictMode();
 
-            final SQLiteDatabase database = mDBHelper.getWritableDatabase();
             final String table = getTableFromMatch(uri);
-            final long ret = database.insert(table, null, values);
-            if (ret != -1) {
-                getContext().getContentResolver().notifyChange(uri, null);
-            } else {
-                Log.e(TAG, "The CardContentProvider insertion failed! Plase check SQLiteDatabase's "
-                        + "message.");
+            database.beginTransaction();
+            for (ContentValues value : values) {
+                long ret = database.insert(table, null, value);
+                if (ret != -1L) {
+                    numInserted++;
+                } else {
+                    Log.e(TAG, "The row " + value.getAsString(CardDatabaseHelper.CardColumns.NAME)
+                            + " insertion failed! Please check your data.");
+                }
             }
+            database.setTransactionSuccessful();
+            getContext().getContentResolver().notifyChange(uri, null);
         } finally {
+            database.endTransaction();
             StrictMode.setThreadPolicy(oldPolicy);
         }
-        return uri;
+        return numInserted;
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/CardDatabaseHelper.java b/src/com/android/settings/homepage/CardDatabaseHelper.java
index 382b71f..b53479e 100644
--- a/src/com/android/settings/homepage/CardDatabaseHelper.java
+++ b/src/com/android/settings/homepage/CardDatabaseHelper.java
@@ -17,6 +17,7 @@
 package com.android.settings.homepage;
 
 import android.content.Context;
+import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.util.Log;
@@ -190,4 +191,12 @@
         }
         return sCardDatabaseHelper;
     }
+
+    Cursor getContextualCards() {
+        final SQLiteDatabase db = this.getReadableDatabase();
+        Cursor cursor = db.query(CARD_TABLE, null /* columns */, null /* selection */,
+                null /* selectionArgs */, null /* groupBy */, null /* having */,
+                null /* orderBy */);
+        return cursor;
+    }
 }
diff --git a/src/com/android/settings/homepage/HomepageCard.java b/src/com/android/settings/homepage/ContextualCard.java
similarity index 69%
rename from src/com/android/settings/homepage/HomepageCard.java
rename to src/com/android/settings/homepage/ContextualCard.java
index 588c758..5bd265b 100644
--- a/src/com/android/settings/homepage/HomepageCard.java
+++ b/src/com/android/settings/homepage/ContextualCard.java
@@ -17,6 +17,7 @@
 package com.android.settings.homepage;
 
 import android.annotation.IntDef;
+import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.text.TextUtils;
@@ -25,17 +26,17 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * Data class representing a {@link HomepageCard}.
+ * Data class representing a {@link ContextualCard}.
  */
-public class HomepageCard {
+public class ContextualCard {
 
     /**
-     * Flags indicating the type of the HomepageCard.
+     * Flags indicating the type of the ContextualCard.
      */
-    @IntDef({CardType.INVALID, CardType.SLICE, CardType.SUGGESTION, CardType.CONDITIONAL})
+    @IntDef({CardType.DEFAULT, CardType.SLICE, CardType.SUGGESTION, CardType.CONDITIONAL})
     @Retention(RetentionPolicy.SOURCE)
     public @interface CardType {
-        int INVALID = -1;
+        int DEFAULT = 0;
         int SLICE = 1;
         int SUGGESTION = 2;
         int CONDITIONAL = 3;
@@ -58,86 +59,90 @@
     private final int mIconResId;
     private final int mCardAction;
     private final long mExpireTimeMS;
-    private final Drawable mIconDrawable;
     private final boolean mIsHalfWidth;
+    private final Drawable mIconDrawable;
 
     String getName() {
         return mName;
     }
 
-    int getCardType() {
+    public int getCardType() {
         return mCardType;
     }
 
-    double getRankingScore() {
+    public double getRankingScore() {
         return mRankingScore;
     }
 
-    String getTextSliceUri() {
+    public String getTextSliceUri() {
         return mSliceUri;
     }
 
-    Uri getSliceUri() {
+    public Uri getSliceUri() {
         return Uri.parse(mSliceUri);
     }
 
-    int getCategory() {
+    public int getCategory() {
         return mCategory;
     }
 
-    String getLocalizedToLocale() {
+    public String getLocalizedToLocale() {
         return mLocalizedToLocale;
     }
 
-    String getPackageName() {
+    public String getPackageName() {
         return mPackageName;
     }
 
-    String getAppVersion() {
+    public String getAppVersion() {
         return mAppVersion;
     }
 
-    String getTitleResName() {
+    public String getTitleResName() {
         return mTitleResName;
     }
 
-    String getTitleText() {
+    public String getTitleText() {
         return mTitleText;
     }
 
-    String getSummaryResName() {
+    public String getSummaryResName() {
         return mSummaryResName;
     }
 
-    String getSummaryText() {
+    public String getSummaryText() {
         return mSummaryText;
     }
 
-    String getIconResName() {
+    public String getIconResName() {
         return mIconResName;
     }
 
-    int getIconResId() {
+    public int getIconResId() {
         return mIconResId;
     }
 
-    int getCardAction() {
+    public int getCardAction() {
         return mCardAction;
     }
 
-    long getExpireTimeMS() {
+    public long getExpireTimeMS() {
         return mExpireTimeMS;
     }
 
-    Drawable getIconDrawable() {
+    public Drawable getIconDrawable() {
         return mIconDrawable;
     }
 
-    boolean isHalfWidth() {
+    public boolean isHalfWidth() {
         return mIsHalfWidth;
     }
 
-    HomepageCard(Builder builder) {
+    boolean isCustomCard() {
+        return TextUtils.isEmpty(mSliceUri);
+    }
+
+    public ContextualCard(Builder builder) {
         mName = builder.mName;
         mCardType = builder.mCardType;
         mRankingScore = builder.mRankingScore;
@@ -158,6 +163,31 @@
         mIsHalfWidth = builder.mIsHalfWidth;
     }
 
+    ContextualCard(Cursor c) {
+        mName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.NAME));
+        mCardType = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.TYPE));
+        mRankingScore = c.getDouble(c.getColumnIndex(CardDatabaseHelper.CardColumns.SCORE));
+        mSliceUri = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.SLICE_URI));
+        mCategory = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.CATEGORY));
+        mLocalizedToLocale = c.getString(
+                c.getColumnIndex(CardDatabaseHelper.CardColumns.LOCALIZED_TO_LOCALE));
+        mPackageName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.PACKAGE_NAME));
+        mAppVersion = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.APP_VERSION));
+        mTitleResName = c.getString(
+                c.getColumnIndex(CardDatabaseHelper.CardColumns.TITLE_RES_NAME));
+        mTitleText = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.TITLE_TEXT));
+        mSummaryResName = c.getString(
+                c.getColumnIndex(CardDatabaseHelper.CardColumns.SUMMARY_RES_NAME));
+        mSummaryText = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.SUMMARY_TEXT));
+        mIconResName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.ICON_RES_NAME));
+        mIconResId = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.ICON_RES_ID));
+        mCardAction = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.CARD_ACTION));
+        mExpireTimeMS = c.getLong(c.getColumnIndex(CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS));
+        mIsHalfWidth = (c.getInt(
+                c.getColumnIndex(CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH)) == 1);
+        mIconDrawable = null;
+    }
+
     @Override
     public int hashCode() {
         return mName.hashCode();
@@ -171,15 +201,15 @@
         if (this == obj) {
             return true;
         }
-        if (!(obj instanceof HomepageCard)) {
+        if (!(obj instanceof ContextualCard)) {
             return false;
         }
-        final HomepageCard that = (HomepageCard) obj;
+        final ContextualCard that = (ContextualCard) obj;
 
         return TextUtils.equals(mName, that.mName);
     }
 
-    static class Builder {
+    public static class Builder {
         private String mName;
         private int mCardType;
         private double mRankingScore;
@@ -289,8 +319,8 @@
             return this;
         }
 
-        public HomepageCard build() {
-            return new HomepageCard(this);
+        public ContextualCard build() {
+            return new ContextualCard(this);
         }
     }
 }
diff --git a/src/com/android/settings/homepage/ContextualCardController.java b/src/com/android/settings/homepage/ContextualCardController.java
new file mode 100644
index 0000000..e47f70c
--- /dev/null
+++ b/src/com/android/settings/homepage/ContextualCardController.java
@@ -0,0 +1,32 @@
+/*
+ * 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.settings.homepage;
+
+/**
+ * Data controller for {@link ContextualCard}.
+ */
+public interface ContextualCardController {
+
+    @ContextualCard.CardType
+    int getCardType();
+
+    void onPrimaryClick(ContextualCard card);
+
+    void onActionClick(ContextualCard card);
+
+    void setCardUpdateListener(ContextualCardUpdateListener listener);
+}
diff --git a/src/com/android/settings/homepage/ContextualCardLookupTable.java b/src/com/android/settings/homepage/ContextualCardLookupTable.java
new file mode 100644
index 0000000..e70b700
--- /dev/null
+++ b/src/com/android/settings/homepage/ContextualCardLookupTable.java
@@ -0,0 +1,75 @@
+/*
+ * 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.settings.homepage;
+
+import com.android.settings.homepage.ContextualCard.CardType;
+import com.android.settings.homepage.conditional.ConditionContextualCardController;
+import com.android.settings.homepage.conditional.ConditionContextualCardRenderer;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+public class ContextualCardLookupTable {
+
+    static class ControllerRendererMapping implements Comparable<ControllerRendererMapping> {
+        @CardType
+        private final int mCardType;
+        private final Class<? extends ContextualCardController> mControllerClass;
+        private final Class<? extends ContextualCardRenderer> mRendererClass;
+
+        private ControllerRendererMapping(@CardType int cardType,
+                Class<? extends ContextualCardController> controllerClass,
+                Class<? extends ContextualCardRenderer> rendererClass) {
+            mCardType = cardType;
+            mControllerClass = controllerClass;
+            mRendererClass = rendererClass;
+        }
+
+        @Override
+        public int compareTo(ControllerRendererMapping other) {
+            return Integer.compare(this.mCardType, other.mCardType);
+        }
+    }
+
+    private static final Set<ControllerRendererMapping> LOOKUP_TABLE =
+            new TreeSet<ControllerRendererMapping>() {{
+                add(new ControllerRendererMapping(CardType.CONDITIONAL,
+                        ConditionContextualCardController.class,
+                        ConditionContextualCardRenderer.class));
+            }};
+
+    public static Class<? extends ContextualCardController> getCardControllerClass(
+            @CardType int cardType) {
+        for (ControllerRendererMapping mapping : LOOKUP_TABLE) {
+            if (mapping.mCardType == cardType) {
+                return mapping.mControllerClass;
+            }
+        }
+        return null;
+    }
+
+    //TODO(b/112578070): Implement multi renderer cases.
+    public static Class<? extends ContextualCardRenderer> getCardRendererClasses(
+            @CardType int cardType) {
+        for (ControllerRendererMapping mapping : LOOKUP_TABLE) {
+            if (mapping.mCardType == cardType) {
+                return mapping.mRendererClass;
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/settings/homepage/ContextualCardManager.java b/src/com/android/settings/homepage/ContextualCardManager.java
new file mode 100644
index 0000000..87b048e
--- /dev/null
+++ b/src/com/android/settings/homepage/ContextualCardManager.java
@@ -0,0 +1,197 @@
+/*
+ * 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.settings.homepage;
+
+import static com.android.settings.homepage.CardContentLoader.CARD_CONTENT_LOADER_ID;
+
+import static java.util.stream.Collectors.groupingBy;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.widget.BaseAdapter;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * This is a centralized manager of multiple {@link ContextualCardController}.
+ *
+ * {@link ContextualCardManager} first loads data from {@link CardContentLoader} and gets back a
+ * list of {@link ContextualCard}. All subclasses of {@link ContextualCardController} are loaded
+ * here, which will then trigger the {@link ContextualCardController} to load its data and listen to
+ * corresponding changes. When every single {@link ContextualCardController} updates its data, the
+ * data will be passed here, then going through some sorting mechanisms. The
+ * {@link ContextualCardController} will end up building a list of {@link ContextualCard} for
+ * {@link ContextualCardsAdapter} and {@link BaseAdapter#notifyDataSetChanged()} will be called to
+ * get the page refreshed.
+ */
+public class ContextualCardManager implements CardContentLoader.CardContentLoaderListener,
+        ContextualCardUpdateListener {
+
+    private static final String TAG = "ContextualCardManager";
+    //The list for Settings Custom Card
+    @ContextualCard.CardType
+    private static final int[] SETTINGS_CARDS = {ContextualCard.CardType.CONDITIONAL};
+
+    private final Context mContext;
+    private final ControllerRendererPool mControllerRendererPool;
+    private final Lifecycle mLifecycle;
+    private final List<ContextualCard> mContextualCards;
+    private final List<LifecycleObserver> mLifecycleObservers;
+
+    private ContextualCardUpdateListener mListener;
+
+    public ContextualCardManager(Context context, @NonNull Lifecycle lifecycle) {
+        mContext = context;
+        mLifecycle = lifecycle;
+        mContextualCards = new ArrayList<>();
+        mLifecycleObservers = new ArrayList<>();
+        mControllerRendererPool = new ControllerRendererPool();
+        //for data provided by Settings
+        for (int cardType : SETTINGS_CARDS) {
+            setupController(cardType);
+        }
+    }
+
+    void loadContextualCards(PersonalSettingsFragment fragment) {
+        final CardContentLoaderCallbacks cardContentLoaderCallbacks =
+                new CardContentLoaderCallbacks(mContext);
+        cardContentLoaderCallbacks.setListener(this);
+        LoaderManager.getInstance(fragment).initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
+                cardContentLoaderCallbacks);
+    }
+
+    private void loadCardControllers() {
+        for (ContextualCard card : mContextualCards) {
+            setupController(card.getCardType());
+        }
+    }
+
+    private void setupController(int cardType) {
+        final ContextualCardController controller = mControllerRendererPool.getController(mContext,
+                cardType);
+        if (controller == null) {
+            Log.w(TAG, "Cannot find ContextualCardController for type " + cardType);
+            return;
+        }
+        controller.setCardUpdateListener(this);
+        if (controller instanceof LifecycleObserver && !mLifecycleObservers.contains(controller)) {
+            mLifecycleObservers.add((LifecycleObserver) controller);
+            mLifecycle.addObserver((LifecycleObserver) controller);
+        }
+    }
+
+    //TODO(b/111822376): implement sorting mechanism.
+    private void sortCards(List<ContextualCard> cards) {
+        //take mContextualCards as the source and do the ranking based on the rule.
+    }
+
+    @Override
+    public void onContextualCardUpdated(Map<Integer, List<ContextualCard>> updateList) {
+        //TODO(b/112245748): Should implement a DiffCallback.
+        //Keep the old list for comparison.
+        final List<ContextualCard> prevCards = mContextualCards;
+
+        final Set<Integer> cardTypes = updateList.keySet();
+        //Remove the existing data that matches the certain cardType before inserting new data.
+        final List<ContextualCard> cardsToKeep = mContextualCards
+                .stream()
+                .filter(card -> !cardTypes.contains(card.getCardType()))
+                .collect(Collectors.toList());
+        final List<ContextualCard> allCards = new ArrayList<>();
+        allCards.addAll(cardsToKeep);
+        allCards.addAll(
+                updateList.values().stream().flatMap(List::stream).collect(Collectors.toList()));
+
+        sortCards(allCards);
+        //replace with the new data
+        mContextualCards.clear();
+        mContextualCards.addAll(allCards);
+
+        loadCardControllers();
+
+        if (mListener != null) {
+            final Map<Integer, List<ContextualCard>> cardsToUpdate = new ArrayMap<>();
+            cardsToUpdate.put(ContextualCard.CardType.DEFAULT, mContextualCards);
+            mListener.onContextualCardUpdated(cardsToUpdate);
+        }
+    }
+
+    @Override
+    public void onFinishCardLoading(List<ContextualCard> cards) {
+        onContextualCardUpdated(cards.stream().collect(groupingBy(ContextualCard::getCardType)));
+    }
+
+    void setListener(ContextualCardUpdateListener listener) {
+        mListener = listener;
+    }
+
+    public ControllerRendererPool getControllerRendererPool() {
+        return mControllerRendererPool;
+    }
+
+    static class CardContentLoaderCallbacks implements
+            LoaderManager.LoaderCallbacks<List<ContextualCard>> {
+
+        private Context mContext;
+        private CardContentLoader.CardContentLoaderListener mListener;
+
+        CardContentLoaderCallbacks(Context context) {
+            mContext = context.getApplicationContext();
+        }
+
+        protected void setListener(CardContentLoader.CardContentLoaderListener listener) {
+            mListener = listener;
+        }
+
+        @NonNull
+        @Override
+        public Loader<List<ContextualCard>> onCreateLoader(int id, @Nullable Bundle bundle) {
+            if (id == CARD_CONTENT_LOADER_ID) {
+                return new CardContentLoader(mContext);
+            } else {
+                throw new IllegalArgumentException("Unknown loader id: " + id);
+            }
+        }
+
+        @Override
+        public void onLoadFinished(@NonNull Loader<List<ContextualCard>> loader,
+                List<ContextualCard> contextualCards) {
+            if (mListener != null) {
+                mListener.onFinishCardLoading(contextualCards);
+            }
+        }
+
+        @Override
+        public void onLoaderReset(@NonNull Loader<List<ContextualCard>> loader) {
+
+        }
+    }
+}
diff --git a/src/com/android/settings/homepage/HomepageCardRenderer.java b/src/com/android/settings/homepage/ContextualCardRenderer.java
similarity index 68%
rename from src/com/android/settings/homepage/HomepageCardRenderer.java
rename to src/com/android/settings/homepage/ContextualCardRenderer.java
index ffa54e3..315c09d 100644
--- a/src/com/android/settings/homepage/HomepageCardRenderer.java
+++ b/src/com/android/settings/homepage/ContextualCardRenderer.java
@@ -21,9 +21,9 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 /**
- * UI renderer for {@link HomepageCard}.
+ * UI renderer for {@link ContextualCard}.
  */
-public interface HomepageCardRenderer {
+public interface ContextualCardRenderer {
 
     /**
      * The layout type of the controller.
@@ -31,16 +31,16 @@
     int getViewType();
 
     /**
-     * When {@link HomepageAdapter} calls {@link HomepageAdapter#onCreateViewHolder(ViewGroup,
-     * int)}, this method will be called to retrieve the corresponding
+     * When {@link ContextualCardsAdapter} calls {@link ContextualCardsAdapter#onCreateViewHolder},
+     * this method will be called to retrieve the corresponding
      * {@link androidx.recyclerview.widget.RecyclerView.ViewHolder}.
      */
     RecyclerView.ViewHolder createViewHolder(View view);
 
     /**
-     * When {@link HomepageAdapter} calls {@link HomepageAdapter#onBindViewHolder(RecyclerView
-     * .ViewHolder, int)}, this method will be called to bind data to the
+     * When {@link ContextualCardsAdapter} calls {@link ContextualCardsAdapter#onBindViewHolder},
+     * this method will be called to bind data to the
      * {@link androidx.recyclerview.widget.RecyclerView.ViewHolder}.
      */
-    void bindView(RecyclerView.ViewHolder holder, HomepageCard card);
+    void bindView(RecyclerView.ViewHolder holder, ContextualCard card);
 }
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/ContextualCardUpdateListener.java b/src/com/android/settings/homepage/ContextualCardUpdateListener.java
new file mode 100644
index 0000000..60dd3a7
--- /dev/null
+++ b/src/com/android/settings/homepage/ContextualCardUpdateListener.java
@@ -0,0 +1,35 @@
+/*
+ * 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.settings.homepage;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * When {@link ContextualCardController} detects changes, it will notify the listeners registered.
+ */
+public interface ContextualCardUpdateListener {
+
+    /**
+     * Called when a set of cards are updated.
+     *
+     * @param cards A map of updates grouped by {@link ContextualCard.CardType}. Values can be
+     *              null, which means all cards from corresponding {@link
+     *              ContextualCard.CardType} are removed.
+     */
+    void onContextualCardUpdated(Map<Integer, List<ContextualCard>> cards);
+}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/ContextualCardsAdapter.java b/src/com/android/settings/homepage/ContextualCardsAdapter.java
new file mode 100644
index 0000000..9ab8893
--- /dev/null
+++ b/src/com/android/settings/homepage/ContextualCardsAdapter.java
@@ -0,0 +1,117 @@
+/*
+ * 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.settings.homepage;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class ContextualCardsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
+        implements ContextualCardUpdateListener {
+    static final int SPAN_COUNT = 2;
+
+    private static final String TAG = "ContextualCardsAdapter";
+    private static final int HALF_WIDTH = 1;
+    private static final int FULL_WIDTH = 2;
+
+    private final Context mContext;
+    private final ControllerRendererPool mControllerRendererPool;
+    private final List<ContextualCard> mContextualCards;
+
+    public ContextualCardsAdapter(Context context, ContextualCardManager manager) {
+        mContext = context;
+        mContextualCards = new ArrayList<>();
+        mControllerRendererPool = manager.getControllerRendererPool();
+        setHasStableIds(true);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return mContextualCards.get(position).hashCode();
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return mContextualCards.get(position).getCardType();
+    }
+
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int cardType) {
+        final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
+                cardType);
+        final int viewType = renderer.getViewType();
+        final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
+
+        return renderer.createViewHolder(view);
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+        final int cardType = mContextualCards.get(position).getCardType();
+        final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
+                cardType);
+
+        renderer.bindView(holder, mContextualCards.get(position));
+    }
+
+    @Override
+    public int getItemCount() {
+        return mContextualCards.size();
+    }
+
+    @Override
+    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
+        super.onAttachedToRecyclerView(recyclerView);
+        final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
+        if (layoutManager instanceof GridLayoutManager) {
+            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
+            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
+                @Override
+                public int getSpanSize(int position) {
+                    final ContextualCard card = mContextualCards.get(position);
+                    //TODO(b/114009676): may use another field to make decision. still under review.
+                    if (card.isHalfWidth()) {
+                        return HALF_WIDTH;
+                    }
+                    return FULL_WIDTH;
+                }
+            });
+        }
+    }
+
+    @Override
+    public void onContextualCardUpdated(Map<Integer, List<ContextualCard>> cards) {
+        final List<ContextualCard> contextualCards = cards.get(ContextualCard.CardType.DEFAULT);
+        //TODO(b/112245748): Should implement a DiffCallback so we can use notifyItemChanged()
+        // instead.
+        if (contextualCards == null) {
+            mContextualCards.clear();
+        } else {
+            mContextualCards.clear();
+            mContextualCards.addAll(contextualCards);
+        }
+        notifyDataSetChanged();
+    }
+}
diff --git a/src/com/android/settings/homepage/ControllerRendererPool.java b/src/com/android/settings/homepage/ControllerRendererPool.java
index b2ac9ec..1e4b37c 100644
--- a/src/com/android/settings/homepage/ControllerRendererPool.java
+++ b/src/com/android/settings/homepage/ControllerRendererPool.java
@@ -21,78 +21,78 @@
 
 import androidx.collection.ArraySet;
 
+import com.android.settings.homepage.conditional.ConditionContextualCardController;
+import com.android.settings.homepage.conditional.ConditionContextualCardRenderer;
+
 import java.util.Set;
 
 /**
- * This is a fragment scoped singleton holding a set of {@link HomepageCardController} and
- * {@link HomepageCardRenderer}.
+ * This is a fragment scoped singleton holding a set of {@link ContextualCardController} and
+ * {@link ContextualCardRenderer}.
  */
 public class ControllerRendererPool {
 
     private static final String TAG = "ControllerRendererPool";
 
-    private final Set<HomepageCardController> mControllers;
-    private final Set<HomepageCardRenderer> mRenderers;
+    private final Set<ContextualCardController> mControllers;
+    private final Set<ContextualCardRenderer> mRenderers;
 
     public ControllerRendererPool() {
         mControllers = new ArraySet<>();
         mRenderers = new ArraySet<>();
     }
 
-    public <T extends HomepageCardController> T getController(Context context,
-            @HomepageCard.CardType int cardType) {
-        final Class<? extends HomepageCardController> clz =
-                HomepageCardLookupTable.getCardControllerClass(cardType);
-        for (HomepageCardController controller : mControllers) {
+    public <T extends ContextualCardController> T getController(Context context,
+            @ContextualCard.CardType int cardType) {
+        final Class<? extends ContextualCardController> clz =
+                ContextualCardLookupTable.getCardControllerClass(cardType);
+        for (ContextualCardController controller : mControllers) {
             if (controller.getClass() == clz) {
                 Log.d(TAG, "Controller is already there.");
                 return (T) controller;
             }
         }
 
-        final HomepageCardController controller = createCardController(context, clz);
+        final ContextualCardController controller = createCardController(context, clz);
         if (controller != null) {
             mControllers.add(controller);
         }
         return (T) controller;
     }
 
-    public Set<HomepageCardController> getControllers() {
+    public Set<ContextualCardController> getControllers() {
         return mControllers;
     }
 
-    public HomepageCardRenderer getRenderer(Context context, @HomepageCard.CardType int cardType) {
-        final Class<? extends HomepageCardRenderer> clz =
-                HomepageCardLookupTable.getCardRendererClasses(cardType);
-        for (HomepageCardRenderer renderer : mRenderers) {
+    public ContextualCardRenderer getRenderer(Context context, @ContextualCard.CardType int cardType) {
+        final Class<? extends ContextualCardRenderer> clz =
+                ContextualCardLookupTable.getCardRendererClasses(cardType);
+        for (ContextualCardRenderer renderer : mRenderers) {
             if (renderer.getClass() == clz) {
                 Log.d(TAG, "Renderer is already there.");
                 return renderer;
             }
         }
 
-        final HomepageCardRenderer renderer = createCardRenderer(context, clz);
+        final ContextualCardRenderer renderer = createCardRenderer(context, clz);
         if (renderer != null) {
             mRenderers.add(renderer);
         }
         return renderer;
     }
 
-    private HomepageCardController createCardController(Context context,
-            Class<? extends HomepageCardController> clz) {
-        /*
-        if (ConditionHomepageCardController.class == clz) {
-            return new ConditionHomepageCardController(context);
+    private ContextualCardController createCardController(Context context,
+            Class<? extends ContextualCardController> clz) {
+        if (ConditionContextualCardController.class == clz) {
+            return new ConditionContextualCardController(context);
         }
-        */
         return null;
     }
 
-    private HomepageCardRenderer createCardRenderer(Context context, Class<?> clz) {
-        //if (ConditionHomepageCardRenderer.class == clz) {
-        //    return new ConditionHomepageCardRenderer(context, this /*controllerRendererPool*/);
-        //}
-
+    private ContextualCardRenderer createCardRenderer(Context context, Class<?> clz) {
+        if (ConditionContextualCardRenderer.class == clz) {
+            return new ConditionContextualCardRenderer(context, this /*controllerRendererPool*/);
+        }
         return null;
     }
 
diff --git a/src/com/android/settings/homepage/HomepageAdapter.java b/src/com/android/settings/homepage/HomepageAdapter.java
deleted file mode 100644
index 9ff5260..0000000
--- a/src/com/android/settings/homepage/HomepageAdapter.java
+++ /dev/null
@@ -1,98 +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.settings.homepage;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class HomepageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements
-        HomepageCardUpdateListener {
-
-    private static final String TAG = "HomepageAdapter";
-
-    private final Context mContext;
-    private final ControllerRendererPool mControllerRendererPool;
-
-    private List<HomepageCard> mHomepageCards;
-    private RecyclerView mRecyclerView;
-
-    public HomepageAdapter(Context context, HomepageManager manager) {
-        mContext = context;
-        mHomepageCards = new ArrayList<>();
-        mControllerRendererPool = manager.getControllerRendererPool();
-        setHasStableIds(true);
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return mHomepageCards.get(position).hashCode();
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        return mHomepageCards.get(position).getCardType();
-    }
-
-    @Override
-    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int cardType) {
-        final HomepageCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
-                cardType);
-        final int viewType = renderer.getViewType();
-        final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
-
-        return renderer.createViewHolder(view);
-    }
-
-    @Override
-    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
-        final int cardType = mHomepageCards.get(position).getCardType();
-        final HomepageCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
-                cardType);
-
-        renderer.bindView(holder, mHomepageCards.get(position));
-    }
-
-    @Override
-    public int getItemCount() {
-        return mHomepageCards.size();
-    }
-
-    @Override
-    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-        super.onAttachedToRecyclerView(recyclerView);
-        mRecyclerView = recyclerView;
-    }
-
-    @Override
-    public void onHomepageCardUpdated(int cardType, List<HomepageCard> homepageCards) {
-        //TODO(b/112245748): Should implement a DiffCallback so we can use notifyItemChanged()
-        // instead.
-        if (homepageCards == null) {
-            mHomepageCards.clear();
-        } else {
-            mHomepageCards = homepageCards;
-        }
-        notifyDataSetChanged();
-    }
-}
diff --git a/src/com/android/settings/homepage/HomepageCardController.java b/src/com/android/settings/homepage/HomepageCardController.java
deleted file mode 100644
index 10fc158..0000000
--- a/src/com/android/settings/homepage/HomepageCardController.java
+++ /dev/null
@@ -1,42 +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.settings.homepage;
-
-import java.util.List;
-
-//TODO(b/111821137): add test cases
-
-/**
- * Data controller for {@link HomepageCard}.
- */
-public interface HomepageCardController {
-
-    @HomepageCard.CardType
-    int getCardType();
-
-    /**
-     * When data is updated or changed, the new data should be passed to HomepageManager for list
-     * updating.
-     */
-    void onDataUpdated(List<HomepageCard> cardList);
-
-    void onPrimaryClick(HomepageCard card);
-
-    void onActionClick(HomepageCard card);
-
-    void setHomepageCardUpdateListener(HomepageCardUpdateListener listener);
-}
diff --git a/src/com/android/settings/homepage/HomepageCardLookupTable.java b/src/com/android/settings/homepage/HomepageCardLookupTable.java
deleted file mode 100644
index ae3f08b..0000000
--- a/src/com/android/settings/homepage/HomepageCardLookupTable.java
+++ /dev/null
@@ -1,71 +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.settings.homepage;
-
-import com.android.settings.homepage.HomepageCard.CardType;
-
-import java.util.Set;
-import java.util.TreeSet;
-
-public class HomepageCardLookupTable {
-
-    static class HomepageMapping implements Comparable<HomepageMapping> {
-        @CardType
-        private final int mCardType;
-        private final Class<? extends HomepageCardController> mControllerClass;
-        private final Class<? extends HomepageCardRenderer> mRendererClass;
-
-        private HomepageMapping(@CardType int cardType,
-                Class<? extends HomepageCardController> controllerClass,
-                Class<? extends HomepageCardRenderer> rendererClass) {
-            mCardType = cardType;
-            mControllerClass = controllerClass;
-            mRendererClass = rendererClass;
-        }
-
-        @Override
-        public int compareTo(HomepageMapping other) {
-            return Integer.compare(this.mCardType, other.mCardType);
-        }
-    }
-
-    private static final Set<HomepageMapping> LOOKUP_TABLE = new TreeSet<HomepageMapping>() {
-            //add(new HomepageMapping(CardType.CONDITIONAL, ConditionHomepageCardController.class,
-                   // ConditionHomepageCardRenderer.class));
-    };
-
-    public static Class<? extends HomepageCardController> getCardControllerClass(
-            @CardType int cardType) {
-        for (HomepageMapping mapping : LOOKUP_TABLE) {
-            if (mapping.mCardType == cardType) {
-                return mapping.mControllerClass;
-            }
-        }
-        return null;
-    }
-
-    //TODO(b/112578070): Implement multi renderer cases.
-    public static Class<? extends HomepageCardRenderer> getCardRendererClasses(
-            @CardType int cardType) {
-        for (HomepageMapping mapping : LOOKUP_TABLE) {
-            if (mapping.mCardType == cardType) {
-                return mapping.mRendererClass;
-            }
-        }
-        return null;
-    }
-}
diff --git a/src/com/android/settings/homepage/HomepageCardUpdateListener.java b/src/com/android/settings/homepage/HomepageCardUpdateListener.java
deleted file mode 100644
index a44ba2b..0000000
--- a/src/com/android/settings/homepage/HomepageCardUpdateListener.java
+++ /dev/null
@@ -1,31 +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.settings.homepage;
-
-import java.util.List;
-
-/**
- * When {@link HomepageCardController} detects changes, it will notify the listeners registered. In
- * our case, {@link HomepageManager} gets noticed.
- *
- * After the list of {@link HomepageCard} gets updated in{@link HomepageManager},
- * {@link HomepageManager} will notify the listeners registered, {@link HomepageAdapter} in this
- * case.
- */
-interface HomepageCardUpdateListener {
-    void onHomepageCardUpdated(int cardType, List<HomepageCard> updateList);
-}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/HomepageFragment.java b/src/com/android/settings/homepage/HomepageFragment.java
deleted file mode 100644
index 402725e..0000000
--- a/src/com/android/settings/homepage/HomepageFragment.java
+++ /dev/null
@@ -1,196 +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.settings.homepage;
-
-import android.app.ActionBar;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Toolbar;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.SettingsHomepageActivity;
-import com.android.settings.Utils;
-import com.android.settings.core.InstrumentedFragment;
-import com.android.settings.dashboard.DashboardSummary;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.search.SearchFeatureProvider;
-
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-
-public class HomepageFragment extends InstrumentedFragment {
-
-    private static final String TAG = "HomepageFragment";
-    private static final String SAVE_BOTTOMBAR_STATE = "bottombar_state";
-    private static final String SAVE_BOTTOM_FRAGMENT_LOADED = "bottom_fragment_loaded";
-
-    private RecyclerView mCardsContainer;
-    private HomepageAdapter mHomepageAdapter;
-    private LinearLayoutManager mLayoutManager;
-
-    private FloatingActionButton mSearchButton;
-    private BottomSheetBehavior mBottomSheetBehavior;
-    private View mBottomBar;
-    private View mSearchBar;
-    private boolean mBottomFragmentLoaded;
-    private HomepageManager mHomepageManager;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mHomepageManager = new HomepageManager(getContext(), getSettingsLifecycle());
-        mHomepageManager.startCardContentLoading();
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        final View rootView = inflater.inflate(R.layout.settings_homepage,
-                container, false);
-        mCardsContainer = (RecyclerView) rootView.findViewById(R.id.card_container);
-        //TODO(b/111822407): May have to swap to GridLayoutManager
-        mLayoutManager = new LinearLayoutManager(getActivity());
-        mCardsContainer.setLayoutManager(mLayoutManager);
-        mHomepageAdapter = new HomepageAdapter(getContext(), mHomepageManager);
-        mCardsContainer.setAdapter(mHomepageAdapter);
-        mHomepageManager.setListener(mHomepageAdapter);
-
-        return rootView;
-    }
-
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        setupBottomBar();
-        setupSearchBar();
-        if (savedInstanceState != null) {
-            final int bottombarState = savedInstanceState.getInt(SAVE_BOTTOMBAR_STATE);
-            mBottomFragmentLoaded = savedInstanceState.getBoolean(SAVE_BOTTOM_FRAGMENT_LOADED);
-            mBottomSheetBehavior.setState(bottombarState);
-            setBarState(bottombarState);
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-
-        if (mBottomSheetBehavior != null) {
-            outState.putInt(SAVE_BOTTOMBAR_STATE, mBottomSheetBehavior.getState());
-            outState.putBoolean(SAVE_BOTTOM_FRAGMENT_LOADED, mBottomFragmentLoaded);
-        }
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.SETTINGS_HOMEPAGE;
-    }
-
-    private void setupBottomBar() {
-        final Activity activity = getActivity();
-
-        mSearchButton = activity.findViewById(R.id.search_fab);
-        mSearchButton.setOnClickListener(v -> {
-            final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT;
-            intent.setPackage(FeatureFactory.getFactory(activity)
-                    .getSearchFeatureProvider().getSettingsIntelligencePkgName());
-            startActivityForResult(intent, 0 /* requestCode */);
-        });
-        mBottomSheetBehavior = BottomSheetBehavior.from(activity.findViewById(R.id.bottom_sheet));
-        mSearchBar = activity.findViewById(R.id.search_bar_container);
-        mBottomBar = activity.findViewById(R.id.bar);
-        mBottomBar.setOnClickListener(v -> {
-            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
-        });
-
-        final int screenWidthpx = getResources().getDisplayMetrics().widthPixels;
-        final Toolbar searchActionBar = activity.findViewById(R.id.search_action_bar);
-        searchActionBar.setNavigationIcon(R.drawable.ic_search_floating_24dp);
-
-        mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
-            @Override
-            public void onStateChanged(@NonNull View bottomSheet, int newState) {
-                if (!mBottomFragmentLoaded) {
-                    // TODO(b/110405144): Switch to {@link TopLevelSettings} when it's ready.
-                    SettingsHomepageActivity.switchToFragment(getActivity(),
-                            R.id.bottom_sheet_fragment, DashboardSummary.class.getName());
-                    mBottomFragmentLoaded = true;
-                }
-                setBarState(newState);
-            }
-
-            @Override
-            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
-                mBottomBar.setAlpha(1 - slideOffset);
-                mSearchButton.setAlpha(1 - slideOffset);
-                mSearchBar.setAlpha(slideOffset);
-                mSearchBar.setPadding((int) (screenWidthpx * (1 - slideOffset)), 0, 0, 0);
-            }
-        });
-    }
-
-    private void setBarState(int bottomSheetState) {
-        if (bottomSheetState == BottomSheetBehavior.STATE_EXPANDED) {
-            mBottomBar.setVisibility(View.INVISIBLE);
-            mSearchBar.setVisibility(View.VISIBLE);
-            mSearchButton.setVisibility(View.GONE);
-        } else if (bottomSheetState == BottomSheetBehavior.STATE_COLLAPSED) {
-            mBottomBar.setVisibility(View.VISIBLE);
-            mSearchBar.setVisibility(View.INVISIBLE);
-            mSearchButton.setVisibility(View.VISIBLE);
-        } else if (bottomSheetState == BottomSheetBehavior.STATE_SETTLING) {
-            mBottomBar.setVisibility(View.VISIBLE);
-            mSearchBar.setVisibility(View.VISIBLE);
-            mSearchButton.setVisibility(View.VISIBLE);
-        }
-    }
-
-    //TODO(110767984), copied from settingsActivity. We have to merge them
-    private void setupSearchBar() {
-        final Activity activity = getActivity();
-        final Toolbar toolbar = activity.findViewById(R.id.search_action_bar);
-        FeatureFactory.getFactory(activity).getSearchFeatureProvider()
-                .initSearchToolbar(activity, toolbar);
-        activity.setActionBar(toolbar);
-
-        // Please forgive me for what I am about to do.
-        //
-        // Need to make the navigation icon non-clickable so that the entire card is clickable
-        // and goes to the search UI. Also set the background to null so there's no ripple.
-        final View navView = toolbar.getNavigationView();
-        navView.setClickable(false);
-        navView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
-        navView.setBackground(null);
-
-        final ActionBar actionBar = activity.getActionBar();
-        if (actionBar != null) {
-            boolean deviceProvisioned = Utils.isDeviceProvisioned(activity);
-            actionBar.setDisplayHomeAsUpEnabled(deviceProvisioned);
-            actionBar.setHomeButtonEnabled(deviceProvisioned);
-            actionBar.setDisplayShowTitleEnabled(false);
-        }
-    }
-}
diff --git a/src/com/android/settings/homepage/HomepageManager.java b/src/com/android/settings/homepage/HomepageManager.java
deleted file mode 100644
index 61d7ce7..0000000
--- a/src/com/android/settings/homepage/HomepageManager.java
+++ /dev/null
@@ -1,140 +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.settings.homepage;
-
-import android.content.Context;
-import android.widget.BaseAdapter;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This is a centralized manager of multiple {@link HomepageCardController}.
- *
- * {@link HomepageManager} first loads data from {@link CardContentLoader} and gets back a list of
- * {@link HomepageCard}. All subclasses of {@link HomepageCardController} are loaded here, which
- * will then trigger the {@link HomepageCardController} to load its data and listen to
- * corresponding changes. When every single {@link HomepageCardController} updates its data, the
- * data will be passed here, then going through some sorting mechanisms. The
- * {@link HomepageCardController} will end up building a list of {@link HomepageCard} for {@link
- * HomepageAdapter} and {@link BaseAdapter#notifyDataSetChanged()} will be called to get the page
- * refreshed.
- */
-public class HomepageManager implements CardContentLoader.CardContentLoaderListener,
-        HomepageCardUpdateListener {
-
-    private static final String TAG = "HomepageManager";
-    //The list for Settings Custom Card
-    @HomepageCard.CardType
-    private static final int[] SETTINGS_CARDS = {HomepageCard.CardType.CONDITIONAL};
-
-    private final Context mContext;
-    private final ControllerRendererPool mControllerRendererPool;
-    private final Lifecycle mLifecycle;
-
-    private List<HomepageCard> mHomepageCards;
-    private HomepageCardUpdateListener mListener;
-
-
-    public HomepageManager(Context context, Lifecycle lifecycle) {
-        mContext = context;
-        mLifecycle = lifecycle;
-        mHomepageCards = new ArrayList<>();
-        mControllerRendererPool = new ControllerRendererPool();
-    }
-
-    void startCardContentLoading() {
-        final CardContentLoader cardContentLoader = new CardContentLoader();
-        cardContentLoader.setListener(this);
-    }
-
-    private void loadCardControllers() {
-        if (mHomepageCards != null) {
-            for (HomepageCard card : mHomepageCards) {
-                setupController(card.getCardType());
-            }
-        }
-
-        //for data provided by Settings
-        for (int cardType : SETTINGS_CARDS) {
-            setupController(cardType);
-        }
-    }
-
-    private void setupController(int cardType) {
-        final HomepageCardController controller = mControllerRendererPool.getController(mContext,
-                cardType);
-        if (controller != null) {
-            controller.setHomepageCardUpdateListener(this);
-            if (controller instanceof LifecycleObserver) {
-                if (mLifecycle != null) {
-                    mLifecycle.addObserver((LifecycleObserver) controller);
-                }
-            }
-        }
-    }
-
-    //TODO(b/111822376): implement sorting mechanism.
-    private void sortCards() {
-        //take mHomepageCards as the source and do the ranking based on the rule.
-    }
-
-    @Override
-    public void onHomepageCardUpdated(int cardType, List<HomepageCard> updateList) {
-        //TODO(b/112245748): Should implement a DiffCallback.
-        //Keep the old list for comparison.
-        final List<HomepageCard> prevCards = mHomepageCards;
-
-        //Remove the existing data that matches the certain cardType so as to insert the new data.
-        for (int i = mHomepageCards.size() - 1; i >= 0; i--) {
-            if (mHomepageCards.get(i).getCardType() == cardType) {
-                mHomepageCards.remove(i);
-            }
-        }
-
-        //Append the new data
-        mHomepageCards.addAll(updateList);
-
-        sortCards();
-
-        if (mListener != null) {
-            mListener.onHomepageCardUpdated(HomepageCard.CardType.INVALID, mHomepageCards);
-        }
-    }
-
-    @Override
-    public void onFinishCardLoading(List<HomepageCard> homepageCards) {
-        mHomepageCards = homepageCards;
-
-        //Force card sorting here in case CardControllers of custom view have nothing to update
-        // for the first launch.
-        sortCards();
-
-        loadCardControllers();
-    }
-
-    void setListener(HomepageCardUpdateListener listener) {
-        mListener = listener;
-    }
-
-    public ControllerRendererPool getControllerRendererPool() {
-        return mControllerRendererPool;
-    }
-}
diff --git a/src/com/android/settings/homepage/PersonalSettingsFragment.java b/src/com/android/settings/homepage/PersonalSettingsFragment.java
new file mode 100644
index 0000000..4a0041e
--- /dev/null
+++ b/src/com/android/settings/homepage/PersonalSettingsFragment.java
@@ -0,0 +1,68 @@
+/*
+ * 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.settings.homepage;
+
+import static com.android.settings.homepage.ContextualCardsAdapter.SPAN_COUNT;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.core.InstrumentedFragment;
+
+public class PersonalSettingsFragment extends InstrumentedFragment {
+
+    private static final String TAG = "PersonalSettingsFragment";
+
+    private RecyclerView mCardsContainer;
+    private GridLayoutManager mLayoutManager;
+    private ContextualCardsAdapter mContextualCardsAdapter;
+    private ContextualCardManager mContextualCardManager;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle());
+        mContextualCardManager.loadContextualCards(this);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View rootView = inflater.inflate(R.layout.settings_homepage, container, false);
+        mCardsContainer = rootView.findViewById(R.id.card_container);
+        mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT,
+                GridLayoutManager.VERTICAL, false /* reverseLayout */);
+        mCardsContainer.setLayoutManager(mLayoutManager);
+        mContextualCardsAdapter = new ContextualCardsAdapter(getContext(), mContextualCardManager);
+        mCardsContainer.setAdapter(mContextualCardsAdapter);
+        mContextualCardManager.setListener(mContextualCardsAdapter);
+
+        return rootView;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.SETTINGS_HOMEPAGE;
+    }
+}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
new file mode 100644
index 0000000..35b45a4
--- /dev/null
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -0,0 +1,106 @@
+/*
+ * 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.settings.homepage;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.FeatureFlagUtils;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+import com.android.settings.R;
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.core.SettingsBaseActivity;
+import com.android.settings.overlay.FeatureFactory;
+
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+
+public class SettingsHomepageActivity extends SettingsBaseActivity {
+
+    @VisibleForTesting
+    static final String PERSONAL_SETTINGS_TAG = "personal_settings";
+    private static final String ALL_SETTINGS_TAG = "all_settings";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (!isDynamicHomepageEnabled(this)) {
+            final Intent settings = new Intent();
+            settings.setAction("android.settings.SETTINGS");
+            startActivity(settings);
+            finish();
+            return;
+        }
+
+        setContentView(R.layout.settings_homepage_container);
+
+        final FloatingActionButton searchButton = findViewById(R.id.search_fab);
+        FeatureFactory.getFactory(this).getSearchFeatureProvider()
+                .initSearchToolbar(this, searchButton);
+
+        final BottomNavigationView navigation = findViewById(R.id.bottom_nav);
+        navigation.setOnNavigationItemSelectedListener(item -> {
+            switch (item.getItemId()) {
+                case R.id.homepage_personal_settings:
+                    switchFragment(new PersonalSettingsFragment(), PERSONAL_SETTINGS_TAG,
+                            ALL_SETTINGS_TAG);
+                    return true;
+
+                case R.id.homepage_all_settings:
+                    switchFragment(new TopLevelSettings(), ALL_SETTINGS_TAG,
+                            PERSONAL_SETTINGS_TAG);
+                    return true;
+            }
+            return false;
+        });
+
+        if (savedInstanceState == null) {
+            // savedInstanceState is null, this is first load.
+            // Default to open contextual cards.
+            switchFragment(new PersonalSettingsFragment(), PERSONAL_SETTINGS_TAG,
+                    ALL_SETTINGS_TAG);
+        }
+    }
+
+    public static boolean isDynamicHomepageEnabled(Context context) {
+        return FeatureFlagUtils.isEnabled(context, FeatureFlags.DYNAMIC_HOMEPAGE);
+    }
+
+    private void switchFragment(Fragment fragment, String showFragmentTag, String hideFragmentTag) {
+        final FragmentManager fragmentManager = getSupportFragmentManager();
+        final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+        final Fragment hideFragment = fragmentManager.findFragmentByTag(hideFragmentTag);
+        if (hideFragment != null) {
+            fragmentTransaction.hide(hideFragment);
+        }
+
+        Fragment showFragment = fragmentManager.findFragmentByTag(showFragmentTag);
+        if (showFragment == null) {
+            fragmentTransaction.add(R.id.main_content, fragment, showFragmentTag);
+        } else {
+            fragmentTransaction.show(showFragment);
+        }
+        fragmentTransaction.commit();
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java
new file mode 100644
index 0000000..fbbab14
--- /dev/null
+++ b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java
@@ -0,0 +1,110 @@
+/*
+ * 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.settings.homepage.conditional;
+
+import android.content.Context;
+import android.util.ArrayMap;
+
+import com.android.settings.homepage.ContextualCard;
+import com.android.settings.homepage.ContextualCardController;
+import com.android.settings.homepage.ContextualCardUpdateListener;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This controller triggers the loading of conditional cards and monitors state changes to
+ * update the homepage.
+ */
+public class ConditionContextualCardController implements ContextualCardController,
+        ConditionListener, LifecycleObserver, OnStart, OnStop {
+
+    private final Context mContext;
+    private final ConditionManager mConditionManager;
+
+    private ContextualCardUpdateListener mListener;
+
+    public ConditionContextualCardController(Context context) {
+        mContext = context;
+        mConditionManager = new ConditionManager(context.getApplicationContext(), this);
+        mConditionManager.startMonitoringStateChange();
+    }
+
+    @Override
+    public void setCardUpdateListener(ContextualCardUpdateListener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    public int getCardType() {
+        return ContextualCard.CardType.CONDITIONAL;
+    }
+
+    @Override
+    public void onStart() {
+        mConditionManager.startMonitoringStateChange();
+    }
+
+    @Override
+    public void onStop() {
+        mConditionManager.stopMonitoringStateChange();
+    }
+
+    @Override
+    public void onPrimaryClick(ContextualCard contextualCard) {
+        final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard;
+        mConditionManager.onPrimaryClick(mContext, card.getConditionId());
+    }
+
+    @Override
+    public void onActionClick(ContextualCard contextualCard) {
+        final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard;
+        mConditionManager.onActionClick(card.getConditionId());
+    }
+
+    @Override
+    public void onConditionsChanged() {
+        final List<ContextualCard> conditionCards = new ArrayList<>();
+        final List<ConditionalCard> conditionList = mConditionManager.getDisplayableCards();
+
+        for (ConditionalCard condition : conditionList) {
+            final ContextualCard conditionCard =
+                    new ConditionalContextualCard.Builder()
+                            .setConditionId(condition.getId())
+                            .setMetricsConstant(condition.getMetricsConstant())
+                            .setActionText(condition.getActionText())
+                            .setName(mContext.getPackageName() + "/"
+                                    + condition.getTitle().toString())
+                            .setTitleText(condition.getTitle().toString())
+                            .setSummaryText(condition.getSummary().toString())
+                            .setIconDrawable(condition.getIcon())
+                            .build();
+
+            conditionCards.add(conditionCard);
+        }
+
+        if (mListener != null) {
+            final Map<Integer, List<ContextualCard>> conditionalCards = new ArrayMap<>();
+            conditionalCards.put(ContextualCard.CardType.CONDITIONAL, conditionCards);
+            mListener.onContextualCardUpdated(conditionalCards);
+        }
+    }
+}
diff --git a/src/com/android/settings/homepage/conditional/ConditionContextualCardRenderer.java b/src/com/android/settings/homepage/conditional/ConditionContextualCardRenderer.java
new file mode 100644
index 0000000..69988ae
--- /dev/null
+++ b/src/com/android/settings/homepage/conditional/ConditionContextualCardRenderer.java
@@ -0,0 +1,137 @@
+/*
+ * 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.settings.homepage.conditional;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.homepage.ContextualCard;
+import com.android.settings.homepage.ControllerRendererPool;
+import com.android.settings.homepage.ContextualCardRenderer;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+/**
+ * Card renderer for {@link ConditionalContextualCard}.
+ */
+public class ConditionContextualCardRenderer implements ContextualCardRenderer {
+
+    private final Context mContext;
+    private final ControllerRendererPool mControllerRendererPool;
+
+    public ConditionContextualCardRenderer(Context context,
+            ControllerRendererPool controllerRendererPool) {
+        mContext = context;
+        mControllerRendererPool = controllerRendererPool;
+    }
+
+    @Override
+    public int getViewType() {
+        return R.layout.homepage_condition_tile;
+    }
+
+    @Override
+    public RecyclerView.ViewHolder createViewHolder(View view) {
+        return new ConditionalCardHolder(view);
+    }
+
+    @Override
+    public void bindView(RecyclerView.ViewHolder holder, ContextualCard contextualCard) {
+        final ConditionalCardHolder view = (ConditionalCardHolder) holder;
+        final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard;
+        final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory(
+                mContext).getMetricsFeatureProvider();
+
+        metricsFeatureProvider.visible(mContext, MetricsProto.MetricsEvent.SETTINGS_HOMEPAGE,
+                card.getMetricsConstant());
+        initializePrimaryClick(view, card, metricsFeatureProvider);
+        initializeView(view, card);
+        initializeActionButton(view, card, metricsFeatureProvider);
+    }
+
+    private void initializePrimaryClick(ConditionalCardHolder view, ConditionalContextualCard card,
+            MetricsFeatureProvider metricsFeatureProvider) {
+        view.itemView.findViewById(R.id.content).setOnClickListener(
+                v -> {
+                    metricsFeatureProvider.action(mContext,
+                            MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK,
+                            card.getMetricsConstant());
+                    mControllerRendererPool.getController(mContext,
+                            card.getCardType()).onPrimaryClick(card);
+                });
+    }
+
+    private void initializeView(ConditionalCardHolder view, ConditionalContextualCard card) {
+        view.icon.setImageDrawable(card.getIconDrawable());
+        view.title.setText(card.getTitleText());
+        view.summary.setText(card.getSummaryText());
+
+        setViewVisibility(view.itemView, R.id.divider, false);
+    }
+
+    private void initializeActionButton(ConditionalCardHolder view, ConditionalContextualCard card,
+            MetricsFeatureProvider metricsFeatureProvider) {
+        final CharSequence action = card.getActionText();
+        final boolean hasButtons = !TextUtils.isEmpty(action);
+        setViewVisibility(view.itemView, R.id.buttonBar, hasButtons);
+
+        final Button button = view.itemView.findViewById(R.id.first_action);
+        if (hasButtons) {
+            button.setVisibility(View.VISIBLE);
+            button.setText(action);
+            button.setOnClickListener(v -> {
+                final Context viewContext = v.getContext();
+                metricsFeatureProvider.action(
+                        viewContext, MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON,
+                        card.getMetricsConstant());
+                mControllerRendererPool.getController(mContext, card.getCardType()).onActionClick(
+                        card);
+            });
+        } else {
+            button.setVisibility(View.GONE);
+        }
+    }
+
+    private void setViewVisibility(View containerView, int viewId, boolean visible) {
+        View view = containerView.findViewById(viewId);
+        if (view != null) {
+            view.setVisibility(visible ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    public static class ConditionalCardHolder extends RecyclerView.ViewHolder {
+
+        public final ImageView icon;
+        public final TextView title;
+        public final TextView summary;
+
+        public ConditionalCardHolder(View itemView) {
+            super(itemView);
+            icon = itemView.findViewById(android.R.id.icon);
+            title = itemView.findViewById(android.R.id.title);
+            summary = itemView.findViewById(android.R.id.summary);
+        }
+    }
+}
diff --git a/src/com/android/settings/homepage/conditional/ConditionalContextualCard.java b/src/com/android/settings/homepage/conditional/ConditionalContextualCard.java
new file mode 100644
index 0000000..828f90b
--- /dev/null
+++ b/src/com/android/settings/homepage/conditional/ConditionalContextualCard.java
@@ -0,0 +1,91 @@
+/*
+ * 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.settings.homepage.conditional;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.homepage.ContextualCard;
+
+/**
+ * Data class representing a conditional {@link ContextualCard}.
+ *
+ * Use this class to store additional attributes on top of {@link ContextualCard} for
+ * {@link ConditionalCard}.
+ */
+public class ConditionalContextualCard extends ContextualCard {
+
+    private final long mConditionId;
+    private final int mMetricsConstant;
+    private final CharSequence mActionText;
+
+    private ConditionalContextualCard(Builder builder) {
+        super(builder);
+
+        mConditionId = builder.mConditionId;
+        mMetricsConstant = builder.mMetricsConstant;
+        mActionText = builder.mActionText;
+    }
+
+    @Override
+    public int getCardType() {
+        return CardType.CONDITIONAL;
+    }
+
+    public long getConditionId() {
+        return mConditionId;
+    }
+
+    public int getMetricsConstant() {
+        return mMetricsConstant;
+    }
+
+    public CharSequence getActionText() {
+        return mActionText;
+    }
+
+    public static class Builder extends ContextualCard.Builder {
+
+        private long mConditionId;
+        private int mMetricsConstant;
+        private CharSequence mActionText;
+
+        public Builder setConditionId(long id) {
+            mConditionId = id;
+            return this;
+        }
+
+        public Builder setMetricsConstant(int metricsConstant) {
+            mMetricsConstant = metricsConstant;
+            return this;
+        }
+
+        public Builder setActionText(CharSequence actionText) {
+            mActionText = actionText;
+            return this;
+        }
+
+        @Override
+        public Builder setCardType(int cardType) {
+            throw new IllegalArgumentException(
+                    "Cannot change card type for " + getClass().getName());
+        }
+
+        public ConditionalContextualCard build() {
+            return new ConditionalContextualCard(this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/conditional/HotspotConditionCard.java b/src/com/android/settings/homepage/conditional/HotspotConditionCard.java
index a6ff224..fd99693 100644
--- a/src/com/android/settings/homepage/conditional/HotspotConditionCard.java
+++ b/src/com/android/settings/homepage/conditional/HotspotConditionCard.java
@@ -23,7 +23,7 @@
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 public class HotspotConditionCard implements ConditionalCard {
 
@@ -42,7 +42,7 @@
 
     @Override
     public CharSequence getActionText() {
-        if (RestrictedLockUtils.hasBaseUserRestriction(mAppContext,
+        if (RestrictedLockUtilsInternal.hasBaseUserRestriction(mAppContext,
                 UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId())) {
             return null;
         }
diff --git a/src/com/android/settings/homepage/conditional/HotspotConditionController.java b/src/com/android/settings/homepage/conditional/HotspotConditionController.java
index 4271136..5ff7f23 100644
--- a/src/com/android/settings/homepage/conditional/HotspotConditionController.java
+++ b/src/com/android/settings/homepage/conditional/HotspotConditionController.java
@@ -31,6 +31,7 @@
 import com.android.settings.TetherSettings;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.util.Objects;
 
@@ -75,7 +76,7 @@
     @Override
     public void onActionClick() {
         final RestrictedLockUtils.EnforcedAdmin admin =
-                RestrictedLockUtils.checkIfRestrictionEnforced(
+                RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                         mAppContext, UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId());
         if (admin != null) {
             RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mAppContext, admin);
diff --git a/src/com/android/settings/location/LocationEnabler.java b/src/com/android/settings/location/LocationEnabler.java
index 65de6e2..20c2280 100644
--- a/src/com/android/settings/location/LocationEnabler.java
+++ b/src/com/android/settings/location/LocationEnabler.java
@@ -13,7 +13,7 @@
  */
 package com.android.settings.location;
 
-import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced;
+import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfRestrictionEnforced;
 import static com.android.settingslib.Utils.updateLocationEnabled;
 import static com.android.settingslib.Utils.updateLocationMode;
 
@@ -32,6 +32,7 @@
 
 import com.android.settings.Utils;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
@@ -168,14 +169,14 @@
                 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId);
 
         if (admin == null) {
-            admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+            admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                     mContext, UserManager.DISALLOW_CONFIG_LOCATION, userId);
         }
         return admin;
     }
 
     boolean hasShareLocationRestriction(int userId) {
-        return RestrictedLockUtils.hasBaseUserRestriction(
+        return RestrictedLockUtilsInternal.hasBaseUserRestriction(
                 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId);
     }
 
diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java
index ece4294..4230c67 100644
--- a/src/com/android/settings/network/MobileNetworkPreferenceController.java
+++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java
@@ -36,7 +36,7 @@
 
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.Utils;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -84,7 +84,7 @@
 
     public boolean isUserRestricted() {
         return mIsSecondaryUser ||
-                RestrictedLockUtils.hasBaseUserRestriction(
+                RestrictedLockUtilsInternal.hasBaseUserRestriction(
                         mContext,
                         DISALLOW_CONFIG_MOBILE_NETWORKS,
                         myUserId());
diff --git a/src/com/android/settings/network/MobilePlanPreferenceController.java b/src/com/android/settings/network/MobilePlanPreferenceController.java
index 1db6b2e..dc41708 100644
--- a/src/com/android/settings/network/MobilePlanPreferenceController.java
+++ b/src/com/android/settings/network/MobilePlanPreferenceController.java
@@ -20,7 +20,7 @@
 import static android.os.UserHandle.myUserId;
 import static android.os.UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
 
-import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction;
+import static com.android.settingslib.RestrictedLockUtilsInternal.hasBaseUserRestriction;
 
 import android.content.ActivityNotFoundException;
 import android.content.Context;
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index a2a2450..0279cfa 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -15,12 +15,15 @@
  */
 package com.android.settings.network;
 
+import static android.provider.Settings.ACTION_DATA_USAGE_SETTINGS;
 import static com.android.settings.network.MobilePlanPreferenceController
         .MANAGE_MOBILE_PLAN_DIALOG_ID;
 
 import android.app.Activity;
 import android.app.Dialog;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.icu.text.ListFormatter;
 import android.provider.SearchIndexableResource;
 import android.text.BidiFormatter;
@@ -45,6 +48,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.function.BooleanSupplier;
 import java.util.List;
 
 @SearchIndexable
@@ -158,24 +162,32 @@
         private final WifiMasterSwitchPreferenceController mWifiPreferenceController;
         private final MobileNetworkPreferenceController mMobileNetworkPreferenceController;
         private final TetherPreferenceController mTetherPreferenceController;
+        private final BooleanSupplier mHasDataUsageActivity;
 
         public SummaryProvider(Context context, SummaryLoader summaryLoader) {
             this(context, summaryLoader,
                     new WifiMasterSwitchPreferenceController(context, null),
                     new MobileNetworkPreferenceController(context),
-                    new TetherPreferenceController(context, null /* lifecycle */));
+                    new TetherPreferenceController(context, null /* lifecycle */),
+                    () -> {
+                        final Intent intent = new Intent(ACTION_DATA_USAGE_SETTINGS);
+                        final PackageManager pm = context.getPackageManager();
+                        return intent.resolveActivity(pm) != null;
+                    });
         }
 
         @VisibleForTesting(otherwise = VisibleForTesting.NONE)
         SummaryProvider(Context context, SummaryLoader summaryLoader,
                 WifiMasterSwitchPreferenceController wifiPreferenceController,
                 MobileNetworkPreferenceController mobileNetworkPreferenceController,
-                TetherPreferenceController tetherPreferenceController) {
+                TetherPreferenceController tetherPreferenceController,
+                BooleanSupplier hasDataUsageActivity) {
             mContext = context;
             mSummaryLoader = summaryLoader;
             mWifiPreferenceController = wifiPreferenceController;
             mMobileNetworkPreferenceController = mobileNetworkPreferenceController;
             mTetherPreferenceController = tetherPreferenceController;
+            mHasDataUsageActivity = hasDataUsageActivity;
         }
 
 
@@ -198,7 +210,7 @@
                 if (mMobileNetworkPreferenceController.isAvailable() && !TextUtils.isEmpty(mobileSummary)) {
                     summaries.add(mobileSummary);
                 }
-                if (!TextUtils.isEmpty(dataUsageSummary)) {
+                if (!TextUtils.isEmpty(dataUsageSummary) && mHasDataUsageActivity.getAsBoolean()) {
                     summaries.add(dataUsageSummary);
                 }
                 if (mTetherPreferenceController.isAvailable() && !TextUtils.isEmpty(hotspotSummary)) {
diff --git a/src/com/android/settings/network/NetworkResetRestrictionChecker.java b/src/com/android/settings/network/NetworkResetRestrictionChecker.java
index bb1fde7..46227f9 100644
--- a/src/com/android/settings/network/NetworkResetRestrictionChecker.java
+++ b/src/com/android/settings/network/NetworkResetRestrictionChecker.java
@@ -22,7 +22,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 public class NetworkResetRestrictionChecker {
 
@@ -36,13 +36,13 @@
 
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
     boolean hasUserBaseRestriction() {
-        return RestrictedLockUtils.hasBaseUserRestriction(mContext,
+        return RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
                 UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
     }
 
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
     boolean isRestrictionEnforcedByAdmin() {
-        return RestrictedLockUtils.checkIfRestrictionEnforced(
+        return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 mContext, UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId()) != null;
     }
 
diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java
index f9a03d9..0d4a6a6 100644
--- a/src/com/android/settings/network/TetherPreferenceController.java
+++ b/src/com/android/settings/network/TetherPreferenceController.java
@@ -17,7 +17,7 @@
 
 import static android.os.UserManager.DISALLOW_CONFIG_TETHERING;
 
-import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced;
+import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfRestrictionEnforced;
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothPan;
diff --git a/src/com/android/settings/network/VpnPreferenceController.java b/src/com/android/settings/network/VpnPreferenceController.java
index 8ecd796..62589d5 100644
--- a/src/com/android/settings/network/VpnPreferenceController.java
+++ b/src/com/android/settings/network/VpnPreferenceController.java
@@ -40,7 +40,7 @@
 import com.android.internal.net.VpnConfig;
 import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
@@ -92,7 +92,7 @@
 
     @Override
     public boolean isAvailable() {
-        return !RestrictedLockUtils.hasBaseUserRestriction(mContext,
+        return !RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
                 UserManager.DISALLOW_CONFIG_VPN, UserHandle.myUserId());
     }
 
diff --git a/src/com/android/settings/nfc/AndroidBeam.java b/src/com/android/settings/nfc/AndroidBeam.java
index efa6041..2b7f872 100644
--- a/src/com/android/settings/nfc/AndroidBeam.java
+++ b/src/com/android/settings/nfc/AndroidBeam.java
@@ -38,7 +38,7 @@
 import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.HelpUtils;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 public class AndroidBeam extends InstrumentedFragment
         implements SwitchBar.OnSwitchChangeListener {
@@ -68,10 +68,10 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
                 getActivity(), UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId());
         final UserManager um = UserManager.get(getActivity());
-        mBeamDisallowedByBase = RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
+        mBeamDisallowedByBase = RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(),
                 UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId());
         if (!mBeamDisallowedByBase && admin != null) {
             new ActionDisabledByAdminDialogHelper(getActivity())
diff --git a/src/com/android/settings/nfc/AndroidBeamEnabler.java b/src/com/android/settings/nfc/AndroidBeamEnabler.java
index 1808775..4dda2fd 100644
--- a/src/com/android/settings/nfc/AndroidBeamEnabler.java
+++ b/src/com/android/settings/nfc/AndroidBeamEnabler.java
@@ -22,7 +22,7 @@
 import android.os.UserManager;
 
 import com.android.settings.R;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 
 /**
@@ -36,7 +36,7 @@
     public AndroidBeamEnabler(Context context, RestrictedPreference preference) {
         super(context);
         mPreference = preference;
-        mBeamDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(context,
+        mBeamDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
                 UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId());
         if (!isNfcAvailable()) {
             // NFC is not supported
diff --git a/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java b/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
index d708edf..1563bc4 100644
--- a/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
+++ b/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
@@ -41,6 +41,7 @@
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
@@ -246,7 +247,7 @@
     private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
             CharSequence entryValue, int keyguardNotificationFeatures) {
         RestrictedLockUtils.EnforcedAdmin admin =
-                RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                         mContext, keyguardNotificationFeatures, UserHandle.myUserId());
         if (admin != null && mLockscreen != null) {
             RestrictedListPreference.RestrictedItem item =
@@ -255,7 +256,7 @@
         }
         if (mProfileUserId != UserHandle.USER_NULL) {
             RestrictedLockUtils.EnforcedAdmin profileAdmin =
-                    RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                    RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                             mContext, keyguardNotificationFeatures, mProfileUserId);
             if (profileAdmin != null && mLockscreenProfile != null) {
                 RestrictedListPreference.RestrictedItem item =
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index 01f1228..03b4ec3 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -78,6 +78,12 @@
         return row;
     }
 
+    public boolean isBlockable(Context context, ApplicationInfo info) {
+        final boolean blocked = getNotificationsBanned(info.packageName, info.uid);
+        final boolean systemApp = isSystemApp(context, info);
+        return !systemApp || (systemApp && blocked);
+    }
+
     public AppRow loadAppRow(Context context, PackageManager pm, PackageInfo app) {
         final AppRow row = loadAppRow(context, pm, app.applicationInfo);
         recordCanBeBlocked(context, pm, app, row);
diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java
index a645c4b..ed0b123 100644
--- a/src/com/android/settings/notification/NotificationSettingsBase.java
+++ b/src/com/android/settings/notification/NotificationSettingsBase.java
@@ -51,7 +51,7 @@
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.widget.MasterCheckBoxPreference;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -112,19 +112,22 @@
 
         mPkgInfo = findPackageInfo(mPkg, mUid);
 
-        mUserId = UserHandle.getUserId(mUid);
-        mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
-                mContext, mPkg, mUserId);
+        if (mPkgInfo != null) {
+            mUserId = UserHandle.getUserId(mUid);
+            mSuspendedAppsAdmin = RestrictedLockUtilsInternal.checkIfApplicationIsSuspended(
+                    mContext, mPkg, mUserId);
 
-        loadChannel();
-        loadAppRow();
-        loadChannelGroup();
-        collectConfigActivities();
 
-        getSettingsLifecycle().addObserver(use(HeaderPreferenceController.class));
+            loadChannel();
+            loadAppRow();
+            loadChannelGroup();
+            collectConfigActivities();
 
-        for (NotificationPreferenceController controller : mControllers) {
-            controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
+            getSettingsLifecycle().addObserver(use(HeaderPreferenceController.class));
+
+            for (NotificationPreferenceController controller : mControllers) {
+                controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
+            }
         }
     }
 
diff --git a/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java b/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java
index a027aec..bbc01f5 100644
--- a/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java
+++ b/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java
@@ -82,17 +82,6 @@
     private Preference mSeeAllPref;
     private Preference mDivider;
 
-    static {
-        SKIP_SYSTEM_PACKAGES.addAll(Arrays.asList(
-                "android",
-                "com.android.phone",
-                "com.android.settings",
-                "com.android.systemui",
-                "com.android.providers.calendar",
-                "com.android.providers.media"
-        ));
-    }
-
     public RecentNotifyingAppsPreferenceController(Context context, NotificationBackend backend,
             Application app, Fragment host) {
         this(context, backend, app == null ? null : ApplicationsState.getInstance(app), host);
@@ -226,6 +215,7 @@
                     .setSourceMetricsCategory(
                             MetricsProto.MetricsEvent.MANAGE_APPLICATIONS_NOTIFICATIONS)
                     .toIntent());
+            pref.setEnabled(mNotificationBackend.isBlockable(mContext, appEntry.info));
             pref.setOnPreferenceChangeListener((preference, newValue) -> {
                 boolean blocked = !(Boolean) newValue;
                 mNotificationBackend.setNotificationsEnabledForPackage(
@@ -272,10 +262,6 @@
      * Whether or not the app should be included in recent list.
      */
     private boolean shouldIncludePkgInRecents(String pkgName) {
-         if (SKIP_SYSTEM_PACKAGES.contains(pkgName)) {
-            Log.d(TAG, "System package, skipping " + pkgName);
-            return false;
-        }
         final Intent launchIntent = new Intent().addCategory(Intent.CATEGORY_LAUNCHER)
                 .setPackage(pkgName);
 
diff --git a/src/com/android/settings/notification/RedactionInterstitial.java b/src/com/android/settings/notification/RedactionInterstitial.java
index 517c041..32dc52d 100644
--- a/src/com/android/settings/notification/RedactionInterstitial.java
+++ b/src/com/android/settings/notification/RedactionInterstitial.java
@@ -47,6 +47,7 @@
 import com.android.settings.SetupWizardUtils;
 import com.android.settings.Utils;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 public class RedactionInterstitial extends SettingsActivity {
 
@@ -160,7 +161,7 @@
 
         private void checkNotificationFeaturesAndSetDisabled(RestrictedRadioButton button,
                 int keyguardNotifications) {
-            EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+            EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                     getActivity(), keyguardNotifications, mUserId);
             button.setDisabledByAdmin(admin);
         }
diff --git a/src/com/android/settings/notification/VisibilityPreferenceController.java b/src/com/android/settings/notification/VisibilityPreferenceController.java
index 578a6c3..fe036e9 100644
--- a/src/com/android/settings/notification/VisibilityPreferenceController.java
+++ b/src/com/android/settings/notification/VisibilityPreferenceController.java
@@ -33,6 +33,7 @@
 import com.android.settings.RestrictedListPreference;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.util.ArrayList;
 
@@ -128,7 +129,7 @@
     private void setRestrictedIfNotificationFeaturesDisabled(RestrictedListPreference pref,
             CharSequence entry, CharSequence entryValue, int keyguardNotificationFeatures) {
         RestrictedLockUtils.EnforcedAdmin admin =
-                RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                         mContext, keyguardNotificationFeatures, mAppRow.userId);
         if (admin != null) {
             RestrictedListPreference.RestrictedItem item =
diff --git a/src/com/android/settings/overlay/SupportFeatureProvider.java b/src/com/android/settings/overlay/SupportFeatureProvider.java
index a9b66d6..b22b458 100644
--- a/src/com/android/settings/overlay/SupportFeatureProvider.java
+++ b/src/com/android/settings/overlay/SupportFeatureProvider.java
@@ -16,55 +16,17 @@
 
 package com.android.settings.overlay;
 
-import android.accounts.Account;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
 import android.app.Activity;
-import android.content.Context;
-
-import com.android.settings.support.SupportPhone;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 
 /**
  * Feature provider for support tab.
  */
 public interface SupportFeatureProvider {
 
-    @IntDef({SupportType.EMAIL, SupportType.PHONE, SupportType.CHAT})
-    @Retention(RetentionPolicy.SOURCE)
-    @interface SupportType {
-        int EMAIL = 1;
-        int PHONE = 2;
-        int CHAT = 3;
-    }
-
     /**
-     * Refreshes all operation rules.
-     */
-    void refreshOperationRules();
-
-    /**
-     * Returns the current country code if it has a operation config, otherwise returns null.
-     */
-    String getCurrentCountryCodeIfHasConfig(@SupportType int type);
-
-    /**
-     * Returns a support phone for specified country.
-     */
-    SupportPhone getSupportPhones(String countryCode, boolean isTollfree);
-
-    /**
-     * Returns array of {@link Account} that's eligible for support options.
-     */
-    @NonNull
-    Account[] getSupportEligibleAccounts(Context context);
-
-    /**
-     * Starts support v2, invokes the support home page. Will no-op if support v2 is not enabled.
+     * Starts support, invokes the support home page.
      *
      * @param activity Calling activity.
      */
-    void startSupportV2(Activity activity);
+    void startSupport(Activity activity);
 }
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 6edacda..df2d3cd 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -64,8 +64,8 @@
 import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settings.search.SearchFeatureProvider;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 
 import java.util.List;
@@ -562,7 +562,7 @@
             final PreferenceScreen entries = getPreferenceScreen();
 
             int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
-            EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
+            EnforcedAdmin enforcedAdmin = RestrictedLockUtilsInternal.checkIfPasswordQualityIsSet(
                     getActivity(), mUserId);
 
             for (ScreenLockType lock : ScreenLockType.values()) {
@@ -813,7 +813,7 @@
         // TODO: figure out how to eliminate duplicated code. It's a bit hard due to the async-ness
         private void removeAllFaceForUserAndFinish(final int userId, RemovalTracker tracker) {
             if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
-                if (mFaceManager.hasEnrolledFaces(userId)) {
+                if (mFaceManager.hasEnrolledTemplates(userId)) {
                     mFaceManager.setActiveUser(userId);
                     Face face = new Face(null, 0, 0);
                     mFaceManager.remove(face, userId,
diff --git a/src/com/android/settings/password/SetNewPasswordController.java b/src/com/android/settings/password/SetNewPasswordController.java
index f3bcedc..d5641cd 100644
--- a/src/com/android/settings/password/SetNewPasswordController.java
+++ b/src/com/android/settings/password/SetNewPasswordController.java
@@ -115,7 +115,7 @@
         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)
                 && mFaceManager != null
                 && mFaceManager.isHardwareDetected()
-                && !mFaceManager.hasEnrolledFaces(mTargetUserId)
+                && !mFaceManager.hasEnrolledTemplates(mTargetUserId)
                 && !isFaceDisabledByAdmin()) {
             extras = getFaceChooseLockExtras();
         } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 6744a7b..c19ccef 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -21,7 +21,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.widget.Toolbar;
+import android.view.View;
 
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.search.SearchIndexableResources;
@@ -55,11 +55,11 @@
     /**
      * Initializes the search toolbar.
      */
-    default void initSearchToolbar(Activity activity, Toolbar toolbar) {
-        if (activity == null || toolbar == null) {
+    default void initSearchToolbar(Activity activity, View view) {
+        if (activity == null || view == null) {
             return;
         }
-        toolbar.setOnClickListener(tb -> {
+        view.setOnClickListener(tb -> {
             final Intent intent = SEARCH_UI_INTENT;
             intent.setPackage(getSettingsIntelligencePkgName());
 
diff --git a/src/com/android/settings/security/ChangeScreenLockPreferenceController.java b/src/com/android/settings/security/ChangeScreenLockPreferenceController.java
index ae857ce..a58c528 100644
--- a/src/com/android/settings/security/ChangeScreenLockPreferenceController.java
+++ b/src/com/android/settings/security/ChangeScreenLockPreferenceController.java
@@ -36,6 +36,7 @@
 import com.android.settings.security.screenlock.ScreenLockSettings;
 import com.android.settings.widget.GearPreference;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 
@@ -170,7 +171,7 @@
      * DO or PO installed in the user may disallow to change password.
      */
     void disableIfPasswordQualityManaged(int userId) {
-        final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtils
+        final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtilsInternal
                 .checkIfPasswordQualityIsSet(mContext, userId);
         final DevicePolicyManager dpm = (DevicePolicyManager) mContext
                 .getSystemService(Context.DEVICE_POLICY_SERVICE);
diff --git a/src/com/android/settings/security/LockUnificationPreferenceController.java b/src/com/android/settings/security/LockUnificationPreferenceController.java
index 71be0ae..1aebe24 100644
--- a/src/com/android/settings/security/LockUnificationPreferenceController.java
+++ b/src/com/android/settings/security/LockUnificationPreferenceController.java
@@ -39,7 +39,7 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.password.ChooseLockGeneric;
 import com.android.settings.password.ChooseLockSettingsHelper;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 
@@ -136,8 +136,9 @@
                     mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileUserId);
             mUnifyProfile.setChecked(!separate);
             if (separate) {
-                mUnifyProfile.setDisabledByAdmin(RestrictedLockUtils.checkIfRestrictionEnforced(
-                        mContext, UserManager.DISALLOW_UNIFIED_PASSWORD, mProfileUserId));
+                mUnifyProfile.setDisabledByAdmin(RestrictedLockUtilsInternal
+                        .checkIfRestrictionEnforced(mContext, UserManager.DISALLOW_UNIFIED_PASSWORD,
+                                mProfileUserId));
             }
         }
     }
diff --git a/src/com/android/settings/security/OwnerInfoPreferenceController.java b/src/com/android/settings/security/OwnerInfoPreferenceController.java
index 226e887..f7a20ba 100644
--- a/src/com/android/settings/security/OwnerInfoPreferenceController.java
+++ b/src/com/android/settings/security/OwnerInfoPreferenceController.java
@@ -27,8 +27,8 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.users.OwnerInfoSettings;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -140,6 +140,6 @@
 
     @VisibleForTesting
     EnforcedAdmin getDeviceOwner() {
-        return RestrictedLockUtils.getDeviceOwner(mContext);
+        return RestrictedLockUtilsInternal.getDeviceOwner(mContext);
     }
 }
diff --git a/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java b/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
index a003d3b..999c945 100644
--- a/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
+++ b/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
@@ -34,6 +34,7 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.security.trustagent.TrustAgentManager;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 public class LockAfterTimeoutPreferenceController extends AbstractPreferenceController
@@ -106,7 +107,7 @@
         preference.setValue(String.valueOf(currentTimeout));
         if (mDPM != null) {
             final RestrictedLockUtils.EnforcedAdmin admin =
-                    RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext);
+                    RestrictedLockUtilsInternal.checkIfMaximumTimeToLockIsSet(mContext);
             final long adminTimeout =
                     mDPM.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId());
             final long displayTimeout = Math.max(0,
diff --git a/src/com/android/settings/security/trustagent/TrustAgentManager.java b/src/com/android/settings/security/trustagent/TrustAgentManager.java
index feac9fa..e039db8 100644
--- a/src/com/android/settings/security/trustagent/TrustAgentManager.java
+++ b/src/com/android/settings/security/trustagent/TrustAgentManager.java
@@ -39,6 +39,7 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -113,7 +114,7 @@
         final List<ResolveInfo> resolveInfos = pm.queryIntentServices(TRUST_AGENT_INTENT,
                 PackageManager.GET_META_DATA);
         final List<ComponentName> enabledTrustAgents = utils.getEnabledTrustAgents(myUserId);
-        final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtils
+        final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtilsInternal
                 .checkIfKeyguardFeaturesDisabled(
                         context, DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS, myUserId);
 
diff --git a/src/com/android/settings/security/trustagent/TrustAgentsPreferenceController.java b/src/com/android/settings/security/trustagent/TrustAgentsPreferenceController.java
index 5088d31..4268839 100644
--- a/src/com/android/settings/security/trustagent/TrustAgentsPreferenceController.java
+++ b/src/com/android/settings/security/trustagent/TrustAgentsPreferenceController.java
@@ -40,7 +40,7 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.security.SecurityFeatureProvider;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -97,8 +97,8 @@
         loadActiveAgents();
         removeUselessExistingPreferences();
 
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(mContext,
-                DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS, UserHandle.myUserId());
+        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
+                mContext, DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS, UserHandle.myUserId());
 
         for (TrustAgentInfo agent : mAvailableAgents.values()) {
             final ComponentName componentName = agent.getComponentName();
diff --git a/src/com/android/settings/support/SupportDashboardActivity.java b/src/com/android/settings/support/SupportDashboardActivity.java
index ed7e76c..245810a 100644
--- a/src/com/android/settings/support/SupportDashboardActivity.java
+++ b/src/com/android/settings/support/SupportDashboardActivity.java
@@ -43,9 +43,9 @@
         SupportFeatureProvider supportFeatureProvider = FeatureFactory.getFactory(this)
                 .getSupportFeatureProvider(this);
 
-        // try to launch support v2 if we have the feature provider
+        // try to launch support if we have the feature provider
         if (supportFeatureProvider != null) {
-          supportFeatureProvider.startSupportV2(this);
+          supportFeatureProvider.startSupport(this);
           finish();
         }
     }
diff --git a/src/com/android/settings/support/SupportPhone.java b/src/com/android/settings/support/SupportPhone.java
deleted file mode 100644
index d27dca5..0000000
--- a/src/com/android/settings/support/SupportPhone.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2016 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.settings.support;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.text.ParseException;
-
-/**
- * Data model for a support phone number.
- */
-public final class SupportPhone implements Parcelable {
-
-    public final String language;
-    public final String number;
-    public final boolean isTollFree;
-
-    public SupportPhone(String config) throws ParseException {
-        // Config follows this format: language:[tollfree|tolled]:number
-        final String[] tokens = config.split(":");
-        if (tokens.length != 3) {
-            throw new ParseException("Phone config is invalid " + config, 0);
-        }
-        language = tokens[0];
-        isTollFree = TextUtils.equals(tokens[1], "tollfree");
-        number = tokens[2];
-    }
-
-    protected SupportPhone(Parcel in) {
-        language = in.readString();
-        number = in.readString();
-        isTollFree = in.readInt() != 0;
-    }
-
-    public Intent getDialIntent() {
-        return new Intent(Intent.ACTION_DIAL)
-                .setData(new Uri.Builder()
-                        .scheme("tel")
-                        .appendPath(number)
-                        .build());
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(language);
-        dest.writeString(number);
-        dest.writeInt(isTollFree ? 1 : 0);
-    }
-
-    public static final Creator<SupportPhone> CREATOR = new Creator<SupportPhone>() {
-        @Override
-        public SupportPhone createFromParcel(Parcel in) {
-            return new SupportPhone(in);
-        }
-
-        @Override
-        public SupportPhone[] newArray(int size) {
-            return new SupportPhone[size];
-        }
-    };
-}
diff --git a/src/com/android/settings/users/EditUserPhotoController.java b/src/com/android/settings/users/EditUserPhotoController.java
index f7d7e86..3253f79 100644
--- a/src/com/android/settings/users/EditUserPhotoController.java
+++ b/src/com/android/settings/users/EditUserPhotoController.java
@@ -53,6 +53,7 @@
 
 import com.android.settings.R;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.drawable.CircleFramedDrawable;
 
 import libcore.io.Streams;
@@ -419,9 +420,9 @@
             mAction = action;
 
             final int myUserId = UserHandle.myUserId();
-            mAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(context,
+            mAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
                     restriction, myUserId);
-            mIsRestrictedByBase = RestrictedLockUtils.hasBaseUserRestriction(mContext,
+            mIsRestrictedByBase = RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
                     restriction, myUserId);
         }
 
diff --git a/src/com/android/settings/users/UserCapabilities.java b/src/com/android/settings/users/UserCapabilities.java
index b9a2228..473c9c5 100644
--- a/src/com/android/settings/users/UserCapabilities.java
+++ b/src/com/android/settings/users/UserCapabilities.java
@@ -25,6 +25,7 @@
 
 import com.android.settings.Utils;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 public class UserCapabilities {
     boolean mEnabled = true;
@@ -67,9 +68,9 @@
     public void updateAddUserCapabilities(Context context) {
         final UserManager userManager =
                 (UserManager) context.getSystemService(Context.USER_SERVICE);
-        mEnforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(context,
+        mEnforcedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
                 UserManager.DISALLOW_ADD_USER, UserHandle.myUserId());
-        final boolean hasBaseUserRestriction = RestrictedLockUtils.hasBaseUserRestriction(
+        final boolean hasBaseUserRestriction = RestrictedLockUtilsInternal.hasBaseUserRestriction(
                 context, UserManager.DISALLOW_ADD_USER, UserHandle.myUserId());
         mDisallowAddUserSetByAdmin = mEnforcedAdmin != null && !hasBaseUserRestriction;
         mDisallowAddUser = (mEnforcedAdmin != null || hasBaseUserRestriction);
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 65868e9..99d3ca4 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -31,7 +31,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.util.List;
 
@@ -105,7 +105,7 @@
             mPhonePref.setChecked(
                     !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
         }
-        if (RestrictedLockUtils.hasBaseUserRestriction(context,
+        if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
                 UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
             removePreference(KEY_REMOVE_USER);
         }
diff --git a/src/com/android/settings/users/UserPreference.java b/src/com/android/settings/users/UserPreference.java
index bcc0167..d87d78e 100644
--- a/src/com/android/settings/users/UserPreference.java
+++ b/src/com/android/settings/users/UserPreference.java
@@ -28,7 +28,7 @@
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 
 import java.util.Comparator;
@@ -142,7 +142,7 @@
 
     private boolean canDeleteUser() {
         return mDeleteClickListener != null
-                && !RestrictedLockUtils.hasBaseUserRestriction(getContext(),
+                && !RestrictedLockUtilsInternal.hasBaseUserRestriction(getContext(),
                 UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
     }
 
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 89e9a67..6e3174d 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -72,6 +72,7 @@
 import com.android.settings.widget.SwitchBarController;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.drawable.CircleFramedDrawable;
 import com.android.settingslib.search.SearchIndexable;
@@ -912,7 +913,7 @@
             if (mUserCaps.mDisallowAddUser) {
                 pref.setDisabledByAdmin(mUserCaps.mEnforcedAdmin);
             } else if (mUserCaps.mDisallowSwitchUser) {
-                pref.setDisabledByAdmin(RestrictedLockUtils.getDeviceOwner(context));
+                pref.setDisabledByAdmin(RestrictedLockUtilsInternal.getDeviceOwner(context));
             } else {
                 pref.setDisabledByAdmin(null);
             }
@@ -963,7 +964,8 @@
                 mAddUserWhenLockedPreferenceController.getPreferenceKey());
         mAddUserWhenLockedPreferenceController.updateState(addUserOnLockScreen);
         mMultiUserFooterPreferenceController.updateState(null /* preference */);
-        mAddUser.setVisible(mUserCaps.mUserSwitcherEnabled);
+        mAddUser.setVisible(mUserCaps.mCanAddUser && Utils.isDeviceProvisioned(context)
+                && mUserCaps.mUserSwitcherEnabled);
         mUserListCategory.setVisible(mUserCaps.mUserSwitcherEnabled);
         if (!mUserCaps.mUserSwitcherEnabled) {
             return;
@@ -1090,7 +1092,7 @@
             switch (v.getId()) {
                 case UserPreference.DELETE_ID:
                     final EnforcedAdmin removeDisallowedAdmin =
-                            RestrictedLockUtils.checkIfRestrictionEnforced(getContext(),
+                            RestrictedLockUtilsInternal.checkIfRestrictionEnforced(getContext(),
                                     UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
                     if (removeDisallowedAdmin != null) {
                         RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
diff --git a/src/com/android/settings/utils/ManagedServiceSettings.java b/src/com/android/settings/utils/ManagedServiceSettings.java
index 6ee5e8e..e5dfb06 100644
--- a/src/com/android/settings/utils/ManagedServiceSettings.java
+++ b/src/com/android/settings/utils/ManagedServiceSettings.java
@@ -32,11 +32,6 @@
 import android.util.Log;
 import android.view.View;
 
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.Fragment;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.Utils;
@@ -47,6 +42,11 @@
 
 import java.util.List;
 
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
 public abstract class ManagedServiceSettings extends EmptyTextSettings {
     private static final String TAG = "ManagedServiceSettings";
     private final Config mConfig;
@@ -117,12 +117,12 @@
             CharSequence title = null;
             try {
                 title = mPm.getApplicationInfoAsUser(
-                        service.packageName, 0, getCurrentUser(managedProfileId)).loadLabel(mPm);
+                        service.packageName, 0, UserHandle.myUserId()).loadLabel(mPm);
             } catch (PackageManager.NameNotFoundException e) {
                 // unlikely, as we are iterating over live services.
                 Log.e(TAG, "can't find package name", e);
             }
-            final String finalTitle = title.toString();
+            final CharSequence finalTitle = title;
             final String summary = service.loadLabel(mPm).toString();
             final SwitchPreference pref = new AppSwitchPreference(getPrefContext());
             pref.setPersistent(false);
@@ -143,7 +143,11 @@
             }
             pref.setOnPreferenceChangeListener((preference, newValue) -> {
                 final boolean enable = (boolean) newValue;
-                return setEnabled(cn, finalTitle, enable);
+                if (finalTitle != null) {
+                    return setEnabled(cn, finalTitle.toString(), enable);
+                } else {
+                    return setEnabled(cn, null, enable);
+                }
             });
             pref.setKey(cn.flattenToString());
             screen.addPreference(pref);
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index dafa7ec..ed36da8 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -63,7 +63,7 @@
 import com.android.settings.RestrictedSettingsFragment;
 import com.android.settings.widget.GearPreference;
 import com.android.settings.widget.GearPreference.OnGearClickListener;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import com.google.android.collect.Lists;
 
@@ -143,7 +143,7 @@
         // Disable all actions if VPN configuration has been disallowed
         for (int i = 0; i < menu.size(); i++) {
             if (isUiRestrictedByOnlyAdmin()) {
-                RestrictedLockUtils.setMenuItemAsDisabledByAdmin(getPrefContext(),
+                RestrictedLockUtilsInternal.setMenuItemAsDisabledByAdmin(getPrefContext(),
                         menu.getItem(i), getRestrictionEnforcedAdmin());
             } else {
                 menu.getItem(i).setEnabled(!mUnavailable);
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index de67c10..2e6611f 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -465,8 +465,7 @@
         } else {
             enabled = ipAndProxyFieldsAreValid();
         }
-        if (mEapCaCertSpinner != null
-                && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) {
+        if (mAccessPointSecurity == AccessPoint.SECURITY_EAP) {
             String caCertSelection = (String) mEapCaCertSpinner.getSelectedItem();
             if (caCertSelection.equals(mUnspecifiedCertString)) {
                 // Disallow submit if the user has not selected a CA certificate for an EAP network
@@ -482,10 +481,8 @@
                 enabled = false;
             }
         }
-        if (mEapUserCertSpinner != null
-                && mView.findViewById(R.id.l_user_cert).getVisibility() != View.GONE
-                && ((String) mEapUserCertSpinner.getSelectedItem())
-                       .equals(mUnspecifiedCertString)) {
+        if (mAccessPointSecurity == AccessPoint.SECURITY_EAP
+                && mEapUserCertSpinner.getSelectedItem().equals(mUnspecifiedCertString)) {
             // Disallow submit if the user has not selected a user certificate for an EAP network
             // configuration.
             enabled = false;
diff --git a/src/com/android/settings/wifi/WifiDialog.java b/src/com/android/settings/wifi/WifiDialog.java
index f1df7e4..2b8fb2d 100644
--- a/src/com/android/settings/wifi/WifiDialog.java
+++ b/src/com/android/settings/wifi/WifiDialog.java
@@ -26,6 +26,7 @@
 
 import com.android.settings.R;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.wifi.AccessPoint;
 
 public class WifiDialog extends AlertDialog implements WifiConfigUiBase,
@@ -117,7 +118,7 @@
                 case BUTTON_FORGET:
                     if (WifiUtils.isNetworkLockedDown(getContext(), mAccessPoint.getConfig())) {
                         RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
-                                RestrictedLockUtils.getDeviceOwner(getContext()));
+                                RestrictedLockUtilsInternal.getDeviceOwner(getContext()));
                         return;
                     }
                     mListener.onForget(this);
diff --git a/src/com/android/settings/wifi/WifiEnabler.java b/src/com/android/settings/wifi/WifiEnabler.java
index 8efefc3..60480c2 100644
--- a/src/com/android/settings/wifi/WifiEnabler.java
+++ b/src/com/android/settings/wifi/WifiEnabler.java
@@ -35,8 +35,8 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.widget.SwitchWidgetController;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.WirelessUtils;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
@@ -162,12 +162,12 @@
                 mSwitchWidget.setEnabled(true);
         }
 
-        if (RestrictedLockUtils.hasBaseUserRestriction(mContext,
+        if (RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
                 UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId())) {
             mSwitchWidget.setEnabled(false);
         } else {
-            final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
-                UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId());
+            final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+                    mContext, UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId());
             mSwitchWidget.setDisabledByAdmin(admin);
         }
     }
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index d23cf46..12ca26a 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -67,6 +67,7 @@
 import com.android.settings.widget.SwitchBarController;
 import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.settingslib.wifi.AccessPoint.AccessPointListener;
@@ -578,7 +579,7 @@
             WifiConfiguration config = accessPoint.getConfig();
             if (WifiUtils.isNetworkLockedDown(getActivity(), config) && accessPoint.isActive()) {
                 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(),
-                        RestrictedLockUtils.getDeviceOwner(getActivity()));
+                        RestrictedLockUtilsInternal.getDeviceOwner(getActivity()));
                 return;
             }
         }
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index d114e06..c29ad60 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -35,6 +35,7 @@
 import com.android.settings.wifi.WifiConfigUiBase;
 import com.android.settings.wifi.WifiDialog;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.wifi.AccessPoint;
 
@@ -108,7 +109,7 @@
             case Menu.FIRST:
                 if (!mWifiDetailPreferenceController.canModifyNetwork()) {
                     RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
-                            RestrictedLockUtils.getDeviceOwner(getContext()));
+                            RestrictedLockUtilsInternal.getDeviceOwner(getContext()));
                 } else {
                     showDialog(WIFI_DIALOG_ID);
                 }
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 1a7b289..1ed50c9 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -29,6 +29,7 @@
 com.android.settings.bluetooth.DevicePickerFragment
 com.android.settings.datausage.AppDataUsage
 com.android.settings.datausage.DataUsageList
+com.android.settings.datausage.DataUsageListV2
 com.android.settings.datetime.timezone.TimeZoneSettings
 com.android.settings.deviceinfo.PrivateVolumeSettings
 com.android.settings.deviceinfo.PublicVolumeSettings
diff --git a/tests/robotests/assets/grandfather_not_in_search_index_provider_registry b/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
index af663f4..64e0a01 100644
--- a/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
+++ b/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
@@ -1,3 +1,3 @@
-com.android.settings.accessibility.FontSizePreferenceFragmentForSetupWizard
+com.android.settings.display.FontSizePreferenceFragmentForSetupWizard
 com.android.settings.display.ScreenZoomPreferenceFragmentForSetupWizard
 com.android.settings.search.FakeSettingsFragment
diff --git a/tests/robotests/config/robolectric.properties b/tests/robotests/config/robolectric.properties
index d213eec..aae2779 100644
--- a/tests/robotests/config/robolectric.properties
+++ b/tests/robotests/config/robolectric.properties
@@ -1,3 +1,6 @@
 manifest=packages/apps/Settings/AndroidManifest.xml
 sdk=NEWEST_SDK
-shadows=com.android.settings.testutils.shadow.ShadowThreadUtils
\ No newline at end of file
+
+shadows=\
+   com.android.settings.testutils.shadow.ShadowThreadUtils,\
+   com.android.settingslib.testutils.shadow.ShadowXmlUtils
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 2488882..6347d79 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -63,6 +63,9 @@
     <bool name="config_disable_uninstall_update">true</bool>
     <bool name="config_show_device_name">false</bool>
 
+    <!-- Whether or not extra preview panels should be used for screen zoom setting. -->
+    <bool name="config_enable_extra_screen_zoom_preview">false</bool>
+
     <!-- List of a11y components on the device allowed to be enabled by Settings Slices -->
     <string-array name="config_settings_slices_accessibility_components" translatable="false">
         <item>fake_package/fake_service</item>
@@ -72,5 +75,4 @@
     <string-array name="slice_whitelist_package_names" translatable="false">
         <item>com.android.settings.slice_whitelist_package</item>
     </string-array>
-
 </resources>
diff --git a/tests/robotests/res/values/themes.xml b/tests/robotests/res/values/themes.xml
index 9a247f6..d3ba69f 100644
--- a/tests/robotests/res/values/themes.xml
+++ b/tests/robotests/res/values/themes.xml
@@ -6,5 +6,14 @@
 
     <!-- Override the main app's style for ActionPrimaryButton to get around lack of new style
          support in robolectric  -->
-    <style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button" />
+    <style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button"/>
+
+    <!-- Test version of Theme.Settings.Home. Needed to build homepage activity in Robolectric -->
+    <style name="Theme.Settings.Home" parent="Theme.AppCompat.DayNight.NoActionBar">
+        <item name="colorPrimary">#ffffff</item>
+        <item name="colorPrimaryDark">#ffffff</item>
+        <item name="colorAccent">#ffffff</item>
+        <item name="preferenceTheme">@style/PreferenceTheme</item>
+        <item name="android:windowLightStatusBar">true</item>
+    </style>
 </resources>
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index 723978f..409512e 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -73,10 +73,11 @@
         Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 0);
         final Intent intent = new Intent(mContext, Settings.class);
         final SettingsActivity activity =
-            Robolectric.buildActivity(SettingsActivity.class, intent).create(Bundle.EMPTY).get();
+                Robolectric.buildActivity(SettingsActivity.class, intent).create(
+                        Bundle.EMPTY).get();
 
         assertThat(activity.findViewById(R.id.search_bar).getVisibility())
-            .isEqualTo(View.INVISIBLE);
+                .isEqualTo(View.INVISIBLE);
     }
 
     @Test
@@ -84,7 +85,8 @@
         Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
         final Intent intent = new Intent(mContext, Settings.class);
         final SettingsActivity activity =
-            Robolectric.buildActivity(SettingsActivity.class, intent).create(Bundle.EMPTY).get();
+                Robolectric.buildActivity(SettingsActivity.class, intent).create(
+                        Bundle.EMPTY).get();
 
         assertThat(activity.findViewById(R.id.search_bar).getVisibility()).isEqualTo(View.VISIBLE);
     }
@@ -92,6 +94,7 @@
     @Test
     public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash() {
         when(mActivity.getSupportFragmentManager()).thenReturn(mFragmentManager);
+        doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver();
         when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
 
         doReturn(RuntimeEnvironment.application.getClassLoader()).when(mActivity).getClassLoader();
diff --git a/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
index 2fa233c..22c2cdb 100644
--- a/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
@@ -41,7 +41,7 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowAccountManager;
 import com.android.settings.testutils.shadow.ShadowContentResolver;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 
 import org.junit.After;
 import org.junit.Before;
@@ -54,7 +54,7 @@
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class,
-        ShadowRestrictedLockUtils.class})
+        ShadowRestrictedLockUtilsInternal.class})
 public class ChooseAccountPreferenceControllerTest {
 
     private Context mContext;
@@ -77,7 +77,7 @@
     public void tearDown() {
         ShadowContentResolver.reset();
         ShadowAccountManager.resetAuthenticator();
-        ShadowRestrictedLockUtils.clearDisabledTypes();
+        ShadowRestrictedLockUtilsInternal.clearDisabledTypes();
     }
 
     @Test
@@ -115,9 +115,9 @@
                 true /* supportsUploading */)};
         ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
 
-        ShadowRestrictedLockUtils.setHasSystemFeature(true);
-        ShadowRestrictedLockUtils.setDevicePolicyManager(mock(DevicePolicyManager.class));
-        ShadowRestrictedLockUtils.setDisabledTypes(new String[] {"test_type"});
+        ShadowRestrictedLockUtilsInternal.setHasSystemFeature(true);
+        ShadowRestrictedLockUtilsInternal.setDevicePolicyManager(mock(DevicePolicyManager.class));
+        ShadowRestrictedLockUtilsInternal.setDisabledTypes(new String[] {"test_type"});
 
         doReturn("label").when(mController).getLabelForType(anyString());
 
@@ -140,9 +140,9 @@
                 true /* supportsUploading */)};
         ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
 
-        ShadowRestrictedLockUtils.setHasSystemFeature(true);
-        ShadowRestrictedLockUtils.setDevicePolicyManager(mock(DevicePolicyManager.class));
-        ShadowRestrictedLockUtils.setDisabledTypes(new String[] {"com.acct1"});
+        ShadowRestrictedLockUtilsInternal.setHasSystemFeature(true);
+        ShadowRestrictedLockUtilsInternal.setDevicePolicyManager(mock(DevicePolicyManager.class));
+        ShadowRestrictedLockUtilsInternal.setDisabledTypes(new String[] {"com.acct1"});
 
         doReturn("label").when(mController).getLabelForType(anyString());
 
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppInfoDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppInfoDashboardFragmentTest.java
index b6bb9b5..539e75f 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppInfoDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppInfoDashboardFragmentTest.java
@@ -170,7 +170,7 @@
     }
 
     @Test
-    public void launchFragment_hasNoPackageInfo_shouldFinish() {
+    public void ensurePackageInfoAvailable_hasNoPackageInfo_shouldFinish() {
         ReflectionHelpers.setField(mFragment, "mPackageInfo", null);
 
         assertThat(mFragment.ensurePackageInfoAvailable(mActivity)).isFalse();
@@ -178,7 +178,7 @@
     }
 
     @Test
-    public void launchFragment_hasPackageInfo_shouldReturnTrue() {
+    public void ensurePackageInfoAvailable_hasPackageInfo_shouldReturnTrue() {
         final PackageInfo packageInfo = mock(PackageInfo.class);
         ReflectionHelpers.setField(mFragment, "mPackageInfo", packageInfo);
 
@@ -187,6 +187,16 @@
     }
 
     @Test
+    public void createPreference_hasNoPackageInfo_shouldSkip() {
+        ReflectionHelpers.setField(mFragment, "mPackageInfo", null);
+
+        mFragment.onCreatePreferences(new Bundle(), "root_key");
+
+        verify(mActivity).finishAndRemoveTask();
+        verify(mFragment, never()).getPreferenceScreen();
+    }
+
+    @Test
     public void packageSizeChange_isOtherPackage_shouldNotRefreshUi() {
         ReflectionHelpers.setField(mFragment, "mPackageName", PACKAGE_NAME);
         mFragment.onPackageSizeChanged("Not_" + PACKAGE_NAME);
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
index 0ef1cf3..4a482d0 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
@@ -18,9 +18,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -133,8 +133,11 @@
     @Test
     public void isBrowserDefault_onlyApp_shouldReturnTrue() {
         when(mPackageManager.getDefaultBrowserPackageNameAsUser(anyInt())).thenReturn(null);
+        final List<ResolveInfo> resolveInfos = new ArrayList<>();
+        final String PACKAGE_ONE = "pkg";
+        resolveInfos.add(createResolveInfo(PACKAGE_ONE));
         when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
-                .thenReturn(Collections.singletonList(new ResolveInfo()));
+            .thenReturn(resolveInfos);
 
         assertThat(mController.isBrowserDefault("pkg", 0)).isTrue();
     }
@@ -161,6 +164,15 @@
         assertThat(defaultBrowserInfo.size()).isEqualTo(2);
     }
 
+    @Test
+    public void getCandidates_shouldQueryActivityWithFlagsEquals0() {
+
+        mController.getCandidates(mPackageManager, 0 /* userId */);
+
+        verify(mPackageManager).queryIntentActivitiesAsUser(
+            any(Intent.class), eq(0) /* flags */, eq(0) /* userId */);
+    }
+
     private ResolveInfo createResolveInfo(String packageName) {
         final ResolveInfo info = new ResolveInfo();
         info.handleAllWebDataURI = true;
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceStatusPreferenceControllerTest.java
index d223099..9907da0 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceStatusPreferenceControllerTest.java
@@ -121,7 +121,7 @@
         when(mFaceManager.isHardwareDetected()).thenReturn(true);
         when(mFaceManager.getEnrolledFaces(anyInt()))
                 .thenReturn(Collections.singletonList(mock(Face.class)));
-        when(mFaceManager.hasEnrolledFaces(anyInt()))
+        when(mFaceManager.hasEnrolledTemplates(anyInt()))
                 .thenReturn(true);
 
         mController.updateState(mPreference);
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 261fac3..01fa32f 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -40,7 +40,7 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.AppItem;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -58,7 +58,7 @@
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtils.class})
+@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
 public class AppDataUsageTest {
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -163,7 +163,7 @@
         ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
         ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager);
 
-        ShadowRestrictedLockUtils.setRestricted(true);
+        ShadowRestrictedLockUtilsInternal.setRestricted(true);
         doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager)
                 .getUidPolicy(testUid);
 
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
index 0140d6f..acd00fd 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
@@ -31,10 +31,12 @@
 import android.provider.Settings;
 
 import androidx.fragment.app.FragmentActivity;
+import androidx.preference.PreferenceManager;
 
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settingslib.NetworkPolicyEditor;
+import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -68,7 +70,11 @@
 
     @Test
     public void resumePause_shouldListenUnlistenDataStateChange() {
-        mDataUsageList.onAttach(mContext);
+        ReflectionHelpers.setField(
+                mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
+        ReflectionHelpers.setField(
+                mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
+
         mDataUsageList.onResume();
 
         verify(mListener).setListener(true, mDataUsageList.mSubId, mContext);
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java
new file mode 100644
index 0000000..9eb8003
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java
@@ -0,0 +1,114 @@
+/*
+ * 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.settings.datausage;
+
+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.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.NetworkPolicyEditor;
+import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.util.ReflectionHelpers;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.PreferenceManager;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class DataUsageListV2Test {
+
+    @Mock
+    private CellDataPreference.DataStateListener mListener;
+    @Mock
+    private TemplatePreference.NetworkServices mNetworkServices;
+    @Mock
+    private Context mContext;
+    private DataUsageListV2 mDataUsageList;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest();
+        mNetworkServices.mPolicyEditor = mock(NetworkPolicyEditor.class);
+        mDataUsageList = spy(DataUsageListV2.class);
+
+        doReturn(mContext).when(mDataUsageList).getContext();
+        ReflectionHelpers.setField(mDataUsageList, "mDataStateListener", mListener);
+        ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
+    }
+
+    @Test
+    public void resumePause_shouldListenUnlistenDataStateChange() {
+        ReflectionHelpers.setField(
+                mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
+        ReflectionHelpers.setField(
+                mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
+
+        mDataUsageList.onResume();
+
+        verify(mListener).setListener(true, mDataUsageList.mSubId, mContext);
+
+        mDataUsageList.onPause();
+
+        verify(mListener).setListener(false, mDataUsageList.mSubId, mContext);
+    }
+
+    @Test
+    public void processArgument_shouldGetTemplateFromArgument() {
+        final Bundle args = new Bundle();
+        args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
+        args.putInt(DataUsageListV2.EXTRA_SUB_ID, 3);
+        mDataUsageList.setArguments(args);
+
+        mDataUsageList.processArgument();
+
+        assertThat(mDataUsageList.mTemplate).isNotNull();
+        assertThat(mDataUsageList.mSubId).isEqualTo(3);
+    }
+
+    @Test
+    public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
+        final FragmentActivity activity = mock(FragmentActivity.class);
+        final Intent intent = new Intent();
+        intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
+        intent.putExtra(Settings.EXTRA_SUB_ID, 3);
+        when(activity.getIntent()).thenReturn(intent);
+        doReturn(activity).when(mDataUsageList).getActivity();
+
+        mDataUsageList.processArgument();
+
+        assertThat(mDataUsageList.mTemplate).isNotNull();
+        assertThat(mDataUsageList.mSubId).isEqualTo(3);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceControllerTest.java
index b357630..983b96d 100644
--- a/tests/robotests/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceControllerTest.java
@@ -43,6 +43,7 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 
@@ -61,6 +62,7 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {
         ShadowRestrictedLockUtils.class,
+        ShadowRestrictedLockUtilsInternal.class,
         UnrestrictedDataAccessPreferenceControllerTest.ShadowAppStateBaseBridge.class
 })
 public class UnrestrictedDataAccessPreferenceControllerTest {
@@ -127,7 +129,7 @@
 
         final String testPkg1 = "com.example.one";
         final String testPkg2 = "com.example.two";
-        ShadowRestrictedLockUtils.setRestrictedPkgs(testPkg2);
+        ShadowRestrictedLockUtilsInternal.setRestrictedPkgs(testPkg2);
 
         doAnswer((invocation) -> {
             final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/DeviceNamePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/DeviceNamePreferenceControllerTest.java
index 4ee7f41..8662c7f 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/DeviceNamePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/DeviceNamePreferenceControllerTest.java
@@ -114,7 +114,7 @@
 
     @Test
     public void setDeviceName_preferenceUpdatedWhenDeviceNameUpdated() {
-        forceAcceptDeviceName();
+        acceptDeviceName(true);
         mController.displayPreference(mScreen);
         mController.onPreferenceChange(mPreference, TESTING_STRING);
 
@@ -123,7 +123,7 @@
 
     @Test
     public void setDeviceName_bluetoothNameUpdatedWhenDeviceNameUpdated() {
-        forceAcceptDeviceName();
+        acceptDeviceName(true);
         mController.displayPreference(mScreen);
         mController.onPreferenceChange(mPreference, TESTING_STRING);
 
@@ -132,7 +132,7 @@
 
     @Test
     public void setDeviceName_wifiTetherNameUpdatedWhenDeviceNameUpdated() {
-        forceAcceptDeviceName();
+        acceptDeviceName(true);
         mController.displayPreference(mScreen);
         mController.onPreferenceChange(mPreference, TESTING_STRING);
 
@@ -150,21 +150,39 @@
 
     @Test
     public void setDeviceName_ignoresIfCancelPressed() {
-        forceAcceptDeviceName();
+        acceptDeviceName(true);
         mController.displayPreference(mScreen);
         mController.onPreferenceChange(mPreference, TESTING_STRING);
 
         assertThat(mBluetoothAdapter.getName()).isEqualTo(TESTING_STRING);
     }
 
-    private void forceAcceptDeviceName() {
+    @Test
+    public void setDeviceName_okInDeviceNameWarningDialog_shouldChangePreferenceText() {
+        acceptDeviceName(true);
+        mController.displayPreference(mScreen);
+        mController.onPreferenceChange(mPreference, TESTING_STRING);
+
+        assertThat(mPreference.getSummary()).isEqualTo(TESTING_STRING);
+    }
+
+    @Test
+    public void setDeviceName_cancelInDeviceNameWarningDialog_shouldNotChangePreferenceText() {
+        acceptDeviceName(false);
+        mController.displayPreference(mScreen);
+        mController.onPreferenceChange(mPreference, TESTING_STRING);
+
+        assertThat(mPreference.getSummary()).isNotEqualTo(TESTING_STRING);
+        assertThat(mPreference.getText()).isEqualTo(mPreference.getSummary());
+    }
+
+    private void acceptDeviceName(boolean accept) {
         mController.setHost(
                 new DeviceNamePreferenceController.DeviceNamePreferenceHost() {
                     @Override
                     public void showDeviceNameWarningDialog(String deviceName) {
-                        mController.confirmDeviceName();
+                        mController.updateDeviceName(accept);
                     }
                 });
     }
-
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/deviceinfo/DeviceNameWarningDialogTest.java b/tests/robotests/src/com/android/settings/deviceinfo/deviceinfo/DeviceNameWarningDialogTest.java
index e28e6ec..9e1400b 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/deviceinfo/DeviceNameWarningDialogTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/deviceinfo/DeviceNameWarningDialogTest.java
@@ -30,7 +30,7 @@
         fragmentController.create().start().resume();
         fragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
 
-        verify(deviceInfoFragment).onSetDeviceNameConfirm();
+        verify(deviceInfoFragment).onSetDeviceNameConfirm(true);
     }
 
     @Test
@@ -43,6 +43,6 @@
         fragmentController.create().start().resume();
         fragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
 
-        verify(deviceInfoFragment, never()).onSetDeviceNameConfirm();
+        verify(deviceInfoFragment).onSetDeviceNameConfirm(false);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/display/ScreenZoomSettingsTest.java b/tests/robotests/src/com/android/settings/display/ScreenZoomSettingsTest.java
new file mode 100644
index 0000000..0822076
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/display/ScreenZoomSettingsTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.settings.display;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ScreenZoomSettingsTest {
+
+    private ScreenZoomSettings mSettings;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mSettings = spy(new ScreenZoomSettings());
+        doReturn(mContext).when(mSettings).getContext();
+    }
+
+    @Test
+    public void getPreviewSampleResIds_default_return3Previews() {
+        assertThat(mSettings.getPreviewSampleResIds()).hasLength(3);
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void getPreviewSampleResIds_extraPreviewDisabled_return1Preview() {
+        assertThat(mSettings.getPreviewSampleResIds()).hasLength(1);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
index e0a504a..f6f0d7f 100644
--- a/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
@@ -34,7 +34,7 @@
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import org.junit.After;
@@ -78,7 +78,7 @@
 
     @After
     public void tearDown() {
-          ShadowRestrictedLockUtils.reset();
+          ShadowRestrictedLockUtilsInternal.reset();
     }
 
     @Test
@@ -139,13 +139,13 @@
     }
 
     @Test
-    @Config(shadows = ShadowRestrictedLockUtils.class)
+    @Config(shadows = ShadowRestrictedLockUtilsInternal.class)
     public void updateState_selectedTimeoutLargerThanAdminMax_shouldSetSummaryToUpdatedPrefValue() {
         final int profileUserId = UserHandle.myUserId();
         final long allowedTimeout = 480000L; // 8 minutes
         when(mUserManager.getProfiles(profileUserId)).thenReturn(Collections.emptyList());
         ShadowDevicePolicyManager.getShadow().setMaximumTimeToLock(profileUserId, allowedTimeout);
-        ShadowRestrictedLockUtils.setMaximumTimeToLockIsSet(true);
+        ShadowRestrictedLockUtilsInternal.setMaximumTimeToLockIsSet(true);
         final CharSequence[] timeouts = {"15000", "30000", "60000", "120000", "300000", "600000"};
         final CharSequence[] summaries = {"15s", "30s", "1m", "2m", "5m", "10m"};
         // set current timeout to be 10 minutes, which is longer than the allowed 8 minutes
diff --git a/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
index 5321c10..9b138a6 100644
--- a/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
@@ -124,10 +124,6 @@
         assertEquals(Shadows.shadowOf(textView).innerText(),
                 mActivity.getString(R.string.disabled_by_policy_title_screen_capture));
 
-        mHelper.setAdminSupportTitle(view, DevicePolicyManager.POLICY_MANDATORY_BACKUPS);
-        assertEquals(Shadows.shadowOf(textView).innerText(),
-                mActivity.getString(R.string.disabled_by_policy_title_turn_off_backups));
-
         mHelper.setAdminSupportTitle(view, DevicePolicyManager.POLICY_SUSPEND_PACKAGES);
         assertEquals(Shadows.shadowOf(textView).innerText(),
                 mActivity.getString(R.string.disabled_by_policy_title_suspend_packages));
diff --git a/tests/robotests/src/com/android/settings/enterprise/BackupsEnabledPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/BackupsEnabledPreferenceControllerTest.java
deleted file mode 100644
index 4e6db05..0000000
--- a/tests/robotests/src/com/android/settings/enterprise/BackupsEnabledPreferenceControllerTest.java
+++ /dev/null
@@ -1,73 +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.settings.enterprise;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-
-import androidx.preference.Preference;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class BackupsEnabledPreferenceControllerTest {
-
-    private static final String KEY_BACKUPS_ENABLED = "backups_enabled";
-
-    private Context mContext;
-    private FakeFeatureFactory mFeatureFactory;
-
-    private BackupsEnabledPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        mFeatureFactory = FakeFeatureFactory.setupForTest();
-        mController = new BackupsEnabledPreferenceController(mContext);
-    }
-
-    @Test
-    public void testIsAvailable() {
-        when(mFeatureFactory.enterprisePrivacyFeatureProvider.areBackupsMandatory())
-                .thenReturn(false);
-        assertThat(mController.isAvailable()).isFalse();
-
-        when(mFeatureFactory.enterprisePrivacyFeatureProvider.areBackupsMandatory())
-                .thenReturn(true);
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void testHandlePreferenceTreeClick() {
-        assertThat(mController.handlePreferenceTreeClick(new Preference(mContext, null, 0, 0)))
-                .isFalse();
-    }
-
-    @Test
-    public void testGetPreferenceKey() {
-        assertThat(mController.getPreferenceKey()).isEqualTo(KEY_BACKUPS_ENABLED);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
index a7bd329..92c420a 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
@@ -346,15 +346,6 @@
                 .isEqualTo(3);
     }
 
-    @Test
-    public void testAreBackupsMandatory() {
-        assertThat(mProvider.areBackupsMandatory()).isFalse();
-        ComponentName transportComponent = new ComponentName("test", "test");
-        when(mDevicePolicyManager.getMandatoryBackupTransport())
-                .thenReturn(transportComponent);
-        assertThat(mProvider.areBackupsMandatory()).isTrue();
-    }
-
     private void resetAndInitializePackageManager() {
         reset(mPackageManager);
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
index d37738d..f1d03c7 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
@@ -99,7 +99,7 @@
 
     private void verifyPreferenceControllers(List<AbstractPreferenceController> controllers) {
         assertThat(controllers).isNotNull();
-        assertThat(controllers.size()).isEqualTo(18);
+        assertThat(controllers.size()).isEqualTo(17);
         int position = 0;
         assertThat(controllers.get(position++)).isInstanceOf(NetworkLogsPreferenceController.class);
         assertThat(controllers.get(position++)).isInstanceOf(BugReportsPreferenceController.class);
@@ -127,8 +127,6 @@
         assertThat(controllers.get(position++)).isInstanceOf(
                 CaCertsManagedProfilePreferenceController.class);
         assertThat(controllers.get(position++)).isInstanceOf(
-                BackupsEnabledPreferenceController.class);
-        assertThat(controllers.get(position++)).isInstanceOf(
                 PreferenceCategoryController.class);
         assertThat(controllers.get(position++)).isInstanceOf(
                 FailedPasswordWipeCurrentUserPreferenceController.class);
diff --git a/tests/robotests/src/com/android/settings/homepage/CardContentProviderTest.java b/tests/robotests/src/com/android/settings/homepage/CardContentProviderTest.java
index eec87b0..84955e2 100644
--- a/tests/robotests/src/com/android/settings/homepage/CardContentProviderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/CardContentProviderTest.java
@@ -72,16 +72,25 @@
 
     @Test
     public void cardData_insert() {
-        final int cnt_before_instert = getRowCount();
-        mResolver.insert(mUri, insertOneRow());
-        final int cnt_after_instert = getRowCount();
+        final int rowsBeforeInsert = getRowCount();
+        mResolver.insert(mUri, generateOneRow());
+        final int rowsAfterInsert = getRowCount();
 
-        assertThat(cnt_after_instert - cnt_before_instert).isEqualTo(1);
+        assertThat(rowsAfterInsert - rowsBeforeInsert).isEqualTo(1);
+    }
+
+    @Test
+    public void cardData_bulkInsert_twoRows() {
+        final int rowsBeforeInsert = getRowCount();
+        mResolver.bulkInsert(mUri, generateTwoRows());
+        final int rowsAfterInsert = getRowCount();
+
+        assertThat(rowsAfterInsert - rowsBeforeInsert).isEqualTo(2);
     }
 
     @Test
     public void cardData_query() {
-        mResolver.insert(mUri, insertOneRow());
+        mResolver.insert(mUri, generateOneRow());
         final int count = getRowCount();
 
         assertThat(count).isGreaterThan(0);
@@ -89,24 +98,24 @@
 
     @Test
     public void cardData_delete() {
-        mResolver.insert(mUri, insertOneRow());
-        final int del_count = mResolver.delete(mUri, null, null);
+        mResolver.insert(mUri, generateOneRow());
+        final int delCount = mResolver.delete(mUri, null, null);
 
-        assertThat(del_count).isGreaterThan(0);
+        assertThat(delCount).isGreaterThan(0);
     }
 
     @Test
     public void cardData_update() {
-        mResolver.insert(mUri, insertOneRow());
+        mResolver.insert(mUri, generateOneRow());
 
         final double updatingScore = 0.87;
         final ContentValues values = new ContentValues();
         values.put(CardDatabaseHelper.CardColumns.SCORE, updatingScore);
         final String strWhere = CardDatabaseHelper.CardColumns.NAME + "=?";
         final String[] selectionArgs = {"auto_rotate"};
-        final int update_count = mResolver.update(mUri, values, strWhere, selectionArgs);
+        final int updateCount = mResolver.update(mUri, values, strWhere, selectionArgs);
 
-        assertThat(update_count).isGreaterThan(0);
+        assertThat(updateCount).isGreaterThan(0);
 
         final String[] columns = {CardDatabaseHelper.CardColumns.SCORE};
         final Cursor cr = mResolver.query(mUri, columns, strWhere, selectionArgs, null);
@@ -122,7 +131,7 @@
         ShadowThreadUtils.setIsMainThread(true);
         ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
 
-        mProvider.insert(mUri, insertOneRow());
+        mProvider.insert(mUri, generateOneRow());
 
         verify(mProvider).enableStrictMode();
     }
@@ -164,7 +173,7 @@
         ShadowThreadUtils.setIsMainThread(false);
         ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
 
-        mProvider.insert(mUri, insertOneRow());
+        mProvider.insert(mUri, generateOneRow());
 
         verify(mProvider, never()).enableStrictMode();
     }
@@ -217,10 +226,10 @@
         mProvider.getTableFromMatch(invalid_Uri);
     }
 
-    private ContentValues insertOneRow() {
+    private ContentValues generateOneRow() {
         final ContentValues values = new ContentValues();
         values.put(CardDatabaseHelper.CardColumns.NAME, "auto_rotate");
-        values.put(CardDatabaseHelper.CardColumns.TYPE, 0);
+        values.put(CardDatabaseHelper.CardColumns.TYPE, 1);
         values.put(CardDatabaseHelper.CardColumns.SCORE, 0.9);
         values.put(CardDatabaseHelper.CardColumns.SLICE_URI,
                 "content://com.android.settings.slices/action/auto_rotate");
@@ -231,6 +240,24 @@
         return values;
     }
 
+    private ContentValues[] generateTwoRows() {
+        final ContentValues[] twoRows = new ContentValues[2];
+        twoRows[0] = generateOneRow();
+
+        final ContentValues values = new ContentValues();
+        values.put(CardDatabaseHelper.CardColumns.NAME, "toggle_airplane");
+        values.put(CardDatabaseHelper.CardColumns.TYPE, 1);
+        values.put(CardDatabaseHelper.CardColumns.SCORE, 0.95);
+        values.put(CardDatabaseHelper.CardColumns.SLICE_URI,
+                "content://com.android.settings.slices/action/toggle_airplane");
+        values.put(CardDatabaseHelper.CardColumns.CATEGORY, 2);
+        values.put(CardDatabaseHelper.CardColumns.PACKAGE_NAME, "com.android.settings");
+        values.put(CardDatabaseHelper.CardColumns.APP_VERSION, "1.0.0");
+        twoRows[1] = values;
+
+        return twoRows;
+    }
+
     private int getRowCount() {
         final Cursor cr = mResolver.query(mUri, null, null, null);
         final int count = cr.getCount();
diff --git a/tests/robotests/src/com/android/settings/homepage/ConditionalContextualCardTest.java b/tests/robotests/src/com/android/settings/homepage/ConditionalContextualCardTest.java
new file mode 100644
index 0000000..ced8b06
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/ConditionalContextualCardTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.settings.homepage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.settings.homepage.conditional.ConditionalContextualCard;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ConditionalContextualCardTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void newInstance_changeCardType_shouldCrash() {
+        new ConditionalContextualCard.Builder()
+                .setCardType(ContextualCard.CardType.SUGGESTION)
+                .build();
+    }
+
+    @Test
+    public void getCardType_shouldAlwaysBeConditional() {
+        assertThat(new ConditionalContextualCard.Builder().build().getCardType())
+                .isEqualTo(ContextualCard.CardType.CONDITIONAL);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
new file mode 100644
index 0000000..4b237a0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.settings.homepage;
+
+import static com.android.settings.homepage.SettingsHomepageActivity.PERSONAL_SETTINGS_TAG;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.util.FeatureFlagUtils;
+
+import androidx.fragment.app.Fragment;
+
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SettingsHomepageActivityTest {
+
+    private Context mContext;
+    private SettingsHomepageActivity mActivity;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DYNAMIC_HOMEPAGE, true);
+    }
+
+    @Test
+    public void launchHomepage_shouldOpenPersonalSettings() {
+        mActivity = Robolectric.setupActivity(SettingsHomepageActivity.class);
+        final Fragment fragment = mActivity.getSupportFragmentManager()
+                .findFragmentByTag(PERSONAL_SETTINGS_TAG);
+
+        assertThat(fragment).isInstanceOf(PersonalSettingsFragment.class);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardControllerTest.java
new file mode 100644
index 0000000..a59a3bc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardControllerTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.settings.homepage.conditional;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+import com.android.settings.R;
+import com.android.settings.homepage.ContextualCardUpdateListener;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ConditionContextualCardControllerTest {
+
+    @Mock
+    private ConditionManager mConditionManager;
+    @Mock
+    private ContextualCardUpdateListener mListener;
+    private Context mContext;
+    private ConditionContextualCardController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mController = spy(new ConditionContextualCardController(mContext));
+        ReflectionHelpers.setField(mController, "mConditionManager", mConditionManager);
+    }
+
+    @Test
+    public void onStart_shouldStartMonitoring() {
+        mController.onStart();
+
+        verify(mConditionManager).startMonitoringStateChange();
+    }
+
+    @Test
+    public void onStop_shouldStopMonitoring() {
+        mController.onStop();
+
+        verify(mConditionManager).stopMonitoringStateChange();
+    }
+
+    @Test
+    public void onConditionsChanged_listenerIsSet_shouldUpdateData() {
+        final FakeConditionalCard fakeConditionalCard = new FakeConditionalCard(mContext);
+        final List<ConditionalCard> conditionalCards = new ArrayList<>();
+        conditionalCards.add(fakeConditionalCard);
+        when(mConditionManager.getDisplayableCards()).thenReturn(conditionalCards);
+        mController.setCardUpdateListener(mListener);
+
+        mController.onConditionsChanged();
+
+        verify(mListener).onContextualCardUpdated(any());
+    }
+
+    @Test
+    public void onConditionsChanged_listenerNotSet_shouldNotUpdateData() {
+        final FakeConditionalCard fakeConditionalCard = new FakeConditionalCard(mContext);
+        final List<ConditionalCard> conditionalCards = new ArrayList<>();
+        conditionalCards.add(fakeConditionalCard);
+        when(mConditionManager.getDisplayableCards()).thenReturn(conditionalCards);
+
+        mController.onConditionsChanged();
+
+        verify(mListener, never()).onContextualCardUpdated(any());
+    }
+
+    private class FakeConditionalCard implements ConditionalCard {
+
+        private final Context mContext;
+
+        public FakeConditionalCard(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public long getId() {
+            return 100;
+        }
+
+        @Override
+        public CharSequence getActionText() {
+            return "action_text_test";
+        }
+
+        @Override
+        public int getMetricsConstant() {
+            return 1;
+        }
+
+        @Override
+        public Drawable getIcon() {
+            return mContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp);
+        }
+
+        @Override
+        public CharSequence getTitle() {
+            return "title_text_test";
+        }
+
+        @Override
+        public CharSequence getSummary() {
+            return "summary_text_test";
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardRendererTest.java
new file mode 100644
index 0000000..dc56a7f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionContextualCardRendererTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.settings.homepage.conditional;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.settings.R;
+import com.android.settings.homepage.ContextualCard;
+import com.android.settings.homepage.ControllerRendererPool;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ConditionContextualCardRendererTest {
+
+    @Mock
+    private ControllerRendererPool mControllerRendererPool;
+    @Mock
+    private ConditionContextualCardController mController;
+    private Context mContext;
+    private ConditionContextualCardRenderer mRenderer;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mRenderer = new ConditionContextualCardRenderer(mContext, mControllerRendererPool);
+    }
+
+    @Test
+    public void bindView_shouldSetListener() {
+        final int viewType = mRenderer.getViewType();
+        final RecyclerView recyclerView = new RecyclerView(mContext);
+        recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
+        final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
+        final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view);
+        final View card = view.findViewById(R.id.content);
+        when(mControllerRendererPool.getController(mContext,
+                ContextualCard.CardType.CONDITIONAL)).thenReturn(mController);
+
+        mRenderer.bindView(viewHolder, buildConditionContextualCard());
+
+        assertThat(card).isNotNull();
+        assertThat(card.hasOnClickListeners()).isTrue();
+    }
+
+    @Test
+    public void viewClick_shouldInvokeControllerPrimaryClick() {
+        final int viewType = mRenderer.getViewType();
+        final RecyclerView recyclerView = new RecyclerView(mContext);
+        recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
+        final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
+        final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view);
+        final View card = view.findViewById(R.id.content);
+        when(mControllerRendererPool.getController(mContext,
+                ContextualCard.CardType.CONDITIONAL)).thenReturn(mController);
+
+        mRenderer.bindView(viewHolder, buildConditionContextualCard());
+
+        assertThat(card).isNotNull();
+        card.performClick();
+
+        verify(mController).onPrimaryClick(any(ContextualCard.class));
+    }
+
+    private ContextualCard buildConditionContextualCard() {
+        return new ConditionalContextualCard.Builder()
+                .setConditionId(123)
+                .setMetricsConstant(1)
+                .setActionText("test_action")
+                .setName("test_name")
+                .setTitleText("test_title")
+                .setSummaryText("test_summary")
+                .setIconDrawable(mContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp))
+                .setIsHalfWidth(true)
+                .build();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
index d6f86f9..469a537 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
@@ -79,7 +79,7 @@
         final SummaryLoader.SummaryProvider provider =
                 new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader,
                         wifiPreferenceController, mobileNetworkPreferenceController,
-                        tetherPreferenceController);
+                        tetherPreferenceController, () -> true);
 
         provider.setListening(false);
 
@@ -107,7 +107,7 @@
         final SummaryLoader.SummaryProvider provider =
                 new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader,
                         wifiPreferenceController, mobileNetworkPreferenceController,
-                        tetherPreferenceController);
+                        tetherPreferenceController, () -> true);
 
         provider.setListening(false);
 
@@ -121,4 +121,34 @@
 
         verify(summaryLoader).setSummary(provider, "Wi\u2011Fi and data usage");
     }
+
+    @Test
+    public void summaryProviderSetListening_noDataUsageActivity_shouldReturnNoDataUsageSummary() {
+        final WifiMasterSwitchPreferenceController wifiPreferenceController =
+                mock(WifiMasterSwitchPreferenceController.class);
+        final MobileNetworkPreferenceController mobileNetworkPreferenceController =
+                mock(MobileNetworkPreferenceController.class);
+        final TetherPreferenceController tetherPreferenceController =
+                mock(TetherPreferenceController.class);
+
+        final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+        final SummaryLoader.SummaryProvider provider =
+                new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader,
+                        wifiPreferenceController, mobileNetworkPreferenceController,
+                        tetherPreferenceController, () -> false);
+
+        provider.setListening(false);
+
+        verifyZeroInteractions(summaryLoader);
+
+        when(wifiPreferenceController.isAvailable()).thenReturn(true);
+        when(mobileNetworkPreferenceController.isAvailable()).thenReturn(true);
+        when(tetherPreferenceController.isAvailable()).thenReturn(true);
+
+        provider.setListening(true);
+
+        verify(summaryLoader).setSummary(provider, "Wi\u2011Fi, mobile, and hotspot");
+    }
+
+
 }
diff --git a/tests/robotests/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.java
index 22aaf2a..004e352 100644
--- a/tests/robotests/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.java
@@ -23,7 +23,7 @@
 import android.content.Context;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settings.wifi.WifiMasterSwitchPreferenceController;
 
 import org.junit.Before;
@@ -36,7 +36,7 @@
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = ShadowRestrictedLockUtils.class)
+@Config(shadows = ShadowRestrictedLockUtilsInternal.class)
 public class TopLevelNetworkEntryPreferenceControllerTest {
 
     @Mock
diff --git a/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java
index e3fc843..bf2c132 100644
--- a/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java
@@ -31,7 +31,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 
 import org.junit.Before;
@@ -69,7 +69,7 @@
         when(mContext.getApplicationContext()).thenReturn(mContext);
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
         when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mManager);
-        when(RestrictedLockUtils.hasBaseUserRestriction(mContext,
+        when(RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
                 UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId())).thenReturn(false);
         when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter);
 
@@ -104,7 +104,7 @@
     public void isBeamEnable_disAllowBeam_shouldReturnFalse() {
         when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF);
 
-        when(RestrictedLockUtils.hasBaseUserRestriction(mContext,
+        when(RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
                 UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId())).thenReturn(true);
         mAndroidBeamController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/notification/RecentNotifyingAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RecentNotifyingAppsPreferenceControllerTest.java
index cbc51a9..e222b20 100644
--- a/tests/robotests/src/com/android/settings/notification/RecentNotifyingAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RecentNotifyingAppsPreferenceControllerTest.java
@@ -189,9 +189,8 @@
         mController.displayPreference(mScreen);
 
         verify(mCategory).setTitle(R.string.recent_notifications);
-        // Only add app1. app2 is skipped because of the package name, app3 skipped because
-        // it's invalid app.
-        verify(mCategory, times(1)).addPreference(any(Preference.class));
+        // Only add app1 & app2. app3 skipped because it's invalid app.
+        verify(mCategory, times(2)).addPreference(any(Preference.class));
 
         verify(mSeeAllPref).setSummary(null);
         verify(mSeeAllPref).setIcon(R.drawable.ic_chevron_right_24dp);
@@ -247,35 +246,6 @@
     }
 
     @Test
-    public void display_hasRecentButNoneDisplayable_showAppInfo() {
-        final List<NotifyingApp> apps = new ArrayList<>();
-        final NotifyingApp app1 = new NotifyingApp()
-                .setPackage("com.android.phone")
-                .setLastNotified(System.currentTimeMillis());
-        final NotifyingApp app2 = new NotifyingApp()
-                .setPackage("com.android.settings")
-                .setLastNotified(System.currentTimeMillis());
-        apps.add(app1);
-        apps.add(app2);
-
-        // app1, app2 are not displayable
-        when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId()))
-                .thenReturn(mock(ApplicationsState.AppEntry.class));
-        when(mAppState.getEntry(app2.getPackage(), UserHandle.myUserId()))
-                .thenReturn(mock(ApplicationsState.AppEntry.class));
-        when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
-                new ResolveInfo());
-        when(mBackend.getRecentApps()).thenReturn(apps);
-
-        mController.displayPreference(mScreen);
-
-        verify(mCategory, never()).addPreference(any(Preference.class));
-        verify(mCategory).setTitle(null);
-        verify(mSeeAllPref).setTitle(R.string.notifications_title);
-        verify(mSeeAllPref).setIcon(null);
-    }
-
-    @Test
     public void display_showRecents_formatSummary() {
         final List<NotifyingApp> apps = new ArrayList<>();
         final NotifyingApp app1 = new NotifyingApp()
diff --git a/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java b/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
index 5b337de..b62495c 100644
--- a/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
@@ -22,7 +22,7 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
 import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settings.testutils.shadow.ShadowUtils;
 
@@ -39,7 +39,7 @@
         SettingsShadowResourcesImpl.class,
         SettingsShadowResources.SettingsShadowTheme.class,
         ShadowUtils.class,
-        ShadowRestrictedLockUtils.class,
+        ShadowRestrictedLockUtilsInternal.class,
         ShadowUserManager.class,
 })
 public class RedactionInterstitialTest {
@@ -49,7 +49,7 @@
     @After
     public void tearDown() {
         ShadowUserManager.getShadow().reset();
-        ShadowRestrictedLockUtils.reset();
+        ShadowRestrictedLockUtilsInternal.reset();
     }
 
     @Test
@@ -85,7 +85,7 @@
     @Test
     public void primaryUserUnredactedRestrictionTest() {
         setupSettings(1 /* show */, 1 /* showUnredacted */);
-        ShadowRestrictedLockUtils.setKeyguardDisabledFeatures(
+        ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(
                 KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
         setupActivity();
 
@@ -97,7 +97,7 @@
     @Test
     public void primaryUserNotificationRestrictionTest() {
         setupSettings(1 /* show */, 1 /* showUnredacted */);
-        ShadowRestrictedLockUtils.setKeyguardDisabledFeatures(
+        ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(
                 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
         setupActivity();
 
@@ -121,7 +121,7 @@
     public void managedProfileUnredactedRestrictionTest() {
         setupSettings(1 /* show */, 1 /* showUnredacted */);
         ShadowUserManager.getShadow().addManagedProfile(UserHandle.myUserId());
-        ShadowRestrictedLockUtils.setKeyguardDisabledFeatures(
+        ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(
                 KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
         setupActivity();
 
diff --git a/tests/robotests/src/com/android/settings/password/SetNewPasswordControllerTest.java b/tests/robotests/src/com/android/settings/password/SetNewPasswordControllerTest.java
index fa1c0f7..af77ad8 100644
--- a/tests/robotests/src/com/android/settings/password/SetNewPasswordControllerTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetNewPasswordControllerTest.java
@@ -113,7 +113,7 @@
         // GIVEN the device supports face.
         when(mFaceManager.isHardwareDetected()).thenReturn(true);
         // GIVEN there are no enrolled face.
-        when(mFaceManager.hasEnrolledFaces(CURRENT_USER_ID)).thenReturn(false);
+        when(mFaceManager.hasEnrolledTemplates(CURRENT_USER_ID)).thenReturn(false);
         // GIVEN DPC does not disallow face for keyguard usage.
         when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
                 .thenReturn(0);
@@ -180,7 +180,7 @@
         // GIVEN the device does NOT support face.
         when(mFaceManager.isHardwareDetected()).thenReturn(false);
         // GIVEN there are no enrolled face.
-        when(mFaceManager.hasEnrolledFaces(CURRENT_USER_ID)).thenReturn(false);
+        when(mFaceManager.hasEnrolledTemplates(CURRENT_USER_ID)).thenReturn(false);
         // GIVEN DPC does not disallow face for keyguard usage.
         when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
                 .thenReturn(0);
@@ -218,7 +218,7 @@
         // GIVEN the device supports face.
         when(mFaceManager.isHardwareDetected()).thenReturn(true);
         // GIVEN there are no enrolled face.
-        when(mFaceManager.hasEnrolledFaces(CURRENT_USER_ID)).thenReturn(true);
+        when(mFaceManager.hasEnrolledTemplates(CURRENT_USER_ID)).thenReturn(true);
         // GIVEN DPC does not disallow face for keyguard usage.
         when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
                 .thenReturn(0);
@@ -256,7 +256,7 @@
         // GIVEN the device supports face.
         when(mFaceManager.isHardwareDetected()).thenReturn(true);
         // GIVEN there is an enrolled face.
-        when(mFaceManager.hasEnrolledFaces(CURRENT_USER_ID)).thenReturn(true);
+        when(mFaceManager.hasEnrolledTemplates(CURRENT_USER_ID)).thenReturn(true);
         // GIVEN DPC disallows face for keyguard usage.
         when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(ComponentName.class)))
                 .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE);
diff --git a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
index f4d7a32..ede6a8f 100644
--- a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
@@ -35,7 +35,7 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
 import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 
 import org.junit.After;
@@ -55,7 +55,7 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {
         ShadowLockPatternUtils.class,
-        ShadowRestrictedLockUtils.class,
+        ShadowRestrictedLockUtilsInternal.class,
         ShadowDevicePolicyManager.class,
         ShadowApplicationPackageManager.class,
         TrustAgentsPreferenceControllerTest.ShadowTrustAgentManager.class
@@ -145,7 +145,7 @@
 
     @Test
     public void onStart_hasUnrestrictedTrustAgent_shouldAddThreeChangeablePreferences() {
-        ShadowRestrictedLockUtils.setKeyguardDisabledFeatures(0);
+        ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(0);
         final List<ResolveInfo> availableAgents = createFakeAvailableAgents();
         for (ResolveInfo rInfo : availableAgents) {
             ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo);
@@ -170,7 +170,7 @@
             ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo);
         }
         mPackageManager.addResolveInfoForIntent(TEST_INTENT, availableAgents);
-        ShadowRestrictedLockUtils.setKeyguardDisabledFeatures(
+        ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(
                 DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS);
 
         mController.displayPreference(mPreferenceScreen);
diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
index ad808fc..87f0a37 100644
--- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
+++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
@@ -76,6 +76,8 @@
             paths.add(new ResourcePath(null,
                 Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/res")), null));
             paths.add(new ResourcePath(null,
+                    Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/HelpUtils/res/")), null));
+            paths.add(new ResourcePath(null,
                 Fs.fromURL(new URL("file:frameworks/base/core/res/res")), null));
             paths.add(new ResourcePath(null,
                 Fs.fromURL(new URL("file:frameworks/opt/setupwizard/library/main/res")), null));
@@ -86,6 +88,8 @@
             paths.add(new ResourcePath(null,
                 Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat-nodeps/android_common/aar/res/")), null));
             paths.add(new ResourcePath(null,
+                Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/extras/material-design-x/com.google.android.material_material-nodeps/android_common/aar/res/")), null));
+            paths.add(new ResourcePath(null,
                 Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.cardview_cardview-nodeps/android_common/aar/res")), null));
         } catch (MalformedURLException e) {
             throw new RuntimeException("SettingsRobolectricTestRunner failure", e);
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtils.java
index d1cedec..c054656 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtils.java
@@ -15,99 +15,24 @@
  */
 package com.android.settings.testutils.shadow;
 
-import android.annotation.UserIdInt;
-import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 
-import com.android.internal.util.ArrayUtils;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.Resetter;
 
 @Implements(RestrictedLockUtils.class)
 public class ShadowRestrictedLockUtils {
 
-    private static boolean sIsRestricted;
     private static boolean sAdminSupportDetailsIntentLaunched;
-    private static boolean sHasSystemFeature;
-    private static boolean sMaximumTimeToLockIsSet;
-    private static String[] sRestrictedPkgs;
-    private static DevicePolicyManager sDevicePolicyManager;
-    private static String[] sDisabledTypes;
-    private static int sKeyguardDisabledFeatures;
-
-    @Resetter
-    public static void reset() {
-        sIsRestricted = false;
-        sRestrictedPkgs = null;
-        sAdminSupportDetailsIntentLaunched = false;
-        sKeyguardDisabledFeatures = 0;
-        sDisabledTypes = new String[0];
-        sMaximumTimeToLockIsSet = false;
-    }
-
-    @Implementation
-    public static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
-            String packageName, int userId) {
-        if (sIsRestricted) {
-            return new EnforcedAdmin();
-        }
-        if (ArrayUtils.contains(sRestrictedPkgs, packageName)) {
-            return new EnforcedAdmin();
-        }
-        return null;
-    }
 
     @Implementation
     public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
         sAdminSupportDetailsIntentLaunched = true;
     }
 
-    @Implementation
-    public static EnforcedAdmin checkIfAccountManagementDisabled(Context context,
-            String accountType, int userId) {
-        if (accountType == null) {
-            return null;
-        }
-        if (!sHasSystemFeature || sDevicePolicyManager == null) {
-            return null;
-        }
-        boolean isAccountTypeDisabled = false;
-        if (ArrayUtils.contains(sDisabledTypes, accountType)) {
-            isAccountTypeDisabled = true;
-        }
-        if (!isAccountTypeDisabled) {
-            return null;
-        }
-        return new EnforcedAdmin();
-    }
-
-    @Implementation
-    public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
-            int features, final @UserIdInt int userId) {
-        return (sKeyguardDisabledFeatures & features) == 0 ? null : new EnforcedAdmin();
-    }
-
-    @Implementation
-    public static boolean hasBaseUserRestriction(Context context,
-            String userRestriction, int userId) {
-        return sIsRestricted;
-    }
-
-    @Implementation
-    public static EnforcedAdmin checkIfRestrictionEnforced(Context context,
-            String userRestriction, int userId) {
-        return sIsRestricted ? new EnforcedAdmin() : null;
-    }
-
-    @Implementation
-    public static EnforcedAdmin checkIfMaximumTimeToLockIsSet(Context context) {
-        return sMaximumTimeToLockIsSet ? new EnforcedAdmin() : null;
-    }
-
     public static boolean hasAdminSupportDetailsIntentLaunched() {
         return sAdminSupportDetailsIntentLaunched;
     }
@@ -116,36 +41,5 @@
         sAdminSupportDetailsIntentLaunched = false;
     }
 
-    public static void setRestricted(boolean restricted) {
-        sIsRestricted = restricted;
-    }
-
-    public static void setRestrictedPkgs(String... pkgs) {
-        sRestrictedPkgs = pkgs;
-    }
-
-    public static void setHasSystemFeature(boolean hasSystemFeature) {
-        sHasSystemFeature = hasSystemFeature;
-    }
-
-    public static void setDevicePolicyManager(DevicePolicyManager dpm) {
-        sDevicePolicyManager = dpm;
-    }
-
-    public static void setDisabledTypes(String[] disabledTypes) {
-        sDisabledTypes = disabledTypes;
-    }
-
-    public static void clearDisabledTypes() {
-        sDisabledTypes = new String[0];
-    }
-
-    public static void setKeyguardDisabledFeatures(int features) {
-        sKeyguardDisabledFeatures = features;
-    }
-
-    public static void setMaximumTimeToLockIsSet(boolean isSet) {
-        sMaximumTimeToLockIsSet = isSet;
-    }
 
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java
new file mode 100644
index 0000000..1508431
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java
@@ -0,0 +1,136 @@
+/*
+ * 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.settings.testutils.shadow;
+
+import android.annotation.UserIdInt;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(RestrictedLockUtilsInternal.class)
+public class ShadowRestrictedLockUtilsInternal {
+
+    private static boolean sIsRestricted;
+    private static boolean sHasSystemFeature;
+    private static boolean sMaximumTimeToLockIsSet;
+    private static String[] sRestrictedPkgs;
+    private static DevicePolicyManager sDevicePolicyManager;
+    private static String[] sDisabledTypes;
+    private static int sKeyguardDisabledFeatures;
+
+    @Resetter
+    public static void reset() {
+        sIsRestricted = false;
+        sRestrictedPkgs = null;
+        sKeyguardDisabledFeatures = 0;
+        sDisabledTypes = new String[0];
+        sMaximumTimeToLockIsSet = false;
+    }
+
+    @Implementation
+    public static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
+            String packageName, int userId) {
+        if (sIsRestricted) {
+            return new EnforcedAdmin();
+        }
+        if (ArrayUtils.contains(sRestrictedPkgs, packageName)) {
+            return new EnforcedAdmin();
+        }
+        return null;
+    }
+
+    @Implementation
+    public static EnforcedAdmin checkIfAccountManagementDisabled(Context context,
+            String accountType, int userId) {
+        if (accountType == null) {
+            return null;
+        }
+        if (!sHasSystemFeature || sDevicePolicyManager == null) {
+            return null;
+        }
+        boolean isAccountTypeDisabled = false;
+        if (ArrayUtils.contains(sDisabledTypes, accountType)) {
+            isAccountTypeDisabled = true;
+        }
+        if (!isAccountTypeDisabled) {
+            return null;
+        }
+        return new EnforcedAdmin();
+    }
+
+    @Implementation
+    public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
+            int features, final @UserIdInt int userId) {
+        return (sKeyguardDisabledFeatures & features) == 0 ? null : new EnforcedAdmin();
+    }
+
+    @Implementation
+    public static boolean hasBaseUserRestriction(Context context,
+            String userRestriction, int userId) {
+        return sIsRestricted;
+    }
+
+    @Implementation
+    public static EnforcedAdmin checkIfRestrictionEnforced(Context context,
+            String userRestriction, int userId) {
+        return sIsRestricted ? new EnforcedAdmin() : null;
+    }
+
+    @Implementation
+    public static EnforcedAdmin checkIfMaximumTimeToLockIsSet(Context context) {
+        return sMaximumTimeToLockIsSet ? new EnforcedAdmin() : null;
+    }
+
+    public static void setRestricted(boolean restricted) {
+        sIsRestricted = restricted;
+    }
+
+    public static void setRestrictedPkgs(String... pkgs) {
+        sRestrictedPkgs = pkgs;
+    }
+
+    public static void setHasSystemFeature(boolean hasSystemFeature) {
+        sHasSystemFeature = hasSystemFeature;
+    }
+
+    public static void setDevicePolicyManager(DevicePolicyManager dpm) {
+        sDevicePolicyManager = dpm;
+    }
+
+    public static void setDisabledTypes(String[] disabledTypes) {
+        sDisabledTypes = disabledTypes;
+    }
+
+    public static void clearDisabledTypes() {
+        sDisabledTypes = new String[0];
+    }
+
+    public static void setKeyguardDisabledFeatures(int features) {
+        sKeyguardDisabledFeatures = features;
+    }
+
+    public static void setMaximumTimeToLockIsSet(boolean isSet) {
+        sMaximumTimeToLockIsSet = isSet;
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index 753d159..3266a7f 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -80,6 +80,15 @@
     }
 
     @Implementation
+    public int[] getProfileIds(@UserIdInt int userHandle, boolean enabledOnly) {
+        int[] ids = new int[mUserProfileInfos.size()];
+        for (int i = 0; i < mUserProfileInfos.size(); i++) {
+            ids[i] = mUserProfileInfos.get(i).id;
+        }
+        return ids;
+    }
+
+    @Implementation
     public int getCredentialOwnerProfile(@UserIdInt int userHandle) {
         return userHandle;
     }
diff --git a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
index 41f48c6..02c279e 100644
--- a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -184,4 +185,58 @@
 
         assertThat(addUser.isEnabled()).isFalse();
     }
+
+    @Test
+    public void updateUserList_cannotAddUserButCanSwitchUser_shouldNotShowAddUser() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+            Settings.Global.DEVICE_PROVISIONED, 1);
+        final RestrictedPreference addUser = mock(RestrictedPreference.class);
+
+        mUserCapabilities.mCanAddUser = false;
+        mUserCapabilities.mDisallowAddUser = true;
+        mUserCapabilities.mUserSwitcherEnabled = true;
+
+        ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
+        ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
+        ReflectionHelpers.setField(mFragment, "mDefaultIconDrawable", mDefaultIconDrawable);
+        ReflectionHelpers.setField(mFragment, "mAddingUser", false);
+        mFragment.mMePreference = mMePreference;
+        mFragment.mUserListCategory = mock(PreferenceCategory.class);
+        mFragment.mAddUser = addUser;
+
+        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+
+        mFragment.updateUserList();
+
+        verify(addUser, never()).setVisible(true);
+
+    }
+
+    @Test
+    public void updateUserList_canAddUserAndSwitchUser_shouldShowAddUser() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+            Settings.Global.DEVICE_PROVISIONED, 1);
+        final RestrictedPreference addUser = mock(RestrictedPreference.class);
+
+        mUserCapabilities.mCanAddUser = true;
+        mUserCapabilities.mDisallowAddUser = false;
+        mUserCapabilities.mUserSwitcherEnabled = true;
+
+        ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
+        ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
+        ReflectionHelpers.setField(mFragment, "mDefaultIconDrawable", mDefaultIconDrawable);
+        ReflectionHelpers.setField(mFragment, "mAddingUser", false);
+        mFragment.mMePreference = mMePreference;
+        mFragment.mUserListCategory = mock(PreferenceCategory.class);
+        mFragment.mAddUser = addUser;
+
+        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+        doReturn("Test summary").when(mFragment).getString(anyInt(), anyInt());
+
+        mFragment.updateUserList();
+
+        verify(addUser).setVisible(true);
+
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
index 5e8dd28..54be773 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
@@ -184,6 +184,22 @@
     }
 
     @Test
+    public void isSubmittable_EapToPskWithValidPassword_shouldReturnTrue() {
+        final TextView password = mView.findViewById(R.id.password);
+        final Spinner securitySpinner = mView.findViewById(R.id.security);
+        assertThat(password).isNotNull();
+        assertThat(securitySpinner).isNotNull();
+        when(mAccessPoint.isSaved()).thenReturn(true);
+
+        // Change it from EAP to PSK
+        mController.onItemSelected(securitySpinner, null, AccessPoint.SECURITY_EAP, 0);
+        mController.onItemSelected(securitySpinner, null, AccessPoint.SECURITY_PSK, 0);
+        password.setText(GOOD_PSK);
+
+        assertThat(mController.isSubmittable()).isTrue();
+    }
+
+    @Test
     public void getSignalString_notReachable_shouldHaveNoSignalString() {
         when(mAccessPoint.isReachable()).thenReturn(false);
 
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java
index 71a7298..53b3a64 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java
@@ -26,7 +26,7 @@
 import android.net.wifi.WifiManager;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settings.widget.SwitchWidgetController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
@@ -38,7 +38,7 @@
 import org.robolectric.annotation.Config;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = ShadowRestrictedLockUtils.class)
+@Config(shadows = ShadowRestrictedLockUtilsInternal.class)
 public class WifiEnablerTest {
 
     @Mock
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiMasterSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiMasterSwitchPreferenceControllerTest.java
index 06d3479..5aef036 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiMasterSwitchPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiMasterSwitchPreferenceControllerTest.java
@@ -37,7 +37,7 @@
 
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settings.widget.MasterSwitchPreference;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
@@ -50,7 +50,7 @@
 import org.robolectric.annotation.Config;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = ShadowRestrictedLockUtils.class)
+@Config(shadows = ShadowRestrictedLockUtilsInternal.class)
 public class WifiMasterSwitchPreferenceControllerTest {
 
     @Mock