Merge "Clarify text shown in a11y service warning dialog"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7689b11..7807f0e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -69,6 +69,7 @@
     <uses-permission android:name="android.permission.READ_PROFILE" />
     <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
     <uses-permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE" />
+    <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
     <uses-permission android:name="android.permission.SET_TIME" />
     <uses-permission android:name="android.permission.ACCESS_NOTIFICATIONS" />
     <uses-permission android:name="android.permission.REBOOT" />
@@ -114,6 +115,14 @@
         <uses-library android:name="org.apache.http.legacy" />
         <!-- Settings -->
 
+        <!-- TODO(b/118444000): Remove this. -->
+        <activity android:name="SettingsActivity"
+                  android:label="@string/settings_label_launcher"
+                  android:launchMode="singleTask">
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+        </activity>
+
         <activity android:name=".homepage.SettingsHomepageActivity"
                   android:label="@string/settings_label_launcher"
                   android:theme="@style/Theme.Settings.Home"
@@ -3036,7 +3045,14 @@
         </provider>
 
         <activity
-            android:name=".wifi.dpp.WifiDppConfiguratorActivity"/>
+            android:name=".wifi.dpp.WifiDppConfiguratorActivity">
+            <intent-filter>
+                <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER"/>
+                <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR"/>
+                <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
 
         <activity android:name=".homepage.contextualcards.ContextualCardFeedbackDialog"
                   android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
diff --git a/protos/contextual_card_list.proto b/protos/contextual_card_list.proto
index ea82408..3496c8c 100644
--- a/protos/contextual_card_list.proto
+++ b/protos/contextual_card_list.proto
@@ -28,4 +28,6 @@
   optional string cardName = 3;
 
   optional Category card_category = 4;
+
+  optional double card_score = 5;
 }
diff --git a/res/drawable/ic_find_in_page_24px.xml b/res/drawable/ic_find_in_page_24px.xml
new file mode 100644
index 0000000..18895e4
--- /dev/null
+++ b/res/drawable/ic_find_in_page_24px.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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorControlNormal">
+  <path
+      android:fillColor="#FFFFFFFF"
+      android:pathData="M6,2C4.9,2 4.01,2.9 4.01,4L4,20c0,1.1 0.89,2 1.99,2H18c1.1,0 2,-0.9 2,-2V8l-6,-6H6zM18,17.59l-2.2,-2.2c0.44,-0.69 0.7,-1.51 0.7,-2.39c0,-2.48 -2.02,-4.5 -4.5,-4.5S7.5,10.52 7.5,13s2.02,4.5 4.5,4.5c0.88,0 1.69,-0.26 2.39,-0.7l3.2,3.2L6,20V4h7.17L18,8.83V17.59zM12,15.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5S13.38,15.5 12,15.5z"/>
+</vector>
diff --git a/res/drawable/ic_qrcode_24dp.xml b/res/drawable/ic_qrcode_24dp.xml
new file mode 100644
index 0000000..ff7806f
--- /dev/null
+++ b/res/drawable/ic_qrcode_24dp.xml
@@ -0,0 +1,39 @@
+<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="M7,4v3H4V4H7M9,2H2v7h7V2L9,2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M15,11l-8,0l0,2l8,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M13,2l-2,0l0,11l2,0l0,-11z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,15l-11,0l0,2l11,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M13,17l-2,0l0,5l2,0l0,-5z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M17,13l-2,0l0,9l2,0l0,-9z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,19l-3,0l0,3l3,0l0,-3z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M5,11l-3,0l0,2l3,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,11l-5,0l0,2l5,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M20,4v3h-3V4H20M22,2h-7v7h7V2L22,2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M7,17v3H4v-3H7M9,15H2v7h7V15L9,15z"/>
+</vector>
diff --git a/res/drawable/ic_scan_24dp.xml b/res/drawable/ic_scan_24dp.xml
new file mode 100644
index 0000000..bcef8e3
--- /dev/null
+++ b/res/drawable/ic_scan_24dp.xml
@@ -0,0 +1,33 @@
+<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="M9,2l-7,0l0,2l7,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,2l-7,0l0,2l7,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,11l-20,0l0,2l20,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,2l-2,0l0,7l2,0l0,-7z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M4,2l-2,0l0,7l2,0l0,-7z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M9,20l-7,0l0,2l7,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,20l-7,0l0,2l7,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,15l-2,0l0,7l2,0l0,-7z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M4,15l-2,0l0,7l2,0l0,-7z"/>
+</vector>
diff --git a/res/drawable/ic_wifi_privacy_24dp.xml b/res/drawable/ic_wifi_privacy_24dp.xml
new file mode 100644
index 0000000..c23fbc1
--- /dev/null
+++ b/res/drawable/ic_wifi_privacy_24dp.xml
@@ -0,0 +1,32 @@
+<?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:viewportWidth="24"
+        android:viewportHeight="24"
+        android:width="24dp"
+        android:height="24dp"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.25,16.5v-0.66c0,-1.13 -1.03,-2.09 -2.25,-2.09s-2.25,0.96 -2.25,2.09v0.66H16V22h6v-5.5H21.25zM19.75,16.5h-1.5v-0.66c0,-0.29 0.38,-0.59 0.75,-0.59s0.75,0.3 0.75,0.59V16.5z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12,17c-3.79,0 -7.17,-2.13 -8.82,-5.5C4.83,8.13 8.21,6 12,6s7.17,2.13 8.82,5.5H23C21.27,7.11 17,4 12,4S2.73,7.11 1,11.5C2.73,15.89 7,19 12,19c0.68,0 1.35,-0.06 2,-0.17v-2.05C13.35,16.91 12.69,17 12,17z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M16.43,12.23c0.04,-0.24 0.07,-0.48 0.07,-0.73C16.5,9.02 14.48,7 12,7s-4.5,2.02 -4.5,4.5S9.52,16 12,16c0.77,0 1.48,-0.21 2.12,-0.55C14.41,14.08 15.27,12.93 16.43,12.23zM12,14.2c-1.49,0 -2.7,-1.21 -2.7,-2.7s1.21,-2.7 2.7,-2.7s2.7,1.21 2.7,2.7S13.49,14.2 12,14.2z"/>
+</vector>
diff --git a/res/layout/homepage_condition_half_tile.xml b/res/layout/homepage_condition_half_tile.xml
index fb83389..eff167a 100644
--- a/res/layout/homepage_condition_half_tile.xml
+++ b/res/layout/homepage_condition_half_tile.xml
@@ -61,6 +61,7 @@
             android:id="@+id/first_action"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:scrollbars="none"
             style="@style/ConditionHalfCardBorderlessButton"/>
 
     </LinearLayout>
diff --git a/res/layout/settings_action_buttons.xml b/res/layout/settings_action_buttons.xml
deleted file mode 100644
index 56e1a36..0000000
--- a/res/layout/settings_action_buttons.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2017 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingStart="8dp"
-    android:orientation="horizontal">
-
-    <Button
-        android:id="@+id/button1"
-        style="@style/SettingsActionButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-
-    <Button
-        android:id="@+id/button2"
-        style="@style/SettingsActionButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-
-    <Button
-        android:id="@+id/button3"
-        style="@style/SettingsActionButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-
-    <Button
-        android:id="@+id/button4"
-        style="@style/SettingsActionButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 8d81e82..75d449f 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -21,24 +21,17 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:background="@android:color/transparent"
-        app:elevation="0dp">
-        <include layout="@layout/search_bar"/>
-    </com.google.android.material.appbar.AppBarLayout>
-
     <androidx.core.widget.NestedScrollView
         android:id="@+id/main_content_scrollable_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        app:layout_behavior="@string/appbar_scrolling_view_behavior">
+        app:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior">
 
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
+            android:paddingTop="@dimen/app_bar_height"
             android:descendantFocusability="blocksDescendants">
 
             <FrameLayout
@@ -55,4 +48,10 @@
 
         </LinearLayout>
     </androidx.core.widget.NestedScrollView>
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <include layout="@layout/search_bar"/>
+    </com.google.android.material.appbar.AppBarLayout>
 </androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/res/layout/settings_main_dashboard.xml b/res/layout/settings_main_dashboard.xml
new file mode 100644
index 0000000..ee84576
--- /dev/null
+++ b/res/layout/settings_main_dashboard.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+
+<!-- TODO(118444000): Remove this -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/search_bar" />
+
+    <FrameLayout
+        android:id="@+id/main_content"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/zen_rule_widget.xml b/res/layout/zen_rule_widget.xml
index d502243..c6214e7 100644
--- a/res/layout/zen_rule_widget.xml
+++ b/res/layout/zen_rule_widget.xml
@@ -20,13 +20,13 @@
         android:layout_height="match_parent"
         android:orientation="horizontal">
     <ImageView
-            android:id="@+id/delete_zen_rule"
+            android:id="@+id/zen_automatic_rule_widget"
             android:layout_width="wrap_content"
             android:layout_height="fill_parent"
             android:paddingStart="16dip"
             android:paddingEnd="16dip"
-            android:src="@drawable/ic_delete"
-            android:contentDescription="@string/zen_mode_delete_rule"
+            android:src="@drawable/ic_settings"
+            android:contentDescription="zen_mode_rule_settings"
             android:layout_gravity="center"
             android:background="?android:attr/selectableItemBackground" />
 </LinearLayout>
diff --git a/res/menu/manage_apps.xml b/res/menu/manage_apps.xml
index 99dba37..51189a0 100644
--- a/res/menu/manage_apps.xml
+++ b/res/menu/manage_apps.xml
@@ -16,6 +16,13 @@
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item
+        android:id="@+id/search_app_list_menu"
+        android:title="@string/search_settings"
+        android:icon="@drawable/ic_find_in_page_24px"
+        android:showAsAction="always|collapseActionView"
+        android:actionViewClass="android.widget.SearchView" />
+
+    <item
         android:id="@+id/advanced"
         android:title="@string/advanced_apps"
         android:icon="@drawable/ic_settings_24dp"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 0ddd3ea..f95809e 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -701,6 +701,15 @@
         <item>120000</item>
     </integer-array>
 
+    <!-- Summaries of accessibility timeout, pairs to Values -->
+    <string-array name="accessibility_timeout_summaries" translatable="false">
+        <item>@string/accessibility_timeout_default</item>
+        <item>@string/accessibility_timeout_10secs</item>
+        <item>@string/accessibility_timeout_30secs</item>
+        <item>@string/accessibility_timeout_1min</item>
+        <item>@string/accessibility_timeout_2mins</item>
+    </string-array>
+
     <!-- Titles for the list of long press timeout options. -->
     <string-array name="long_press_timeout_selector_titles">
         <!-- A title for the option for short long-press timeout [CHAR LIMIT=25] -->
@@ -1068,11 +1077,18 @@
         <item>never</item>
     </string-array>
 
-    <string-array name="zen_mode_contacts_entries" translatable="false">
+    <string-array name="zen_mode_contacts_messages_entries" translatable="false">
         <item>@string/zen_mode_from_anyone</item>
         <item>@string/zen_mode_from_contacts</item>
         <item>@string/zen_mode_from_starred</item>
-        <item>@string/zen_mode_from_none</item>
+        <item>@string/zen_mode_from_none_calls</item>
+    </string-array>
+
+    <string-array name="zen_mode_contacts_calls_entries" translatable="false">
+        <item>@string/zen_mode_from_anyone</item>
+        <item>@string/zen_mode_from_contacts</item>
+        <item>@string/zen_mode_from_starred</item>
+        <item>@string/zen_mode_from_none_messages</item>
     </string-array>
 
     <string-array name="zen_mode_contacts_values" translatable="false">
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 752fd3d..86763b7 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -72,6 +72,14 @@
         <attr name="allowDynamicSummaryInSlice" format="boolean" />
     </declare-styleable>
 
+    <declare-styleable name="PreferenceScreen">
+        <!-- Determines if static preferences defined in addStaticPreferences are added before or after the radio buttons -->
+        <attr name="staticPreferenceLocation">
+            <enum name="prepend" value="0" />
+            <enum name="append" value="1" />
+        </attr>
+    </declare-styleable>
+
     <!-- For DotsPageIndicator -->
     <declare-styleable name="DotsPageIndicator">
         <attr name="dotDiameter" format="dimension" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 83848af..a6c6c37 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -105,6 +105,8 @@
     <dimen name="search_bar_avatar_size">32dp</dimen>
     <dimen name="search_bar_avatar_start_margin">4dp</dimen>
     <dimen name="search_bar_avatar_end_margin">16dp</dimen>
+    <!-- appbar height is equal search bar height (48dp) plus search bar top and bottom margin  -->
+    <dimen name="app_bar_height">80dp</dimen>
 
     <!-- Dimensions for Wifi Assistant Card -->
     <dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4700d3f..b6d9239 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -653,6 +653,8 @@
     <string name="done">Done</string>
     <!-- Button label for generic apply action [CHAR LIMIT=20] -->
     <string name="apply">Apply</string>
+    <!-- Button label for generic share action [CHAR LIMIT=20] -->
+    <string name="share">Share</string>
 
     <!-- Title of the Settings activity shown within the application itself. -->
     <string name="settings_label">Settings</string>
@@ -670,7 +672,7 @@
     <!-- check box cellular data title [CHAR LIMIT=30] -->
     <string name="cellular_data_title">Mobile data</string>
     <!-- check box Calls title [CHAR LIMIT=30] -->
-    <string name="calls_title">Calls</string>
+    <string name="calls_title">Allow calls</string>
     <!-- check box SMS Messges title [CHAR LIMIT=30] -->
     <string name="sms_messages_title">SMS messages</string>
     <!-- check box cellular data summary [CHAR LIMIT=85] -->
@@ -2878,6 +2880,14 @@
     <string name="status_prl_version">PRL version</string>
     <!-- About phone screen, title for MEID for multi-sim devices -->
     <string name="meid_multi_sim">MEID (sim slot %1$d)</string>
+    <!-- The status text when both Wi-Fi scanning and Bluetooth scanning are on. [CHAR LIMIT=120] -->
+    <string name="scanning_status_text_wifi_on_ble_on">Both Wi\u2011Fi and Bluetooth are allowed to determine location</string>
+    <!-- The status text when Wi-Fi scanning is on and Bluetooth scanning are off. [CHAR LIMIT=120] -->
+    <string name="scanning_status_text_wifi_on_ble_off">Only Wi\u2011Fi is allowed to determine location</string>
+    <!-- The status text when Wi-Fi scanning is off and Bluetooth scanning are on. [CHAR LIMIT=120] -->
+    <string name="scanning_status_text_wifi_off_ble_on">Only Bluetooth is allowed to determine location</string>
+    <!-- The status text when both Wi-Fi scanning and Bluetooth scanning are off. [CHAR LIMIT=120] -->
+    <string name="scanning_status_text_wifi_off_ble_off">Neither Wi\u2011Fi nor Bluetooth is allowed to determine location</string>
     <!-- About phone, status item title.  The phone MEID number of the current LTE/CDMA device. [CHAR LIMIT=30] -->
     <string name="status_meid_number">MEID</string>
     <!-- About phone, status item title.  The ICCID of the current LTE device. [CHAR LIMIT=30] -->
@@ -3612,8 +3622,8 @@
     <string name="location_high_battery_use">High battery use</string>
     <!-- [CHAR LIMIT=30] Location settings screen, recent location requests low battery use-->
     <string name="location_low_battery_use">Low battery use</string>
-    <!-- [CHAR LIMIT=30] Wireless background scanning settings screen, screen title -->
-    <string name="location_scanning_screen_title">Scanning</string>
+    <!-- [CHAR LIMIT=60] Wireless background scanning settings screen, screen title -->
+    <string name="location_scanning_screen_title">Wi\u2011Fi and Bluetooth scanning</string>
     <!-- [CHAR LIMIT=130] Preference title for Wi-Fi always scanning -->
     <string name="location_scanning_wifi_always_scanning_title">Wi\u2011Fi scanning</string>
     <!-- Preference description text for Wi-Fi always scanning -->
@@ -3757,6 +3767,8 @@
     <string name="lockpassword_choose_your_pattern_header_for_face">To use face authentication, set pattern</string>
     <!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
     <string name="lockpassword_choose_your_pin_header_for_face">To use face authentication, set PIN</string>
+    <!-- Message on Wi-Fi Sharing screen [CHAR LIMIT=NONE] -->
+    <string name="wifi_sharing_message">Your Wi\u2011Fi name and password for \"<xliff:g id="SSID" example="GoogleGuest">%1$s</xliff:g>\" will be shared.</string>
 
     <!-- Message to be used to explain the user that he needs to enter his pattern to continue a
          particular operation. [CHAR LIMIT=70]-->
@@ -5407,6 +5419,12 @@
     <!-- Battery saver: Label for preference to turn on battery saver automatically when battery is low [CHAR_LIMIT=40] -->
     <string name="battery_saver_auto_title">Turn on automatically</string>
 
+    <!-- Battery saver: Label for preference to indicate there is no battery saver schedule [CHAR_LIMIT=40] -->
+    <string name="battery_saver_auto_no_schedule">No schedule</string>
+
+    <!-- Battery saver: Title for battery saver schedule screen [CHAR_LIMIT=40] -->
+    <string name="battery_saver_schedule_settings_title">Set a schedule</string>
+
     <!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
     <string name="battery_saver_seekbar_title">At <xliff:g id="percent">%1$s</xliff:g></string>
 
@@ -7084,8 +7102,8 @@
 
     <!-- Sound: Summary for the Do not Disturb option when at least one automatic rules turned on. [CHAR LIMIT=NONE]-->
     <plurals name="zen_mode_settings_summary_on">
-        <item quantity="one">1 rule</item>
-        <item quantity="other"><xliff:g id="on_count" example="10">%d</xliff:g> rules</item>
+        <item quantity="one">1 enabled</item>
+        <item quantity="other"><xliff:g id="on_count" example="10">%d</xliff:g> enabled</item>
     </plurals>
 
     <!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]-->
@@ -7118,11 +7136,17 @@
     <!--  Do not disturb: Title for the zen mode automation option in Settings. [CHAR LIMIT=40] -->
     <string name="zen_mode_automation_settings_title">Schedules</string>
 
+    <!--  Do not disturb: Title for dialog that allows users to delete DND rules/schedules[CHAR LIMIT=40] -->
+    <string name="zen_mode_delete_automatic_rules">Delete schedules</string>
+
+    <!--  Do not disturb: Delete text button presented in a dialog to confirm the user would like to delete the selected DND rules. [CHAR LIMIT=30] -->
+    <string name="zen_mode_schedule_delete">Delete</string>
+
     <!--  Do not disturb: Title for the zen mode automatic rules page in settings. [CHAR LIMIT=30] -->
-    <string name="zen_mode_automation_settings_page_title">Do Not Disturb</string>
+    <string name="zen_mode_automation_settings_page_title">Schedules</string>
 
     <!--  Do not disturb: Title for a specific zen mode automatic rule in settings. [CHAR LIMIT=30] -->
-    <string name="zen_mode_automatic_rule_settings_page_title">Automatic rule</string>
+    <string name="zen_mode_automatic_rule_settings_page_title">Schedule</string>
 
     <!--  Do not disturb: Title do not disturb settings representing automatic (scheduled) do not disturb rules. [CHAR LIMIT=30] -->
     <string name="zen_mode_schedule_category_title">Schedule</string>
@@ -7137,7 +7161,7 @@
     <string name="zen_mode_schedule_title">Schedule</string>
 
     <!--  Do not disturb: Switch toggle to toggle whether to use an automatic dnd rule or not [CHAR LIMIT=40] -->
-    <string name="zen_mode_use_automatic_rule">Use rule</string>
+    <string name="zen_mode_use_automatic_rule">Use schedule</string>
 
     <!--  Do not disturb: Zen mode option: Important interruptions [CHAR LIMIT=60] -->
     <string name="zen_mode_option_important_interruptions">Priority only</string>
@@ -7161,7 +7185,7 @@
     <string name="zen_mode_settings_category">When Do Not Disturb is on</string>
 
     <!-- Do not disturb: restrict notifications title [CHAR LIMIT=80] -->
-    <string name="zen_mode_restrict_notifications_title">Notification restrictions</string>
+    <string name="zen_mode_restrict_notifications_title">Restrict notifications</string>
     <!-- Do not disturb: Mute notifications option [CHAR LIMIT=60] -->
     <string name="zen_mode_restrict_notifications_mute">No sound from notifications</string>
     <!-- Do not disturb:Mute notifications summary [CHAR LIMIT=NONE] -->
@@ -7254,6 +7278,9 @@
     <!-- [CHAR LIMIT=110] Zen mode settings footer: Footer how DND was triggered by an app -->
     <string name="zen_mode_settings_dnd_automatic_rule_app">Do Not Disturb was automatically turned on by an app (<xliff:g id="app_name" example="Android Services">%s</xliff:g>)</string>
 
+    <!-- [CHAR LIMIT=120] Zen mode settings footer: Footer informing user DND has custom settings. -->
+    <string name="zen_mode_settings_dnd_custom_settings_footer">Do Not Disturb is on for <xliff:g id="rule_names" example="Sleeping and Work">%s</xliff:g> with custom settings.</string>
+
     <!--[CHAR LIMIT=40] Zen Interruption level: Priority.  -->
     <string name="zen_interruption_level_priority">Priority only</string>
 
@@ -7264,7 +7291,7 @@
     <string name="zen_mode_sound_summary_on_with_info">On / <xliff:g name="dnd_summary" example="No sound except alarms and media">%1$s</xliff:g></string>
 
     <!-- Sound settings screen, summary format of do not disturb when off with extra information. [CHAR LIMIT=NONE] -->
-    <string name="zen_mode_sound_summary_off_with_info">Off / <xliff:g name="dnd_summary" example="1 rule can turn on automatically">%1$s</xliff:g></string>
+    <string name="zen_mode_sound_summary_off_with_info">Off / <xliff:g name="dnd_summary" example="1 schedule can turn on automatically">%1$s</xliff:g></string>
 
     <!-- Sound settings screen, summary format of do not disturb when off with no extra information. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_sound_summary_off">Off</string>
@@ -7289,12 +7316,12 @@
 
     <!-- Summary for the Sound Do not Disturb option when at least one automatic rules is enabled. [CHAR LIMIT=NONE]-->
     <plurals name="zen_mode_sound_summary_summary_off_info">
-        <item quantity="one">1 rule can turn on automatically</item>
-        <item quantity="other"><xliff:g id="on_count" example="3">%d</xliff:g> rules can turn on automatically</item>
+        <item quantity="one">1 schedule can turn on automatically</item>
+        <item quantity="other"><xliff:g id="on_count" example="3">%d</xliff:g> schedules can turn on automatically</item>
     </plurals>
 
     <!-- Do not disturb settings, category header [CHAR LIMIT=120]-->
-    <string name="zen_category_behavior">Mute phone, but allow exceptions</string>
+    <string name="zen_category_behavior">Mute device but allow exceptions</string>
     <!-- Do not disturb settings, exceptions to dnd title [CHAR LIMIT=100]-->
     <string name="zen_category_exceptions">Exceptions</string>
     <!-- Do not disturb settings, category header [CHAR LIMIT=100]-->
@@ -7745,28 +7772,28 @@
     <string name="zen_mode_rule_rename_button">Rename</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Rule name option and edit dialog title -->
-    <string name="zen_mode_rule_name">Rule name</string>
+    <string name="zen_mode_rule_name">Schedule name</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Rule name hint text -->
-    <string name="zen_mode_rule_name_hint">Enter rule name</string>
+    <string name="zen_mode_rule_name_hint">Enter schedule name</string>
 
     <!-- [CHAR LIMIT=100] Zen mode settings: Warning text for invalid zen rule names -->
-    <string name="zen_mode_rule_name_warning">Rule name already in use</string>
+    <string name="zen_mode_rule_name_warning">Schedule name already in use</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Add another automatic zen rule option name-->
     <string name="zen_mode_add_rule">Add more</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Add event-based rule, set rule name title -->
-    <string name="zen_mode_add_event_rule">Add event rule</string>
+    <string name="zen_mode_add_event_rule">Add event schedule</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Add time-based rule, set rule name title -->
-    <string name="zen_mode_add_time_rule">Add time rule</string>
+    <string name="zen_mode_add_time_rule">Add time schedule</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Delete rule menu option name -->
-    <string name="zen_mode_delete_rule">Delete rule</string>
+    <string name="zen_mode_delete_rule">Delete schedule</string>
 
     <!-- [CHAR LIMIT=60] Zen mode settings: Choose rule type dialog title -->
-    <string name="zen_mode_choose_rule_type">Choose rule type</string>
+    <string name="zen_mode_choose_rule_type">Choose schedule type</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Delete rule dialog confirmation message -->
     <string name="zen_mode_delete_rule_confirmation">Delete \u201c<xliff:g id="rule" example="Weekends">%1$s</xliff:g>\u201d rule?</string>
@@ -7847,7 +7874,16 @@
     <string name="zen_mode_schedule_alarm_title">Alarm can override end time</string>
 
     <!-- [CHAR LIMIT=NONE] Zen mode settings: Downtime rule setting -->
-    <string name="zen_mode_schedule_alarm_summary">Stop at the end time or next alarm, whichever comes first</string>
+    <string name="zen_mode_schedule_alarm_summary">Schedule turns off when an alarm rings</string>
+
+    <!-- [CHAR LIMIT=80] Zen mode settings: Title for preference to allow custom behavior for the dnd schedule -->
+    <string name="zen_mode_custom_behavior_title">Do Not Disturb behavior</string>
+
+    <!-- [CHAR LIMIT=120] Zen mode settings: Summay text indicating the currenty dnd schedule is using the default dnd settings -->
+    <string name="zen_mode_custom_behavior_summary_default">Use default settings</string>
+
+    <!-- [CHAR LIMIT=120] Zen mode settings: Summay text indicating the currenty dnd schedule is using custom behavior -->
+    <string name="zen_mode_custom_behavior_summary">Create custom settings for this schedule</string>
 
     <!-- [CHAR LIMIT=40] General divider text when concatenating multiple items in a text summary -->
     <string name="summary_divider_text">,\u0020</string>
@@ -7859,10 +7895,10 @@
     <string name="summary_range_verbal_combination"><xliff:g id="start" example="Sun">%1$s</xliff:g> to <xliff:g id="end" example="Thu">%2$s</xliff:g></string>
 
     <!-- [CHAR LIMIT=20] Zen mode settings: Calls option -->
-    <string name="zen_mode_calls">Calls</string>
+    <string name="zen_mode_calls">Allow calls</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Allow calls toggle title -->
-    <string name="zen_mode_calls_title">Allow calls</string>
+    <string name="zen_mode_calls_title">Calls</string>
 
     <!-- [CHAR LIMIT=20] Zen mode settings: Calls screen footer -->
     <string name="zen_mode_calls_footer">When Do Not Disturb is on, incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.</string>
@@ -7877,25 +7913,13 @@
     </plurals>
 
     <!-- [CHAR LIMIT=20] Zen mode settings: Messages option -->
-    <string name="zen_mode_messages">Messages</string>
+    <string name="zen_mode_messages">Allow text messages</string>
 
     <!-- Do not disturb settings, messages, events and reminders footer [CHAR LIMIT=NONE]-->
     <string name="zen_mode_messages_footer">When Do Not Disturb is on, incoming text messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.</string>
 
-    <!-- [CHAR LIMIT=40] Zen mode settings: Allow messages toggle title -->
-    <string name="zen_mode_messages_title">Allow messages</string>
-
-    <!-- [CHAR LIMIT=50] Zen mode settings: All messages summary -->
-    <string name="zen_mode_all_messages">Messages</string>
-
-    <!-- [CHAR LIMIT=50] Zen mode settings: Messages option (ie: text messages) -->
-    <string name="zen_mode_all_messages_list">messages</string>
-
-    <!-- [CHAR LIMIT=50] Zen mode settings: Selected messages summary -->
-    <string name="zen_mode_selected_messages">Some messages</string>
-
-    <!-- [CHAR LIMIT=50] Zen mode settings: Selected messages (ie: some text messages are allowed to bypass dnd) -->
-    <string name="zen_mode_selected_messages_list">some messages</string>
+    <!-- [CHAR LIMIT=40] Zen mode settings: Allow messages to bypass DND title -->
+    <string name="zen_mode_messages_title">Text messages</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From anyone -->
     <string name="zen_mode_from_anyone">From anyone</string>
@@ -7915,9 +7939,15 @@
     <!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
     <string name="zen_calls_summary_repeat_only">From repeat callers only</string>
 
-    <!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: None -->
+    <!-- [CHAR LIMIT=40] Zen mode settings: Calls and/or messages from none-->
     <string name="zen_mode_from_none">None</string>
 
+    <!-- [CHAR LIMIT=40] Zen mode settings: Calls option value: No calls allowed -->
+    <string name="zen_mode_from_none_calls">Don\u2019t allow any calls</string>
+
+    <!-- [CHAR LIMIT=40] Zen mode settings: Messages option value: No messages allowed -->
+    <string name="zen_mode_from_none_messages">Don\u2019t allow any messages</string>
+
     <!-- [CHAR LIMIT=80] Zen mode settings: Allow alarms option -->
     <string name="zen_mode_alarms">Allow alarms</string>
 
@@ -7925,7 +7955,7 @@
     <string name="zen_mode_alarms_list">alarms</string>
 
     <!-- [CHAR LIMIT=80] Zen mode settings: Allow media (sound from video) to bypass dnd -->
-    <string name="zen_mode_media">Allow media</string>
+    <string name="zen_mode_media">Allow media sounds</string>
 
     <!-- [CHAR LIMIT=50] Zen mode settings: Media (ie: sound from video) -->
     <string name="zen_mode_media_list">media</string>
@@ -7949,7 +7979,7 @@
     <string name="zen_mode_bypassing_apps">Allow apps to override</string>
 
     <!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND title-->
-    <string name="zen_mode_bypassing_apps_title">Overrides Do Not Disturb</string>
+    <string name="zen_mode_bypassing_apps_title">App exceptions</string>
 
     <!-- [CHAR LIMIT=80] Zen mode settings: Allow apps to bypass DND -->
     <plurals name="zen_mode_bypassing_apps_subtext">
@@ -7980,10 +8010,10 @@
     <string name="zen_mode_repeat_callers_title">Allow repeat callers</string>
 
     <!-- [CHAR LIMIT=50] Zen mode settings: calls summary -->
-    <string name="zen_mode_calls_summary_one">From <xliff:g id="caller type" example="contacts">%1$s</xliff:g></string>
+    <string name="zen_mode_calls_summary_one">Allow from <xliff:g id="caller type" example="contacts">%1$s</xliff:g></string>
 
     <!-- [CHAR LIMIT=50] Zen mode settings: calls summary -->
-    <string name="zen_mode_calls_summary_two">From <xliff:g id="caller type" example="starred contacts">%1$s</xliff:g> and <xliff:g id="callert tpye" example="repeat callers">%2$s</xliff:g></string>
+    <string name="zen_mode_calls_summary_two">Allow from <xliff:g id="caller type" example="starred contacts">%1$s</xliff:g> and <xliff:g id="callert tpye" example="repeat callers">%2$s</xliff:g></string>
 
     <!-- [CHAR LIMIT=200] Zen mode settings: Repeat callers option summary -->
     <string name="zen_mode_repeat_callers_summary">If the same person calls a second time within a <xliff:g id="minutes">%d</xliff:g> minute period</string>
@@ -8959,7 +8989,7 @@
     <string name="condition_cellular_title">Mobile data is off</string>
 
     <!-- Summary of condition that cellular data is off [CHAR LIMIT=NONE] -->
-    <string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
+    <string name="condition_cellular_summary">Internet only available via Wi\u2011Fi</string>
 
     <!-- Title of condition that background data is off [CHAR LIMIT=30] -->
     <string name="condition_bg_data_title">Data Saver</string>
@@ -8971,7 +9001,7 @@
     <string name="condition_work_title">Work profile is off</string>
 
     <!-- Summary of condition that work mode is off [CHAR LIMIT=NONE] -->
-    <string name="condition_work_summary">Apps, background sync, and other features related to your work profile are turned off.</string>
+    <string name="condition_work_summary">For apps &amp; notifications</string>
 
     <!-- Action label on device muted card - clicking action will turn on ringtone sound [CHAR LIMIT=50] -->
     <string name="condition_device_muted_action_turn_on_sound">Turn on sound</string>
@@ -9433,6 +9463,11 @@
     <string name="managed_profile_contact_search_title">Contact search</string>
     <!-- [CHAR LIMIT=NONE] The preference summary for enabling cross-profile remote contact search -->
     <string name="managed_profile_contact_search_summary">Allow contact searches by your organization to identify callers and contacts</string>
+    <!-- [CHAR LIMIT=60] The preference title for enabling cross profile calendar sync -->
+    <string name="cross_profile_calendar_title">Cross-profile calendar</string>
+    <!-- [CHAR LIMIT=NONE] The preference summary for enabling cross profile calendar sync -->
+    <string name="cross_profile_calendar_summary">Show work events on personal calendar</string>
+
 
     <!-- Time in hours -->
     <plurals name="hours">
@@ -10218,15 +10253,17 @@
     <!-- Message for Network connection timeout Dialog [CHAR LIMIT=NONE] -->
     <string name="network_connection_timeout_dialog_message">No devices found. Make sure the device is turned on and available to connect.</string>
     <!-- OK button for Network connection timeout Dialog [CHAR LIMIT=30] -->
-    <string name="network_connection_timeout_dialog_ok">Scan again</string>
+    <string name="network_connection_timeout_dialog_ok">Try again</string>
+    <!-- Message for Network connection error state Dialog [CHAR LIMIT=NONE] -->
+    <string name="network_connection_errorstate_dialog_message">Something came up. The application has cancelled the request to choose a device.</string>
 
-    <!-- Summary for connected devices count in connected device slice. [CHAR LIMIT=NONE] -->
-    <plurals name="show_connected_devices">
+    <!-- Summary for bluetooth devices count in Bluetooth devices slice. [CHAR LIMIT=NONE] -->
+    <plurals name="show_bluetooth_devices">
         <item quantity="one"><xliff:g id="number_device_count">%1$d</xliff:g> device connected</item>
         <item quantity="other"><xliff:g id="number_device_count">%1$d</xliff:g> devices connected</item>
     </plurals>
-    <!-- Title for no connected devices in connected device slice. [CHAR LIMIT=NONE] -->
-    <string name="no_connected_devices">No connected devices</string>
+    <!-- Title for no bluetooth devices in Bluetooth devices slice. [CHAR LIMIT=NONE] -->
+    <string name="no_bluetooth_devices">No Bluetooth devices</string>
 
     <!-- Default title for the settings panel [CHAR LIMIT=NONE] -->
     <string name="settings_panel_title">Settings Panel</string>
@@ -10234,6 +10271,9 @@
     <!-- Title for the Internet Connectivity dialog (settings panel) with Internet related settings [CHAR LIMIT=50] -->
     <string name="internet_connectivity_panel_title">Internet Connectivity</string>
 
+    <!-- Title for the Volume dialog (settings panel) with all volume streams[CHAR LIMIT=50] -->
+    <string name="volume_connectivity_panel_title">Volume</string>
+
     <!-- UI debug setting: force desktop mode [CHAR LIMIT=50] -->
     <string name="force_desktop_mode">Force desktop mode</string>
     <!-- UI debug setting: force desktop mode summary [CHAR LIMIT=NONE] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 8a92eaa..19ce333 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -401,16 +401,6 @@
 
     <style name="ActionSecondaryButton" parent="android:Widget.DeviceDefault.Button"/>
 
-    <style name="SettingsActionButton"
-           parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
-        <item name="android:drawablePadding">4dp</item>
-        <item name="android:drawableTint">@*android:color/btn_colored_borderless_text_material
-        </item>
-        <item name="android:layout_marginEnd">8dp</item>
-        <item name="android:paddingTop">20dp</item>
-        <item name="android:paddingBottom">20dp</item>
-    </style>
-
     <style name="LockPatternContainerStyle">
         <item name="android:maxHeight">400dp</item>
         <item name="android:maxWidth">420dp</item>
@@ -471,8 +461,9 @@
     <style name="SearchBarStyle">
         <item name="android:layout_margin">@dimen/search_bar_margin</item>
         <item name="cardCornerRadius">8dp</item>
-        <item name="strokeColor">@color/homepage_card_stroke_color</item>
-        <item name="strokeWidth">1dp</item>
+        <item name="enforceMaterialTheme">true</item>
+        <item name="cardElevation">3dp</item>
+        <item name="shapeAppearance">@null</item>
     </style>
 
     <style name="ConditionCardBorderlessButton"
diff --git a/res/values/themes.xml b/res/values/themes.xml
index be57bd3..1e24770 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -54,6 +54,10 @@
         <item name="batteryGoodColor">@color/battery_good_color_light</item>
         <item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
         <item name="batteryBadColor">@color/battery_bad_color_light</item>
+
+        <!-- TODO(118444000): Remove colorPrimary and colorPrimaryVariant -->
+        <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
+        <item name="colorPrimaryVariant">@android:color/white</item>
     </style>
 
     <!-- Variant of the settings theme with no action bar. -->
@@ -185,6 +189,8 @@
         <item name="batteryGoodColor">@color/battery_good_color_light</item>
         <item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
         <item name="batteryBadColor">@color/battery_bad_color_light</item>
+        <!-- Define this color for material design -->
+        <item name="colorPrimaryVariant">@android:color/white</item>
     </style>
 
     <style name="Theme.Settings.Home" parent="Theme.Settings.HomeBase">
diff --git a/res/xml/accessibility_content_timeout_settings.xml b/res/xml/accessibility_content_timeout_settings.xml
index d450449..2d9072b 100644
--- a/res/xml/accessibility_content_timeout_settings.xml
+++ b/res/xml/accessibility_content_timeout_settings.xml
@@ -17,27 +17,23 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="accessibility_content_timeout_preference"
     android:title="@string/accessibility_content_timeout_preference_title"
     android:persistent="false" >
 
     <com.android.settings.widget.VideoPreference
         android:key="accessibility_content_timeout_video"
-        app:animation="@raw/gesture_swipe_up"
-        app:preview="@drawable/gesture_swipe_up"
-        android:persistent="false" />
-
-    <Preference
-        android:key="accessibility_content_timeout_summary"
-        android:selectable="false"
-        android:enabled="true"
-        android:summary="@string/accessibility_content_timeout_preference_summary"
+        android:title="@string/summary_placeholder"
+        settings:animation="@raw/gesture_swipe_up"
+        settings:preview="@drawable/gesture_swipe_up"
+        settings:controller="com.android.settings.widget.VideoPreferenceController"
         android:persistent="false" />
 
     <com.android.settings.widget.RadioButtonPreference
         android:key="accessibility_content_timeout_default"
         android:title="@string/accessibility_timeout_default"
+        settings:allowDividerAbove="true"
         android:persistent="false" />
 
     <com.android.settings.widget.RadioButtonPreference
@@ -60,4 +56,8 @@
         android:title="@string/accessibility_timeout_2mins"
         android:persistent="false" />
 
+    <com.android.settingslib.widget.FooterPreference
+        android:title="@string/accessibility_content_timeout_preference_summary"
+        android:selectable="false" />
+
 </PreferenceScreen>
diff --git a/res/xml/accessibility_control_timeout_settings.xml b/res/xml/accessibility_control_timeout_settings.xml
index 6d8e1d0..ea8d8c6 100644
--- a/res/xml/accessibility_control_timeout_settings.xml
+++ b/res/xml/accessibility_control_timeout_settings.xml
@@ -17,27 +17,23 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="accessibility_control_timeout_preference"
     android:title="@string/accessibility_control_timeout_preference_title"
     android:persistent="false" >
 
     <com.android.settings.widget.VideoPreference
         android:key="accessibility_control_timeout_video"
-        app:animation="@raw/gesture_swipe_up"
-        app:preview="@drawable/gesture_swipe_up"
-        android:persistent="false" />
-
-    <Preference
-        android:key="accessibility_control_timeout_summary"
-        android:selectable="false"
-        android:enabled="true"
-        android:summary="@string/accessibility_control_timeout_preference_summary"
+        android:title="@string/summary_placeholder"
+        settings:animation="@raw/gesture_swipe_up"
+        settings:preview="@drawable/gesture_swipe_up"
+        settings:controller="com.android.settings.widget.VideoPreferenceController"
         android:persistent="false" />
 
     <com.android.settings.widget.RadioButtonPreference
         android:key="accessibility_control_timeout_default"
         android:title="@string/accessibility_timeout_default"
+        settings:allowDividerAbove="true"
         android:persistent="false" />
 
     <com.android.settings.widget.RadioButtonPreference
@@ -60,4 +56,8 @@
         android:title="@string/accessibility_timeout_2mins"
         android:persistent="false" />
 
+    <com.android.settingslib.widget.FooterPreference
+        android:title="@string/accessibility_control_timeout_preference_summary"
+        android:selectable="false" />
+
 </PreferenceScreen>
diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index 8f99ce1..506686a 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -36,7 +36,7 @@
         settings:allowDividerAbove="true"
         settings:allowDividerBelow="true"/>
 
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="action_buttons"
         android:order="-9998" />
 
@@ -72,12 +72,6 @@
         settings:controller="com.android.settings.applications.appinfo.AppDataUsagePreferenceController" />
 
     <Preference
-        android:key="data_settings_v2"
-        android:title="@string/data_usage_app_summary_title"
-        android:summary="@string/summary_placeholder"
-        settings:controller="com.android.settings.applications.appinfo.AppDataUsagePreferenceControllerV2" />
-
-    <Preference
         android:key="time_spent_in_app"
         android:title="@string/time_spent_in_app_pref_title"
         settings:controller="com.android.settings.applications.appinfo.TimeSpentInAppPreferenceController" />
@@ -185,4 +179,4 @@
         settings:allowDividerAbove="true"
         settings:enableCopying="true"/>
 
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml
index 7036d27..376f09e 100644
--- a/res/xml/app_storage_settings.xml
+++ b/res/xml/app_storage_settings.xml
@@ -19,7 +19,7 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/storage_label">
 
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="header_view" />
 
     <com.android.settings.applications.SpacePreference
diff --git a/res/xml/battery_saver_schedule_settings.xml b/res/xml/battery_saver_schedule_settings.xml
new file mode 100644
index 0000000..f91e4ca
--- /dev/null
+++ b/res/xml/battery_saver_schedule_settings.xml
@@ -0,0 +1,23 @@
+<?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.
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:title="@string/battery_saver_schedule_settings_title"
+    settings:staticPreferenceLocation="append">
+</PreferenceScreen >
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index 6449e4b..40ce93d 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -25,7 +25,7 @@
         android:selectable="false"
         settings:allowDividerBelow="true"/>
 
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="action_buttons" />
 
     <PreferenceCategory
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index a0f019d..be45cd0 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -424,9 +424,6 @@
             android:summary="%s"
             android:title="@string/simulate_color_space" />
 
-        <Preference android:key="angle_enabled_app"
-            android:title="@string/angle_enabled_app" />
-
         <Preference android:key="updated_gfx_driver_dev_opt_in_app"
             android:summary="@string/updated_gfx_driver_dev_opt_in_app_summary"
             android:title="@string/updated_gfx_driver_dev_opt_in_app" />
diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml
index 4fa50e7..e8b26b0 100644
--- a/res/xml/enterprise_privacy_settings.xml
+++ b/res/xml/enterprise_privacy_settings.xml
@@ -21,82 +21,107 @@
 
     <!-- Header -->
     <Preference android:key="enterprise_privacy_header"
+                android:order="100"
                 android:icon="@drawable/ic_info_outline_24dp"
                 android:summary="@string/enterprise_privacy_header"
                 android:selectable="false"/>
 
     <PreferenceCategory android:key="exposure_category"
+                        android:order="200"
                         android:title="@string/enterprise_privacy_exposure_category"
                         android:contentDescription="@string/enterprise_privacy_exposure_category">
         <Preference android:key="enterprise_privacy_enterprise_data"
+                    android:order="210"
                     android:layout_height="wrap_content"
                     android:title="@string/enterprise_privacy_enterprise_data"
                     android:selectable="false"/>
         <Preference android:key="enterprise_privacy_installed_packages"
+                    android:order="220"
                     android:title="@string/enterprise_privacy_installed_packages"
                     android:selectable="false"/>
         <Preference android:key="enterprise_privacy_usage_stats"
+                    android:order="230"
                     android:title="@string/enterprise_privacy_usage_stats"
                     android:selectable="false"/>
         <Preference android:key="network_logs"
+                    android:order="240"
                     android:title="@string/enterprise_privacy_network_logs"
                     android:selectable="false"/>
         <Preference android:key="bug_reports"
+                    android:order="250"
                     android:title="@string/enterprise_privacy_bug_reports"
                     android:selectable="false"/>
         <Preference android:key="security_logs"
+                    android:order="260"
                     android:title="@string/enterprise_privacy_security_logs"
                     android:selectable="false"/>
     </PreferenceCategory>
 
     <PreferenceCategory android:title="@string/enterprise_privacy_exposure_changes_category"
+                        android:order="300"
                         android:key="exposure_changes_category">
         <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$EnterpriseInstalledPackages"
+                    android:order="310"
                     android:key="number_enterprise_installed_packages"
                     android:title="@string/enterprise_privacy_enterprise_installed_packages"/>
         <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionLocation"
+                    android:order="320"
                     android:key="enterprise_privacy_number_location_access_packages"
                     android:title="@string/enterprise_privacy_location_access"/>
         <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionMicrophone"
+                    android:order="330"
                     android:key="enterprise_privacy_number_microphone_access_packages"
                     android:title="@string/enterprise_privacy_microphone_access"/>
         <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionCamera"
+                    android:order="340"
                     android:key="enterprise_privacy_number_camera_access_packages"
                     android:title="@string/enterprise_privacy_camera_access"/>
         <Preference android:fragment="com.android.settings.enterprise.EnterpriseSetDefaultAppsListFragment"
+                    android:order="350"
                     android:key="number_enterprise_set_default_apps"
                     android:title="@string/enterprise_privacy_enterprise_set_default_apps"/>
         <Preference android:key="always_on_vpn_primary_user"
+                    android:order="360"
                     android:selectable="false"/>
         <Preference android:key="always_on_vpn_managed_profile"
+                    android:order="370"
                     android:title="@string/enterprise_privacy_always_on_vpn_work"
                     android:selectable="false"/>
         <Preference android:key="input_method"
+                    android:order="380"
                     android:title="@string/enterprise_privacy_input_method"
                     android:selectable="false"/>
         <Preference android:key="global_http_proxy"
+                    android:order="390"
                     android:title="@string/enterprise_privacy_global_http_proxy"
                     android:selectable="false"/>
         <Preference android:key="ca_certs_current_user"
+                    android:order="400"
                     android:title="@string/enterprise_privacy_ca_certs_personal"
                     android:selectable="false"/>
         <Preference android:key="ca_certs_managed_profile"
+                    android:order="410"
                     android:title="@string/enterprise_privacy_ca_certs_work"
                     android:selectable="false"/>
     </PreferenceCategory>
 
     <PreferenceCategory android:key="device_access_category"
+                        android:order="500"
                         android:title="@string/enterprise_privacy_device_access_category">
         <Preference android:key="enterprise_privacy_lock_device"
+                    android:order="510"
                     android:title="@string/enterprise_privacy_lock_device"
                     android:selectable="false"/>
         <Preference android:key="enterprise_privacy_wipe_device"
+                    android:order="520"
                     android:title="@string/enterprise_privacy_wipe_device"
                     android:selectable="false"/>
         <Preference android:key="failed_password_wipe_current_user"
+                    android:order="530"
                     android:title="@string/enterprise_privacy_failed_password_wipe_device"
                     android:selectable="false"/>
         <Preference android:key="failed_password_wipe_managed_profile"
+                    android:order="540"
                     android:title="@string/enterprise_privacy_failed_password_wipe_work"
                     android:selectable="false"/>
     </PreferenceCategory>
diff --git a/res/xml/managed_profile_settings.xml b/res/xml/managed_profile_settings.xml
index ee1e4fa..bd44cc1 100644
--- a/res/xml/managed_profile_settings.xml
+++ b/res/xml/managed_profile_settings.xml
@@ -32,4 +32,11 @@
         settings:useAdditionalSummary="true"
         settings:controller="com.android.settings.accounts.ContactSearchPreferenceController"/>
 
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="cross_profile_calendar"
+        android:summary="@string/cross_profile_calendar_summary"
+        android:title="@string/cross_profile_calendar_title"
+        settings:useAdditionalSummary="true"
+        settings:controller="com.android.settings.accounts.CrossProfileCalendarPreferenceController"/>
+
 </PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/network_and_internet_v2.xml b/res/xml/network_and_internet_v2.xml
index 680b268..974739d 100644
--- a/res/xml/network_and_internet_v2.xml
+++ b/res/xml/network_and_internet_v2.xml
@@ -21,13 +21,20 @@
     android:title="@string/network_dashboard_title"
     settings:initialExpandedChildrenCount="5">
 
+    <PreferenceCategory
+        android:key="multi_network_header"
+        settings:allowDividerBelow="true"
+        android:order="-40"
+        settings:controller="com.android.settings.network.MultiNetworkHeaderController"/>
+
     <com.android.settings.widget.MasterSwitchPreference
         android:fragment="com.android.settings.wifi.WifiSettings"
         android:key="toggle_wifi"
         android:title="@string/wifi_settings"
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_settings_wireless"
-        android:order="-30">
+        android:order="-30"
+        settings:allowDividerAbove="true">
         <intent
             android:action="android.settings.WIFI_SETTINGS"
             android:targetClass="Settings$WifiSettingsActivity" />
@@ -44,16 +51,15 @@
         settings:useAdminDisabledSummary="true">
     </com.android.settingslib.RestrictedPreference>
 
-    <com.android.settingslib.RestrictedPreference
-        android:fragment="com.android.settings.TetherSettings"
-        android:key="tether_settings"
-        android:title="@string/tether_settings_title_all"
-        android:icon="@drawable/ic_wifi_tethering"
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="toggle_airplane"
+        android:title="@string/airplane_mode"
+        android:icon="@drawable/ic_airplanemode_active"
+        android:disableDependentsState="true"
         android:order="-5"
-        android:summary="@string/summary_placeholder"
-        settings:keywords="@string/keywords_hotspot_tethering"
-        settings:userRestriction="no_config_tethering"
-        settings:useAdminDisabledSummary="true" />
+        settings:controller="com.android.settings.network.AirplaneModePreferenceController"
+        settings:platform_slice="true"
+        settings:userRestriction="no_airplane_mode"/>
 
     <com.android.settingslib.RestrictedPreference
         android:key="manage_mobile_plan"
@@ -63,20 +69,16 @@
         settings:userRestriction="no_config_mobile_networks"
         settings:useAdminDisabledSummary="true" />
 
-    <com.android.settingslib.RestrictedSwitchPreference
-        android:key="toggle_airplane"
-        android:title="@string/airplane_mode"
-        android:icon="@drawable/ic_airplanemode_active"
-        android:disableDependentsState="true"
+    <com.android.settingslib.RestrictedPreference
+        android:fragment="com.android.settings.TetherSettings"
+        android:key="tether_settings"
+        android:title="@string/tether_settings_title_all"
+        android:icon="@drawable/ic_wifi_tethering"
         android:order="5"
-        settings:controller="com.android.settings.network.AirplaneModePreferenceController"
-        settings:platform_slice="true"
-        settings:userRestriction="no_airplane_mode"/>
-
-    <Preference
-        android:fragment="com.android.settings.ProxySelector"
-        android:key="proxy_settings"
-        android:title="@string/proxy_settings_title" />
+        android:summary="@string/summary_placeholder"
+        settings:keywords="@string/keywords_hotspot_tethering"
+        settings:userRestriction="no_config_tethering"
+        settings:useAdminDisabledSummary="true" />
 
     <com.android.settingslib.RestrictedPreference
         android:fragment="com.android.settings.vpn2.VpnSettings"
diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml
index 12c7e21..945ceed 100644
--- a/res/xml/power_usage_detail.xml
+++ b/res/xml/power_usage_detail.xml
@@ -26,7 +26,7 @@
         android:order="-10000"
         settings:allowDividerBelow="true"/>
 
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="action_buttons"
         android:order="-9999"/>
 
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index d38a8e4..ee8613d 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -28,6 +28,7 @@
         android:icon="@drawable/ic_media_stream"
         android:title="@string/media_volume_option_title"
         android:order="-180"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/>
 
     <!-- Media output switcher -->
@@ -44,6 +45,7 @@
         android:icon="@drawable/ic_local_phone_24_lib"
         android:title="@string/call_volume_option_title"
         android:order="-170"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.notification.CallVolumePreferenceController"/>
 
     <!-- Hands free profile output switcher -->
@@ -60,6 +62,7 @@
         android:icon="@drawable/ic_notifications"
         android:title="@string/ring_volume_option_title"
         android:order="-160"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.notification.RingVolumePreferenceController"/>
 
 
@@ -69,6 +72,7 @@
         android:icon="@*android:drawable/ic_audio_alarm"
         android:title="@string/alarm_volume_option_title"
         android:order="-150"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
 
     <!-- Notification volume -->
diff --git a/res/xml/tts_settings.xml b/res/xml/tts_settings.xml
index e76cdb7..92bf5d7 100644
--- a/res/xml/tts_settings.xml
+++ b/res/xml/tts_settings.xml
@@ -50,7 +50,7 @@
             android:defaultValue="100"
             android:max="400"/>
 
-        <com.android.settings.widget.ActionButtonPreference
+        <com.android.settingslib.widget.ActionButtonsPreference
             android:key="action_buttons" />
 
     </PreferenceCategory>
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
index 8ec320a..15ab1aa 100644
--- a/res/xml/wifi_configure_settings.xml
+++ b/res/xml/wifi_configure_settings.xml
@@ -41,7 +41,8 @@
     <SwitchPreference
         android:key="wifi_cellular_data_fallback"
         android:title="@string/wifi_cellular_data_fallback_title"
-        android:summary="@string/wifi_cellular_data_fallback_summary" />
+        android:summary="@string/wifi_cellular_data_fallback_summary"
+        settings:controller="com.android.settings.wifi.CellularFallbackPreferenceController" />
 
     <Preference
         android:key="install_credentials"
diff --git a/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml
index 8b027e2..70bd194 100644
--- a/res/xml/wifi_network_details_fragment.xml
+++ b/res/xml/wifi_network_details_fragment.xml
@@ -27,7 +27,7 @@
         settings:allowDividerBelow="true"/>
 
     <!-- Buttons -->
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="buttons"
         android:selectable="false" />
 
@@ -60,6 +60,7 @@
 
         <DropDownPreference
             android:key="privacy"
+            android:icon="@drawable/ic_wifi_privacy_24dp"
             android:title="@string/wifi_privacy_settings"
             android:entries="@array/wifi_privacy_entries"
             android:entryValues="@array/wifi_privacy_values"/>
diff --git a/res/xml/zen_mode_calls_settings.xml b/res/xml/zen_mode_calls_settings.xml
index 74b6986..4616cf8 100644
--- a/res/xml/zen_mode_calls_settings.xml
+++ b/res/xml/zen_mode_calls_settings.xml
@@ -19,7 +19,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="zen_mode_calls_settings_page"
-    android:title="@string/zen_mode_calls" >
+    android:title="@string/zen_mode_calls_title" >
 
    <PreferenceCategory
        android:title="@string/zen_mode_settings_category"
@@ -27,8 +27,8 @@
       <!-- Calls -->
       <ListPreference
           android:key="zen_mode_calls"
-          android:title="@string/zen_mode_calls_title"
-          android:entries="@array/zen_mode_contacts_entries"
+          android:title="@string/zen_mode_calls"
+          android:entries="@array/zen_mode_contacts_calls_entries"
           android:entryValues="@array/zen_mode_contacts_values"/>
 
       <Preference
diff --git a/res/xml/zen_mode_messages_settings.xml b/res/xml/zen_mode_messages_settings.xml
index 4ca6c92..2d0129e 100644
--- a/res/xml/zen_mode_messages_settings.xml
+++ b/res/xml/zen_mode_messages_settings.xml
@@ -18,7 +18,7 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:key="zen_mode_messages_settings_page"
-    android:title="@string/zen_mode_messages" >
+    android:title="@string/zen_mode_messages_title" >
 
     <PreferenceCategory
         android:title="@string/zen_mode_settings_category"
@@ -26,8 +26,8 @@
         <!-- Messages -->
         <ListPreference
             android:key="zen_mode_messages"
-            android:title="@string/zen_mode_messages_title"
-            android:entries="@array/zen_mode_contacts_entries"
+            android:title="@string/zen_mode_messages"
+            android:entries="@array/zen_mode_contacts_messages_entries"
             android:entryValues="@array/zen_mode_contacts_values"/>
 
         <Preference
diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml
index d05bbd2..c257d87 100644
--- a/res/xml/zen_mode_schedule_rule_settings.xml
+++ b/res/xml/zen_mode_schedule_rule_settings.xml
@@ -43,4 +43,10 @@
         android:summary="@string/zen_mode_schedule_alarm_summary"
         android:order="99" />
 
+    <!-- Custom Do Not Disturb Setting-->
+    <Preference
+        android:key="zen_schedule_custom_setting"
+        android:title="@string/zen_mode_custom_behavior_title"
+        android:order="100" />
+
 </PreferenceScreen>
diff --git a/res/xml/zen_mode_sound_vibration_settings.xml b/res/xml/zen_mode_sound_vibration_settings.xml
index 30e2abb..73b5b05 100644
--- a/res/xml/zen_mode_sound_vibration_settings.xml
+++ b/res/xml/zen_mode_sound_vibration_settings.xml
@@ -27,13 +27,13 @@
         <!-- Calls -->
         <Preference
             android:key="zen_mode_calls_settings"
-            android:title="@string/zen_mode_calls_title"
+            android:title="@string/zen_mode_calls"
             android:fragment="com.android.settings.notification.ZenModeCallsSettings" />
 
         <!-- Messages -->
         <Preference
             android:key="zen_mode_messages_settings"
-            android:title="@string/zen_mode_messages_title"
+            android:title="@string/zen_mode_messages"
             android:fragment="com.android.settings.notification.ZenModeMessagesSettings" />
 
         <!-- Alarms -->
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java
index 7b0be94..5ab543f 100644
--- a/src/com/android/settings/CredentialStorage.java
+++ b/src/com/android/settings/CredentialStorage.java
@@ -172,8 +172,9 @@
                     dialog.show(getSupportFragmentManager(), ConfigureKeyGuardDialog.TAG);
                     return;
                 }
-                installIfAvailable();
-                finish();
+                if (installIfAvailable()) {
+                    finish();
+                }
                 return;
             }
         }
@@ -217,10 +218,13 @@
 
     /**
      * Install credentials if available, otherwise do nothing.
+     *
+     * @return true if the installation is done and the activity should be finished, false if
+     * an asynchronous task is pending and will finish the activity when it's done.
      */
-    private void installIfAvailable() {
+    private boolean installIfAvailable() {
         if (mInstallBundle == null || mInstallBundle.isEmpty()) {
-            return;
+            return true;
         }
 
         final Bundle bundle = mInstallBundle;
@@ -235,16 +239,17 @@
             if (uid != Process.WIFI_UID) {
                 Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs"
                         + " may only target wifi uids");
-                return;
+                return true;
             }
 
             final Intent installIntent = new Intent(ACTION_INSTALL)
                     .setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
                     .putExtras(bundle);
             startActivityAsUser(installIntent, new UserHandle(dstUserId));
-            return;
+            return true;
         }
 
+        boolean shouldFinish = true;
         if (bundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) {
             final String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
             final byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
@@ -259,7 +264,7 @@
 
             if (!mKeyStore.importKey(key, value, uid, flags)) {
                 Log.e(TAG, "Failed to install " + key + " as uid " + uid);
-                return;
+                return true;
             }
             // The key was prepended USER_PRIVATE_KEY by the CredentialHelper. However,
             // KeyChain internally uses the raw alias name and only prepends USER_PRIVATE_KEY
@@ -270,6 +275,7 @@
             if (uid == Process.SYSTEM_UID || uid == KeyStore.UID_SELF) {
                 new MarkKeyAsUserSelectable(
                         key.replaceFirst("^" + Credentials.USER_PRIVATE_KEY, "")).execute();
+                shouldFinish = false;
             }
         }
 
@@ -281,7 +287,7 @@
 
             if (!mKeyStore.put(certName, certData, uid, flags)) {
                 Log.e(TAG, "Failed to install " + certName + " as uid " + uid);
-                return;
+                return shouldFinish;
             }
         }
 
@@ -291,7 +297,7 @@
 
             if (!mKeyStore.put(caListName, caListData, uid, flags)) {
                 Log.e(TAG, "Failed to install " + caListName + " as uid " + uid);
-                return;
+                return shouldFinish;
             }
         }
 
@@ -300,6 +306,7 @@
         sendBroadcast(broadcast);
 
         setResult(RESULT_OK);
+        return shouldFinish;
     }
 
     /**
@@ -411,6 +418,13 @@
                 return false;
             }
         }
+
+        @Override
+        protected void onPostExecute(Boolean result) {
+            Log.i(TAG, String.format("Marked alias %s as selectable, success? %s",
+                        mAlias, result));
+            CredentialStorage.this.finish();
+        }
     }
 
     /**
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index 1f331d7..05054b4 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -33,11 +33,11 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
+import android.sysprop.VoldProperties;
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
 import android.text.Editable;
@@ -400,7 +400,7 @@
         super.onCreate(savedInstanceState);
 
         // If we are not encrypted or encrypting, get out quickly.
-        final String state = SystemProperties.get("vold.decrypt");
+        final String state = VoldProperties.decrypt().orElse("");
         if (!isDebugView() && ("".equals(state) || DECRYPT_STATE.equals(state))) {
             disableCryptKeeperComponent(this);
             // Typically CryptKeeper is launched as the home app.  We didn't
@@ -468,7 +468,7 @@
             return;
         }
 
-        final String progress = SystemProperties.get("vold.encrypt_progress");
+        final String progress = VoldProperties.encrypt_progress().orElse("");
         if (!"".equals(progress) || isDebugView(FORCE_VIEW_PROGRESS)) {
             setContentView(R.layout.crypt_keeper_progress);
             encryptionProgressInit();
@@ -636,7 +636,7 @@
     }
 
     private void updateProgress() {
-        final String state = SystemProperties.get("vold.encrypt_progress");
+        final String state = VoldProperties.encrypt_progress().orElse("");
 
         if ("error_partially_encrypted".equals(state)) {
             showFactoryReset(false);
@@ -657,8 +657,7 @@
         // Now try to get status as time remaining and replace as appropriate
         Log.v(TAG, "Encryption progress: " + progress);
         try {
-            final String timeProperty = SystemProperties.get("vold.encrypt_time_remaining");
-            int time = Integer.parseInt(timeProperty);
+            int time = VoldProperties.encrypt_time_remaining().get();
             if (time >= 0) {
                 // Round up to multiple of 10 - this way display is less jerky
                 time = (time + 9) / 10 * 10;
@@ -773,9 +772,10 @@
         if (imeSwitcher != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
             imeSwitcher.setVisibility(View.VISIBLE);
             imeSwitcher.setOnClickListener(new OnClickListener() {
-                    @Override
+                @Override
                 public void onClick(View v) {
-                    imm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
+                    imm.showInputMethodPickerFromSystem(false /* showAuxiliarySubtypes */,
+                            v.getDisplay().getDisplayId());
                 }
             });
         }
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 97942fe..307bbc1 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -39,6 +39,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.sysprop.VoldProperties;
 import android.telephony.euicc.EuiccManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -440,7 +441,7 @@
     }
 
     private boolean isExtStorageEncrypted() {
-        String state = SystemProperties.get("vold.decrypt");
+        String state = VoldProperties.decrypt().orElse("");
         return !"".equals(state);
     }
 
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 222c18c..9b5fc00 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -35,9 +35,9 @@
 import android.transition.TransitionManager;
 import android.util.Log;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.Toolbar;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
@@ -168,6 +168,12 @@
 
     private Button mNextButton;
 
+    /**
+     * TODO(b/118444000): Remove this and all related code.
+     */
+    @Deprecated
+    private boolean mIsShowingDashboard;
+
     private ViewGroup mContent;
 
     // Categories
@@ -250,7 +256,11 @@
             setTheme(R.style.Theme_SubSettings);
         }
 
-        setContentView(R.layout.settings_main_prefs);
+        mIsShowingDashboard = TextUtils.equals(
+                SettingsActivity.class.getName(), intent.getComponent().getClassName());
+
+        setContentView(mIsShowingDashboard ?
+                R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
 
         mContent = findViewById(R.id.main_content);
 
@@ -273,12 +283,21 @@
         }
 
         final boolean deviceProvisioned = Utils.isDeviceProvisioned(this);
+        if (mIsShowingDashboard) {
+            findViewById(R.id.search_bar).setVisibility(
+                    deviceProvisioned ? View.VISIBLE : View.INVISIBLE);
+            findViewById(R.id.action_bar).setVisibility(View.GONE);
+            final Toolbar toolbar = findViewById(R.id.search_action_bar);
+            setActionBar(toolbar);
+            FeatureFactory.getFactory(this).getSearchFeatureProvider()
+                    .initSearchToolbar(this, toolbar);
+        }
 
         ActionBar actionBar = getActionBar();
         if (actionBar != null) {
             actionBar.setDisplayHomeAsUpEnabled(deviceProvisioned);
             actionBar.setHomeButtonEnabled(deviceProvisioned);
-            actionBar.setDisplayShowTitleEnabled(true);
+            actionBar.setDisplayShowTitleEnabled(!mIsShowingDashboard);
         }
         mSwitchBar = findViewById(R.id.switch_bar);
         if (mSwitchBar != null) {
@@ -292,26 +311,20 @@
             if (buttonBar != null) {
                 buttonBar.setVisibility(View.VISIBLE);
 
-                Button backButton = (Button) findViewById(R.id.back_button);
-                backButton.setOnClickListener(new OnClickListener() {
-                    public void onClick(View v) {
-                        setResult(RESULT_CANCELED, null);
-                        finish();
-                    }
+                Button backButton = findViewById(R.id.back_button);
+                backButton.setOnClickListener(v -> {
+                    setResult(RESULT_CANCELED, null);
+                    finish();
                 });
-                Button skipButton = (Button) findViewById(R.id.skip_button);
-                skipButton.setOnClickListener(new OnClickListener() {
-                    public void onClick(View v) {
-                        setResult(RESULT_OK, null);
-                        finish();
-                    }
+                Button skipButton = findViewById(R.id.skip_button);
+                skipButton.setOnClickListener(v -> {
+                    setResult(RESULT_OK, null);
+                    finish();
                 });
-                mNextButton = (Button) findViewById(R.id.next_button);
-                mNextButton.setOnClickListener(new OnClickListener() {
-                    public void onClick(View v) {
-                        setResult(RESULT_OK, null);
-                        finish();
-                    }
+                mNextButton = findViewById(R.id.next_button);
+                mNextButton.setOnClickListener(v -> {
+                    setResult(RESULT_OK, null);
+                    finish();
                 });
 
                 // set our various button parameters
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 65b0e86..76be66d 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -21,6 +21,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
@@ -63,6 +64,8 @@
 import com.android.settingslib.accessibility.AccessibilityUtils;
 import com.android.settingslib.search.SearchIndexable;
 
+import com.google.common.primitives.Ints;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -125,6 +128,11 @@
             "vibration_preference_screen";
     private static final String DISPLAY_DALTONIZER_PREFERENCE_SCREEN =
             "daltonizer_preference";
+    private static final String ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE =
+            "accessibility_content_timeout_preference_fragment";
+    private static final String ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE =
+            "accessibility_control_timeout_preference_fragment";
+
 
     // Extras passed to sub-fragments.
     static final String EXTRA_PREFERENCE_KEY = "preference_key";
@@ -659,6 +667,8 @@
                     mToggleInversionPreference.getOrder() + 1);
             mToggleDisableAnimationsPreference.setOrder(
                     mToggleLargePointerIconPreference.getOrder() + 1);
+            findPreference(ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE).setOrder(
+                    mToggleDisableAnimationsPreference.getOrder() + 1);
             mToggleInversionPreference.setSummary(R.string.summary_empty);
             displayCategory.addPreference(mToggleInversionPreference);
             displayCategory.addPreference(mDisplayDaltonizerPreferenceScreen);
@@ -718,6 +728,31 @@
         updateAutoclickSummary(mAutoclickPreferenceScreen);
 
         updateAccessibilityShortcut(mAccessibilityShortcutPreferenceScreen);
+
+        updateAccessibilityTimeoutSummary(getContentResolver(),
+                findPreference(ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE));
+        updateAccessibilityTimeoutSummary(getContentResolver(),
+                findPreference(ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE));
+    }
+
+    void updateAccessibilityTimeoutSummary(ContentResolver resolver, Preference pref) {
+
+        String[] timeoutSummarys = getResources().getStringArray(
+                R.array.accessibility_timeout_summaries);
+        int[] timeoutValues = getResources().getIntArray(
+                R.array.accessibility_timeout_selector_values);
+
+        int timeoutValue = 0;
+        if (pref.getKey().equals(ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE)) {
+            timeoutValue = AccessibilityTimeoutController.getSecureAccessibilityTimeoutValue(
+                    resolver, AccessibilityTimeoutController.CONTENT_TIMEOUT_SETTINGS_SECURE);
+        } else if (pref.getKey().equals(ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE)) {
+            timeoutValue = AccessibilityTimeoutController.getSecureAccessibilityTimeoutValue(
+                    resolver, AccessibilityTimeoutController.CONTROL_TIMEOUT_SETTINGS_SECURE);
+        }
+
+        int idx = Ints.indexOf(timeoutValues, timeoutValue);
+        pref.setSummary(timeoutSummarys[idx == -1 ? 0 : idx]);
     }
 
     private void updateMagnificationSummary(Preference pref) {
diff --git a/src/com/android/settings/accessibility/AccessibilityTimeoutController.java b/src/com/android/settings/accessibility/AccessibilityTimeoutController.java
index 2995df5..d933d92 100644
--- a/src/com/android/settings/accessibility/AccessibilityTimeoutController.java
+++ b/src/com/android/settings/accessibility/AccessibilityTimeoutController.java
@@ -31,6 +31,8 @@
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import com.google.common.primitives.Ints;
+
 import java.lang.Integer;
 
 import java.util.HashMap;
@@ -38,6 +40,10 @@
 
 public class AccessibilityTimeoutController extends AbstractPreferenceController implements
         LifecycleObserver, RadioButtonPreference.OnClickListener, PreferenceControllerMixin {
+    static final String CONTENT_TIMEOUT_SETTINGS_SECURE =
+            Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS;
+    static final String CONTROL_TIMEOUT_SETTINGS_SECURE =
+            Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS;
 
     // pair the preference key and timeout value
     private final Map<String, Integer> mAccessibilityTimeoutKeyToValueMap = new HashMap<>();
@@ -64,6 +70,15 @@
         mfragmentTag = fragmentTag;
     }
 
+    protected static int getSecureAccessibilityTimeoutValue(ContentResolver resolver, String name) {
+        String timeOutSec = Settings.Secure.getString(resolver, name);
+        if (timeOutSec == null) {
+            return 0;
+        }
+        Integer timeOutValue = Ints.tryParse(timeOutSec);
+        return timeOutValue == null ? 0 : timeOutValue;
+    }
+
     public void setOnChangeListener(OnChangeListener listener) {
         mOnChangeListener = listener;
     }
@@ -131,16 +146,17 @@
         }
     }
 
-    protected void getAccessibilityUiValue() {
-        String timeoutValue = null;
-        if (mfragmentTag.equals(AccessibilityContentTimeoutPreferenceFragment.TAG)) {
-            timeoutValue = Settings.Secure.getString(mContentResolver,
-                    Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS);
-        } else if (mfragmentTag.equals(AccessibilityControlTimeoutPreferenceFragment.TAG)) {
-            timeoutValue = Settings.Secure.getString(mContentResolver,
-                    Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS);
+    private int getAccessibilityTimeoutValue(String fragmentTag) {
+        int timeoutValue = 0;
+        // two kinds of Secure value, one is content timeout, the other is control timeout.
+        if (AccessibilityContentTimeoutPreferenceFragment.TAG.equals(fragmentTag)) {
+            timeoutValue = getSecureAccessibilityTimeoutValue(mContentResolver,
+                    CONTENT_TIMEOUT_SETTINGS_SECURE);
+        } else if (AccessibilityControlTimeoutPreferenceFragment.TAG.equals(fragmentTag)) {
+            timeoutValue = getSecureAccessibilityTimeoutValue(mContentResolver,
+                    CONTROL_TIMEOUT_SETTINGS_SECURE);
         }
-        mAccessibilityUiTimeoutValue = timeoutValue == null? 0: Integer.parseInt(timeoutValue);
+        return timeoutValue;
     }
 
     protected void updatePreferenceCheckedState(int value) {
@@ -153,7 +169,7 @@
     public void updateState(Preference preference) {
         super.updateState(preference);
 
-        getAccessibilityUiValue();
+        mAccessibilityUiTimeoutValue = getAccessibilityTimeoutValue(mfragmentTag);
 
         // reset RadioButton
         mPreference.setChecked(false);
diff --git a/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java b/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java
new file mode 100644
index 0000000..38c95dc
--- /dev/null
+++ b/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java
@@ -0,0 +1,79 @@
+/*
+ * 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.accounts;
+
+import static android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.slices.SliceData;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import androidx.preference.Preference;
+
+public class CrossProfileCalendarPreferenceController extends TogglePreferenceController {
+
+    private UserHandle mManagedUser;
+
+    public CrossProfileCalendarPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    public void setManagedUser(UserHandle managedUser) {
+        mManagedUser = managedUser;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return (mManagedUser != null) ? AVAILABLE : DISABLED_FOR_USER;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        if (preference instanceof RestrictedSwitchPreference && mManagedUser != null) {
+            final RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
+            final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
+                    RestrictedLockUtilsInternal.getCrossProfileCalendarEnforcingAdmin(
+                            mContext, mManagedUser.getIdentifier());
+            pref.setDisabledByAdmin(enforcedAdmin);
+        }
+    }
+
+    @Override
+    public boolean isChecked() {
+        if (mManagedUser == null) {
+            return false;
+        }
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                CROSS_PROFILE_CALENDAR_ENABLED, /* default= */ 0,
+                mManagedUser.getIdentifier()) == 1;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        if (mManagedUser == null) {
+            return false;
+        }
+        final int value = isChecked ? 1 : 0;
+        return Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                CROSS_PROFILE_CALENDAR_ENABLED, value, mManagedUser.getIdentifier());
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/accounts/EmergencyInfoPreferenceController.java b/src/com/android/settings/accounts/EmergencyInfoPreferenceController.java
index 408db09..33e7771 100644
--- a/src/com/android/settings/accounts/EmergencyInfoPreferenceController.java
+++ b/src/com/android/settings/accounts/EmergencyInfoPreferenceController.java
@@ -36,8 +36,9 @@
 public class EmergencyInfoPreferenceController extends AbstractPreferenceController
         implements PreferenceControllerMixin {
 
+    public static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
+
     private static final String KEY_EMERGENCY_INFO = "emergency_info";
-    private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
     private static final String PACKAGE_NAME_EMERGENCY = "com.android.emergency";
 
     public EmergencyInfoPreferenceController(Context context) {
@@ -57,7 +58,7 @@
 
     public void updateState(Preference preference) {
         UserInfo info = mContext.getSystemService(UserManager.class).getUserInfo(
-            UserHandle.myUserId());
+                UserHandle.myUserId());
         preference.setSummary(mContext.getString(R.string.emergency_info_summary, info.name));
     }
 
diff --git a/src/com/android/settings/accounts/ManagedProfileSettings.java b/src/com/android/settings/accounts/ManagedProfileSettings.java
index 07e5845..dccd7f6 100644
--- a/src/com/android/settings/accounts/ManagedProfileSettings.java
+++ b/src/com/android/settings/accounts/ManagedProfileSettings.java
@@ -23,17 +23,25 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.SearchIndexableResource;
 import android.util.Log;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Setting page for managed profile.
  * FIXME: It currently assumes there is only one managed profile.
  */
+@SearchIndexable
 public class ManagedProfileSettings extends DashboardFragment {
 
     private UserManager mUserManager;
@@ -63,6 +71,7 @@
         }
         use(WorkModePreferenceController.class).setManagedUser(mManagedUser);
         use(ContactSearchPreferenceController.class).setManagedUser(mManagedUser);
+        use(CrossProfileCalendarPreferenceController.class).setManagedUser(mManagedUser);
     }
 
     @Override
@@ -99,6 +108,23 @@
         return MetricsProto.MetricsEvent.ACCOUNTS_WORK_PROFILE_SETTINGS;
     }
 
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+                        boolean enabled) {
+                    final ArrayList<SearchIndexableResource> result = new ArrayList<>();
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.managed_profile_settings;
+                    result.add(sir);
+                    return result;
+                }
+                @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return false;
+                }
+            };
+
     private class ManagedProfileBroadcastReceiver extends BroadcastReceiver {
 
         @Override
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 61ce33d..61293c5 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -53,11 +53,11 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.applications.ApplicationsState.Callbacks;
 import com.android.settingslib.applications.StorageStatsSource;
 import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
+import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 
 import java.util.Collections;
@@ -107,7 +107,7 @@
 
     // Views related to cache info
     @VisibleForTesting
-    ActionButtonPreference mButtonsPref;
+    ActionButtonsPreference mButtonsPref;
 
     private Preference mStorageUsed;
     private Button mChangeStorageButton;
@@ -168,7 +168,7 @@
                 .setComputingString(R.string.computing_size)
                 .setErrorString(R.string.invalid_size_value)
                 .build();
-        mButtonsPref = ((ActionButtonPreference) findPreference(KEY_HEADER_BUTTONS));
+        mButtonsPref = ((ActionButtonsPreference) findPreference(KEY_HEADER_BUTTONS));
         mStorageUsed = findPreference(KEY_STORAGE_USED);
         mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE))
                 .findViewById(R.id.button);
diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
index 9740ecb..2e528a7 100644
--- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
@@ -54,7 +54,6 @@
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.core.PreferenceControllerMixin;
 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;
@@ -64,6 +63,7 @@
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnDestroy;
 import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -99,8 +99,9 @@
     @VisibleForTesting
     boolean mDisableAfterUninstall = false;
     @VisibleForTesting
-    ActionButtonPreference mButtonsPref;
+    ActionButtonsPreference mButtonsPref;
 
+    private final int mUserId;
     private final int mRequestUninstall;
     private final int mRequestRemoveDeviceAdmin;
     private final DevicePolicyManager mDpm;
@@ -110,8 +111,8 @@
     private final InstrumentedPreferenceFragment mFragment;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private final ApplicationFeatureProvider mApplicationFeatureProvider;
-    private final int mUserId;
 
+    private Intent mAppLaunchIntent;
     private ApplicationsState.Session mSession;
     private RestrictedLockUtils.EnforcedAdmin mAppsControlDisallowedAdmin;
 
@@ -144,6 +145,7 @@
         mUserId = UserHandle.myUserId();
         mRequestUninstall = requestUninstall;
         mRequestRemoveDeviceAdmin = requestRemoveDeviceAdmin;
+        mAppLaunchIntent = mPm.getLaunchIntentForPackage(mPackageName);
 
         if (packageName != null) {
             mAppEntry = mState.getEntry(packageName, mUserId);
@@ -158,21 +160,25 @@
     public int getAvailabilityStatus() {
         // TODO(b/37313605): Re-enable once this controller supports instant apps
         return mAppEntry != null && !AppUtils.isInstant(mAppEntry.info)
-            ? AVAILABLE : DISABLED_FOR_USER ;
+                ? AVAILABLE : DISABLED_FOR_USER;
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         if (isAvailable()) {
-            mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_ACTION_BUTTONS))
-                    .setButton1Text(R.string.uninstall_text)
-                    .setButton1Icon(R.drawable.ic_settings_delete)
-                    .setButton2Text(R.string.force_stop)
-                    .setButton2Icon(R.drawable.ic_settings_force_stop)
-                    .setButton1OnClickListener(new UninstallAndDisableButtonListener())
-                    .setButton2OnClickListener(new ForceStopButtonListener())
-                    .setButton2Enabled(false);
+            mButtonsPref = ((ActionButtonsPreference) screen.findPreference(
+                    KEY_ACTION_BUTTONS))
+                    .setButton1Text(R.string.launch_instant_app)
+                    .setButton1Icon(R.drawable.ic_settings_open)
+                    .setButton1OnClickListener(v -> launchApplication())
+                    .setButton2Text(R.string.uninstall_text)
+                    .setButton2Icon(R.drawable.ic_settings_delete)
+                    .setButton2OnClickListener(new UninstallAndDisableButtonListener())
+                    .setButton3Text(R.string.force_stop)
+                    .setButton3Icon(R.drawable.ic_settings_force_stop)
+                    .setButton3OnClickListener(new ForceStopButtonListener())
+                    .setButton3Enabled(false);
         }
     }
 
@@ -361,6 +367,12 @@
     }
 
     @VisibleForTesting
+    void updateOpenButton() {
+        mAppLaunchIntent = mPm.getLaunchIntentForPackage(mPackageName);
+        mButtonsPref.setButton1Visible(mAppLaunchIntent != null);
+    }
+
+    @VisibleForTesting
     void updateUninstallButton() {
         final boolean isBundled = (mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
         boolean enabled = true;
@@ -430,7 +442,7 @@
             enabled = false;
         }
 
-        mButtonsPref.setButton1Enabled(enabled);
+        mButtonsPref.setButton2Enabled(enabled);
     }
 
     /**
@@ -484,7 +496,7 @@
         } else {
             Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
                     Uri.fromParts("package", mAppEntry.info.packageName, null));
-            intent.putExtra(Intent.EXTRA_PACKAGES, new String[] {mAppEntry.info.packageName});
+            intent.putExtra(Intent.EXTRA_PACKAGES, new String[]{mAppEntry.info.packageName});
             intent.putExtra(Intent.EXTRA_UID, mAppEntry.info.uid);
             intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mAppEntry.info.uid));
             Log.d(TAG, "Sending broadcast to query restart status for "
@@ -497,9 +509,9 @@
     @VisibleForTesting
     void updateForceStopButtonInner(boolean enabled) {
         if (mAppsControlDisallowedBySystem) {
-            mButtonsPref.setButton2Enabled(false);
+            mButtonsPref.setButton3Enabled(false);
         } else {
-            mButtonsPref.setButton2Enabled(enabled);
+            mButtonsPref.setButton3Enabled(enabled);
         }
     }
 
@@ -547,16 +559,16 @@
         if (mHomePackages.contains(mAppEntry.info.packageName)
                 || isSystemPackage(mActivity.getResources(), mPm, mPackageInfo)) {
             // Disable button for core system applications.
-            mButtonsPref.setButton1Text(R.string.uninstall_text)
-                    .setButton1Icon(R.drawable.ic_settings_delete);
+            mButtonsPref.setButton2Text(R.string.uninstall_text)
+                    .setButton2Icon(R.drawable.ic_settings_delete);
         } else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) {
-            mButtonsPref.setButton1Text(R.string.uninstall_text)
-                    .setButton1Icon(R.drawable.ic_settings_delete);
+            mButtonsPref.setButton2Text(R.string.uninstall_text)
+                    .setButton2Icon(R.drawable.ic_settings_delete);
             disableable = !mApplicationFeatureProvider.getKeepEnabledPackages()
                     .contains(mAppEntry.info.packageName);
         } else {
-            mButtonsPref.setButton1Text(R.string.install_text)
-                    .setButton1Icon(R.drawable.ic_settings_install);
+            mButtonsPref.setButton2Text(R.string.install_text)
+                    .setButton2Icon(R.drawable.ic_settings_install);
             disableable = true;
         }
 
@@ -639,6 +651,7 @@
             }
         }
 
+        updateOpenButton();
         updateUninstallButton();
         updateForceStopButton();
 
@@ -663,6 +676,11 @@
         mActivity.unregisterReceiver(mPackageRemovedReceiver);
     }
 
+    private void launchApplication() {
+        if (mAppLaunchIntent != null) {
+            mContext.startActivityAsUser(mAppLaunchIntent, new UserHandle(mUserId));
+        }
+    }
 
     /**
      * Changes the status of disable/enable for a package
diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
index 9443c93..1bfcd7d 100644
--- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 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.
@@ -17,15 +17,10 @@
 package com.android.settings.applications.appinfo;
 
 import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
 import android.net.NetworkTemplate;
 import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.text.format.DateUtils;
 import android.text.format.Formatter;
-import android.util.FeatureFlagUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.loader.app.LoaderManager;
@@ -36,53 +31,35 @@
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.datausage.AppDataUsage;
-import com.android.settings.datausage.DataUsageList;
 import com.android.settings.datausage.DataUsageUtils;
 import com.android.settingslib.AppItem;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
+import com.android.settingslib.net.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
 
-/**
- * Deprecated in favor of {@link AppDataUsagePreferenceControllerV2}
- *
- * @deprecated
- */
-@Deprecated
+import java.util.List;
+
 public class AppDataUsagePreferenceController extends AppInfoPreferenceControllerBase
-        implements LoaderManager.LoaderCallbacks<ChartData>, LifecycleObserver, OnResume, OnPause {
+        implements LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>, LifecycleObserver,
+        OnResume, OnPause {
 
-    private ChartData mChartData;
-    private INetworkStatsSession mStatsSession;
+    private List<NetworkCycleDataForUid> mAppUsageData;
 
-    public AppDataUsagePreferenceController(Context context,String key) {
+    public AppDataUsagePreferenceController(Context context, String key) {
         super(context, key);
     }
 
     @Override
     public int getAvailabilityStatus() {
-        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DATA_USAGE_V2)) {
-            return UNSUPPORTED_ON_DEVICE;
-        }
         return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        if (isAvailable()) {
-            final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-            try {
-                mStatsSession = statsService.openSession();
-            } catch (RemoteException e) {
-                throw new RuntimeException(e);
-            }
-        }
     }
 
     @Override
@@ -92,36 +69,42 @@
 
     @Override
     public void onResume() {
-        if (mStatsSession != null) {
+        if (isAvailable()) {
             final int uid = mParent.getAppEntry().info.uid;
             final AppItem app = new AppItem(uid);
             app.addUid(uid);
-            mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA,
-                    ChartDataLoaderCompat.buildArgs(getTemplate(mContext), app),
+            mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA, null /* args */,
                     this);
         }
     }
 
     @Override
     public void onPause() {
-        if (mStatsSession != null) {
+        if (isAvailable()) {
             mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
         }
     }
 
     @Override
-    public Loader<ChartData> onCreateLoader(int id, Bundle args) {
-        return new ChartDataLoaderCompat(mContext, mStatsSession, args);
+    public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+        final NetworkTemplate template = getTemplate(mContext);
+        return NetworkCycleDataForUidLoader.builder(mContext)
+            .setUid(mParent.getAppEntry().info.uid)
+            .setRetrieveDetail(false)
+            .setNetworkTemplate(template)
+            .setSubscriberId(template.getSubscriberId())
+            .build();
     }
 
     @Override
-    public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
-        mChartData = data;
+    public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+            List<NetworkCycleDataForUid> data) {
+        mAppUsageData = data;
         updateState(mPreference);
     }
 
     @Override
-    public void onLoaderReset(Loader<ChartData> loader) {
+    public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
         // Leave last result.
     }
 
@@ -131,14 +114,22 @@
     }
 
     private CharSequence getDataSummary() {
-        if (mChartData != null) {
-            final long totalBytes = mChartData.detail.getTotalBytes();
+        if (mAppUsageData != null) {
+            long totalBytes = 0;
+            long startTime = System.currentTimeMillis();
+            for (NetworkCycleDataForUid data : mAppUsageData) {
+                totalBytes += data.getTotalUsage();
+                final long cycleStart = data.getStartTime();
+                if (cycleStart < startTime) {
+                    startTime = cycleStart;
+                }
+            }
             if (totalBytes == 0) {
                 return mContext.getString(R.string.no_data_usage);
             }
             return mContext.getString(R.string.data_summary_format,
                     Formatter.formatFileSize(mContext, totalBytes),
-                    DateUtils.formatDateTime(mContext, mChartData.detail.getStart(),
+                    DateUtils.formatDateTime(mContext, startTime,
                             DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
         }
         return mContext.getString(R.string.computing_size);
diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
deleted file mode 100644
index 9bbc5c0..0000000
--- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
+++ /dev/null
@@ -1,158 +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.applications.appinfo;
-
-import android.content.Context;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.text.format.DateUtils;
-import android.text.format.Formatter;
-import android.util.FeatureFlagUtils;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.Loader;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
-import com.android.settings.datausage.AppDataUsageV2;
-import com.android.settings.datausage.DataUsageUtils;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-import com.android.settingslib.net.NetworkCycleDataForUidLoader;
-
-import java.util.List;
-
-public class AppDataUsagePreferenceControllerV2 extends AppInfoPreferenceControllerBase
-        implements LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>, LifecycleObserver,
-        OnResume, OnPause {
-
-    private List<NetworkCycleDataForUid> mAppUsageData;
-
-    public AppDataUsagePreferenceControllerV2(Context context, String key) {
-        super(context, key);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DATA_USAGE_V2)) {
-            return UNSUPPORTED_ON_DEVICE;
-        }
-        return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        preference.setSummary(getDataSummary());
-    }
-
-    @Override
-    public void onResume() {
-        if (isAvailable()) {
-            final int uid = mParent.getAppEntry().info.uid;
-            final AppItem app = new AppItem(uid);
-            app.addUid(uid);
-            mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA, null /* args */,
-                    this);
-        }
-    }
-
-    @Override
-    public void onPause() {
-        if (isAvailable()) {
-            mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
-        }
-    }
-
-    @Override
-    public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
-        final NetworkTemplate template = getTemplate(mContext);
-        return NetworkCycleDataForUidLoader.builder(mContext)
-            .setUid(mParent.getAppEntry().info.uid)
-            .setRetrieveDetail(false)
-            .setNetworkTemplate(template)
-            .setSubscriberId(template.getSubscriberId())
-            .build();
-    }
-
-    @Override
-    public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
-            List<NetworkCycleDataForUid> data) {
-        mAppUsageData = data;
-        updateState(mPreference);
-    }
-
-    @Override
-    public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
-        // Leave last result.
-    }
-
-    @Override
-    protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
-        return AppDataUsageV2.class;
-    }
-
-    private CharSequence getDataSummary() {
-        if (mAppUsageData != null) {
-            long totalBytes = 0;
-            long startTime = System.currentTimeMillis();
-            for (NetworkCycleDataForUid data : mAppUsageData) {
-                totalBytes += data.getTotalUsage();
-                final long cycleStart = data.getStartTime();
-                if (cycleStart < startTime) {
-                    startTime = cycleStart;
-                }
-            }
-            if (totalBytes == 0) {
-                return mContext.getString(R.string.no_data_usage);
-            }
-            return mContext.getString(R.string.data_summary_format,
-                    Formatter.formatFileSize(mContext, totalBytes),
-                    DateUtils.formatDateTime(mContext, startTime,
-                            DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
-        }
-        return mContext.getString(R.string.computing_size);
-    }
-
-    private static NetworkTemplate getTemplate(Context context) {
-        if (DataUsageUtils.hasReadyMobileRadio(context)) {
-            return NetworkTemplate.buildTemplateMobileWildcard();
-        }
-        if (DataUsageUtils.hasWifiRadio(context)) {
-            return NetworkTemplate.buildTemplateWifiWildcard();
-        }
-        return NetworkTemplate.buildTemplateEthernet();
-    }
-
-    @VisibleForTesting
-    boolean isBandwidthControlEnabled() {
-        return Utils.isBandwidthControlEnabled();
-    }
-
-}
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 32880d3..80cc6ae 100755
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -34,7 +34,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -49,7 +48,6 @@
 import com.android.settings.applications.manageapplications.ManageApplications;
 import com.android.settings.applications.specialaccess.pictureinpicture
         .PictureInPictureDetailPreferenceController;
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -141,11 +139,7 @@
         final String packageName = getPackageName();
         use(TimeSpentInAppPreferenceController.class).setPackageName(packageName);
 
-        if (FeatureFlagUtils.isEnabled(context, FeatureFlags.DATA_USAGE_V2)) {
-            use(AppDataUsagePreferenceControllerV2.class).setParentFragment(this);
-        } else {
-            use(AppDataUsagePreferenceController.class).setParentFragment(this);
-        }
+        use(AppDataUsagePreferenceController.class).setParentFragment(this);
         final AppInstallerInfoPreferenceController installer =
                 use(AppInstallerInfoPreferenceController.class);
         installer.setPackageName(packageName);
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 6b2fb91..c2db019 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -67,11 +67,14 @@
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.Filter;
 import android.widget.FrameLayout;
+import android.widget.SearchView;
 import android.widget.Spinner;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -140,7 +143,7 @@
  * intent.
  */
 public class ManageApplications extends InstrumentedFragment
-        implements View.OnClickListener, OnItemSelectedListener {
+        implements View.OnClickListener, OnItemSelectedListener, SearchView.OnQueryTextListener {
 
     static final String TAG = "ManageApplications";
     static final boolean DEBUG = true;
@@ -196,6 +199,7 @@
 
     private View mListContainer;
     private RecyclerView mRecyclerView;
+    private SearchView mSearchView;
 
     // Size resource used for packages whose size computation failed for some reason
     CharSequence mInvalidSizeStr;
@@ -599,6 +603,13 @@
         mOptionsMenu = menu;
         inflater.inflate(R.menu.manage_apps, menu);
 
+        final MenuItem searchMenuItem = menu.findItem(R.id.search_app_list_menu);
+        if (searchMenuItem != null) {
+            mSearchView = (SearchView) searchMenuItem.getActionView();
+            mSearchView.setQueryHint(getText(R.string.search_settings));
+            mSearchView.setOnQueryTextListener(this);
+        }
+
         updateOptionsMenu();
     }
 
@@ -724,6 +735,17 @@
     public void onNothingSelected(AdapterView<?> parent) {
     }
 
+    @Override
+    public boolean onQueryTextSubmit(String query) {
+        return false;
+    }
+
+    @Override
+    public boolean onQueryTextChange(String newText) {
+        mApplications.filterSearch(newText);
+        return false;
+    }
+
     public void updateView() {
         updateOptionsMenu();
         final Activity host = getActivity();
@@ -859,6 +881,7 @@
 
         private AppFilterItem mAppFilter;
         private ArrayList<ApplicationsState.AppEntry> mEntries;
+        private ArrayList<ApplicationsState.AppEntry> mOriginalEntries;
         private boolean mResumed;
         private int mLastSortMode = -1;
         private int mWhichSize = SIZE_TOTAL;
@@ -866,6 +889,7 @@
         private boolean mHasReceivedLoadEntries;
         private boolean mHasReceivedBridgeCallback;
         private FileViewHolderController mExtraViewController;
+        private SearchFilter mSearchFilter;
 
         // This is to remember and restore the last scroll position when this
         // fragment is paused. We need this special handling because app entries are added gradually
@@ -1100,6 +1124,13 @@
             });
         }
 
+        public void filterSearch(String query) {
+            if (mSearchFilter == null) {
+                mSearchFilter = new SearchFilter();
+            }
+            mSearchFilter.filter(query);
+        }
+
         @VisibleForTesting
         static boolean shouldUseStableItemHeight(int listType) {
             return true;
@@ -1146,6 +1177,7 @@
                 entries = removeDuplicateIgnoringUser(entries);
             }
             mEntries = entries;
+            mOriginalEntries = entries;
             notifyDataSetChanged();
             if (getItemCount() == 0) {
                 mManageApplications.mRecyclerView.setVisibility(View.GONE);
@@ -1153,6 +1185,14 @@
             } else {
                 mManageApplications.mEmptyView.setVisibility(View.GONE);
                 mManageApplications.mRecyclerView.setVisibility(View.VISIBLE);
+
+                if (mManageApplications.mSearchView != null
+                        && mManageApplications.mSearchView.isVisibleToUser()) {
+                    final CharSequence query = mManageApplications.mSearchView.getQuery();
+                    if (!TextUtils.isEmpty(query)) {
+                        filterSearch(query.toString());
+                    }
+                }
             }
             // Restore the last scroll position if the number of entries added so far is bigger than
             // it.
@@ -1405,6 +1445,38 @@
                 }
             }
         }
+
+        /**
+         * An array filter that constrains the content of the array adapter with a substring.
+         * Item that does not contains the specified substring will be removed from the list.</p>
+         */
+        private class SearchFilter extends Filter {
+            @WorkerThread
+            @Override
+            protected FilterResults performFiltering(CharSequence query) {
+                final ArrayList<ApplicationsState.AppEntry> matchedEntries;
+                if (TextUtils.isEmpty(query)) {
+                    matchedEntries = mOriginalEntries;
+                } else {
+                    matchedEntries = new ArrayList<>();
+                    for (ApplicationsState.AppEntry entry : mOriginalEntries) {
+                        if (entry.label.toLowerCase().contains(query.toString().toLowerCase())) {
+                            matchedEntries.add(entry);
+                        }
+                    }
+                }
+                final FilterResults results = new FilterResults();
+                results.values = matchedEntries;
+                results.count = matchedEntries.size();
+                return results;
+            }
+
+            @Override
+            protected void publishResults(CharSequence constraint, FilterResults results) {
+                mEntries = (ArrayList<ApplicationsState.AppEntry>) results.values;
+                notifyDataSetChanged();
+            }
+        }
     }
 
     private static class SummaryProvider implements SummaryLoader.SummaryProvider {
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
index 4bb2103..a438f09 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
@@ -22,9 +22,9 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 /**
  * This class adds two buttons: one to connect/disconnect from a device (depending on the current
@@ -35,7 +35,7 @@
     private boolean mIsConnected;
 
     private boolean mConnectButtonInitialized;
-    private ActionButtonPreference mActionButtons;
+    private ActionButtonsPreference mActionButtons;
 
     public BluetoothDetailsButtonsController(Context context, PreferenceFragmentCompat fragment,
             CachedBluetoothDevice device, Lifecycle lifecycle) {
@@ -51,7 +51,8 @@
 
     @Override
     protected void init(PreferenceScreen screen) {
-        mActionButtons = ((ActionButtonPreference) screen.findPreference(getPreferenceKey()))
+        mActionButtons = ((ActionButtonsPreference) screen.findPreference(
+                getPreferenceKey()))
                 .setButton1Text(R.string.forget)
                 .setButton1Icon(R.drawable.ic_settings_delete)
                 .setButton1OnClickListener((view) -> onForgetButtonPressed())
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
index de8902a..19339cd 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
@@ -199,20 +199,7 @@
 
     private void onNegative() {
         if (DEBUG) Log.d(TAG, "onNegative");
-
-        boolean always = true;
-        if (mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) {
-            LocalBluetoothManager bluetoothManager = Utils.getLocalBtManager(this);
-            CachedBluetoothDeviceManager cachedDeviceManager =
-                    bluetoothManager.getCachedDeviceManager();
-            CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
-            if (cachedDevice == null) {
-                cachedDevice = cachedDeviceManager.addDevice(mDevice);
-            }
-            always = cachedDevice.checkAndIncreaseMessageRejectionCount();
-        }
-
-        sendReplyIntentToReceiver(false, always);
+        sendReplyIntentToReceiver(false, true);
     }
 
     private void sendReplyIntentToReceiver(final boolean allowed, final boolean always) {
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index 0a26b79..b350778 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -24,7 +24,7 @@
     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";
     public static final String WIFI_MAC_RANDOMIZATION = "settings_wifi_mac_randomization";
     public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
+    public static final String WIFI_SHARING = "settings_wifi_sharing";
 }
diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java
index 9fdeeef..ce5c505 100644
--- a/src/com/android/settings/core/PreferenceXmlParserUtils.java
+++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java
@@ -55,6 +55,8 @@
     private static final List<String> SUPPORTED_PREF_TYPES = Arrays.asList(
             "Preference", "PreferenceCategory", "PreferenceScreen",
             "com.android.settings.widget.WorkOnlyCategory");
+    public static final int PREPEND_VALUE = 0;
+    public static final int APPEND_VALUE = 1;
 
     /**
      * Flag definition to indicate which metadata should be extracted when
@@ -84,6 +86,7 @@
         int FLAG_NEED_KEYWORDS = 1 << 8;
         int FLAG_NEED_SEARCHABLE = 1 << 9;
         int FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE = 1 << 10;
+        int FLAG_NEED_PREF_APPEND = 1 << 11;
     }
 
     public static final String METADATA_PREF_TYPE = "type";
@@ -97,6 +100,7 @@
     public static final String METADATA_SEARCHABLE = "searchable";
     public static final String METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE =
             "allow_dynamic_summary_in_slice";
+    public static final String METADATA_APPEND = "staticPreferenceLocation";
 
     private static final String ENTRIES_SEPARATOR = "|";
 
@@ -184,14 +188,13 @@
             // Parse next until start tag is found
         }
         final int outerDepth = parser.getDepth();
-
+        final boolean hasPrefScreenFlag = hasFlag(flags, MetadataFlag.FLAG_INCLUDE_PREF_SCREEN);
         do {
             if (type != XmlPullParser.START_TAG) {
                 continue;
             }
             final String nodeName = parser.getName();
-            if (!hasFlag(flags, MetadataFlag.FLAG_INCLUDE_PREF_SCREEN)
-                    && TextUtils.equals(PREF_SCREEN_TAG, nodeName)) {
+            if (!hasPrefScreenFlag && TextUtils.equals(PREF_SCREEN_TAG, nodeName)) {
                 continue;
             }
             if (!SUPPORTED_PREF_TYPES.contains(nodeName) && !nodeName.endsWith("Preference")) {
@@ -199,8 +202,14 @@
             }
             final Bundle preferenceMetadata = new Bundle();
             final AttributeSet attrs = Xml.asAttributeSet(parser);
+
             final TypedArray preferenceAttributes = context.obtainStyledAttributes(attrs,
                     R.styleable.Preference);
+            TypedArray preferenceScreenAttributes = null;
+            if (hasPrefScreenFlag) {
+                preferenceScreenAttributes = context.obtainStyledAttributes(
+                        attrs, R.styleable.PreferenceScreen);
+            }
 
             if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TYPE)) {
                 preferenceMetadata.putString(METADATA_PREF_TYPE, nodeName);
@@ -236,6 +245,10 @@
                 preferenceMetadata.putBoolean(METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE,
                         isDynamicSummaryAllowed(preferenceAttributes));
             }
+            if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_APPEND) && hasPrefScreenFlag) {
+                preferenceMetadata.putBoolean(METADATA_APPEND,
+                        isAppended(preferenceScreenAttributes));
+            }
             metadata.add(preferenceMetadata);
 
             preferenceAttributes.recycle();
@@ -325,7 +338,12 @@
                 false /* default */);
     }
 
-    private static String getKeywords(TypedArray styleAttributes) {
-        return styleAttributes.getString(R.styleable.Preference_keywords);
+    private static String getKeywords(TypedArray styledAttributes) {
+        return styledAttributes.getString(R.styleable.Preference_keywords);
+    }
+
+    private static boolean isAppended(TypedArray styledAttributes) {
+        return styledAttributes.getInt(R.styleable.PreferenceScreen_staticPreferenceLocation,
+            PREPEND_VALUE) == APPEND_VALUE;
     }
 }
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index 8b5d521..2f447d4 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -28,6 +28,7 @@
 import com.android.settings.development.DevelopmentSettingsDashboardFragment;
 import com.android.settings.deviceinfo.StorageDashboardFragment;
 import com.android.settings.display.NightDisplaySettings;
+import com.android.settings.enterprise.EnterprisePrivacySettings;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.gestures.GestureSettings;
 import com.android.settings.homepage.TopLevelSettings;
@@ -107,6 +108,8 @@
                 CategoryKey.CATEGORY_NIGHT_DISPLAY);
         PARENT_TO_CATEGORY_KEY_MAP.put(PrivacyDashboardFragment.class.getName(),
                 CategoryKey.CATEGORY_PRIVACY);
+        PARENT_TO_CATEGORY_KEY_MAP.put(EnterprisePrivacySettings.class.getName(),
+                CategoryKey.CATEGORY_ENTERPRISE_PRIVACY);
 
         CATEGORY_KEY_TO_PARENT_MAP = new ArrayMap<>(PARENT_TO_CATEGORY_KEY_MAP.size());
 
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 78aa6c2..b6c95dd 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.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. You may obtain a copy of the License at
@@ -22,13 +22,8 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.net.INetworkStatsSession;
-import android.net.NetworkPolicy;
-import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.net.TrafficStats;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.IconDrawableFactory;
@@ -51,11 +46,13 @@
 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.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
 import com.android.settingslib.net.UidDetail;
 import com.android.settingslib.net.UidDetailProvider;
 
+import java.util.List;
+
 public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceChangeListener,
         DataSaverBackend.Listener {
 
@@ -73,7 +70,7 @@
     private static final String KEY_CYCLE = "cycle";
     private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
 
-    private static final int LOADER_CHART_DATA = 2;
+    private static final int LOADER_APP_USAGE_DATA = 2;
     private static final int LOADER_APP_PREF = 3;
 
     private PackageManager mPackageManager;
@@ -88,14 +85,10 @@
     private Drawable mIcon;
     private CharSequence mLabel;
     private String mPackageName;
-    private INetworkStatsSession mStatsSession;
     private CycleAdapter mCycleAdapter;
 
-    private long mStart;
-    private long mEnd;
-    private ChartData mChartData;
+    private List<NetworkCycleDataForUid> mUsageData;
     private NetworkTemplate mTemplate;
-    private NetworkPolicy mPolicy;
     private AppItem mAppItem;
     private Intent mAppSettingsIntent;
     private SpinnerPreference mCycle;
@@ -108,12 +101,6 @@
         mPackageManager = getPackageManager();
         final Bundle args = getArguments();
 
-        try {
-            mStatsSession = services.mStatsService.openSession();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-
         mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null;
         mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE)
                 : null;
@@ -210,20 +197,13 @@
     }
 
     @Override
-    public void onDestroy() {
-        TrafficStats.closeQuietly(mStatsSession);
-        super.onDestroy();
-    }
-
-    @Override
     public void onResume() {
         super.onResume();
         if (mDataSaverBackend != null) {
             mDataSaverBackend.addListener(this);
         }
-        mPolicy = services.mPolicyEditor.getPolicy(mTemplate);
-        LoaderManager.getInstance(this).restartLoader(LOADER_CHART_DATA,
-                ChartDataLoaderCompat.buildArgs(mTemplate, mAppItem), mChartDataCallbacks);
+        LoaderManager.getInstance(this).restartLoader(LOADER_APP_USAGE_DATA, null /* args */,
+                mUidDataCallbacks);
         updatePrefs();
     }
 
@@ -301,19 +281,17 @@
         }
     }
 
-    private void bindData() {
+    @VisibleForTesting
+    void bindData(int position) {
         final long backgroundBytes, foregroundBytes;
-        if (mChartData == null || mStart == 0) {
+        if (mUsageData == null || position >= mUsageData.size()) {
             backgroundBytes = foregroundBytes = 0;
             mCycle.setVisible(false);
         } else {
             mCycle.setVisible(true);
-            final long now = System.currentTimeMillis();
-            NetworkStatsHistory.Entry entry = null;
-            entry = mChartData.detailDefault.getValues(mStart, mEnd, now, entry);
-            backgroundBytes = entry.rxBytes + entry.txBytes;
-            entry = mChartData.detailForeground.getValues(mStart, mEnd, now, entry);
-            foregroundBytes = entry.rxBytes + entry.txBytes;
+            final NetworkCycleDataForUid data = mUsageData.get(position);
+            backgroundBytes = data.getBackgroudUsage();
+            foregroundBytes = data.getForegroudUsage();
         }
         final long totalBytes = backgroundBytes + foregroundBytes;
         final Context context = getContext();
@@ -377,11 +355,7 @@
             new AdapterView.OnItemSelectedListener() {
         @Override
         public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem) mCycle.getSelectedItem();
-
-            mStart = cycle.start;
-            mEnd = cycle.end;
-            bindData();
+            bindData(position);
         }
 
         @Override
@@ -390,24 +364,30 @@
         }
     };
 
-    private final LoaderManager.LoaderCallbacks<ChartData> mChartDataCallbacks =
-            new LoaderManager.LoaderCallbacks<ChartData>() {
-        @Override
-        public Loader<ChartData> onCreateLoader(int id, Bundle args) {
-            return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
-        }
+    private final LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>> mUidDataCallbacks =
+        new LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>() {
+            @Override
+            public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+                return NetworkCycleDataForUidLoader.builder(getContext())
+                    .setUid(mAppItem.key)
+                    .setRetrieveDetail(true)
+                    .setNetworkTemplate(mTemplate)
+                    .setSubscriberId(mTemplate.getSubscriberId())
+                    .build();
+            }
 
-        @Override
-        public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
-            mChartData = data;
-            mCycleAdapter.updateCycleList(mPolicy, mChartData);
-            bindData();
-        }
+            @Override
+            public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+                    List<NetworkCycleDataForUid> data) {
+                mUsageData = data;
+                mCycleAdapter.updateCycleList(data);
+                bindData(0 /* position */);
+            }
 
-        @Override
-        public void onLoaderReset(Loader<ChartData> loader) {
-        }
-    };
+            @Override
+            public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
+            }
+        };
 
     private final LoaderManager.LoaderCallbacks<ArraySet<Preference>> mAppPrefCallbacks =
         new LoaderManager.LoaderCallbacks<ArraySet<Preference>>() {
diff --git a/src/com/android/settings/datausage/AppDataUsageV2.java b/src/com/android/settings/datausage/AppDataUsageV2.java
deleted file mode 100644
index 6a31726..0000000
--- a/src/com/android/settings/datausage/AppDataUsageV2.java
+++ /dev/null
@@ -1,432 +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.datausage;
-
-import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.util.IconDrawableFactory;
-import android.util.Log;
-import android.view.View;
-import android.widget.AdapterView;
-
-import androidx.annotation.VisibleForTesting;
-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;
-import com.android.settings.R;
-import com.android.settings.applications.AppInfoBase;
-import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-import com.android.settingslib.net.NetworkCycleDataForUidLoader;
-import com.android.settingslib.net.UidDetail;
-import com.android.settingslib.net.UidDetailProvider;
-
-import java.util.List;
-
-public class AppDataUsageV2 extends DataUsageBaseFragment implements OnPreferenceChangeListener,
-        DataSaverBackend.Listener {
-
-    private static final String TAG = "AppDataUsageV2";
-
-    public static final String ARG_APP_ITEM = "app_item";
-    public static final String ARG_NETWORK_TEMPLATE = "network_template";
-
-    private static final String KEY_TOTAL_USAGE = "total_usage";
-    private static final String KEY_FOREGROUND_USAGE = "foreground_usage";
-    private static final String KEY_BACKGROUND_USAGE = "background_usage";
-    private static final String KEY_APP_SETTINGS = "app_settings";
-    private static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
-    private static final String KEY_APP_LIST = "app_list";
-    private static final String KEY_CYCLE = "cycle";
-    private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
-
-    private static final int LOADER_APP_USAGE_DATA = 2;
-    private static final int LOADER_APP_PREF = 3;
-
-    private PackageManager mPackageManager;
-    private final ArraySet<String> mPackages = new ArraySet<>();
-    private Preference mTotalUsage;
-    private Preference mForegroundUsage;
-    private Preference mBackgroundUsage;
-    private Preference mAppSettings;
-    private RestrictedSwitchPreference mRestrictBackground;
-    private PreferenceCategory mAppList;
-
-    private Drawable mIcon;
-    private CharSequence mLabel;
-    private String mPackageName;
-    private CycleAdapter mCycleAdapter;
-
-    private List<NetworkCycleDataForUid> mUsageData;
-    private NetworkTemplate mTemplate;
-    private AppItem mAppItem;
-    private Intent mAppSettingsIntent;
-    private SpinnerPreference mCycle;
-    private RestrictedSwitchPreference mUnrestrictedData;
-    private DataSaverBackend mDataSaverBackend;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        mPackageManager = getPackageManager();
-        final Bundle args = getArguments();
-
-        mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null;
-        mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE)
-                : null;
-        if (mTemplate == null) {
-            Context context = getContext();
-            mTemplate = DataUsageUtils.getDefaultTemplate(context,
-                    DataUsageUtils.getDefaultSubscriptionId(context));
-        }
-        if (mAppItem == null) {
-            int uid = (args != null) ? args.getInt(AppInfoBase.ARG_PACKAGE_UID, -1)
-                    : getActivity().getIntent().getIntExtra(AppInfoBase.ARG_PACKAGE_UID, -1);
-            if (uid == -1) {
-                // TODO: Log error.
-                getActivity().finish();
-            } else {
-                addUid(uid);
-                mAppItem = new AppItem(uid);
-                mAppItem.addUid(uid);
-            }
-        } else {
-            for (int i = 0; i < mAppItem.uids.size(); i++) {
-                addUid(mAppItem.uids.keyAt(i));
-            }
-        }
-
-        mTotalUsage = findPreference(KEY_TOTAL_USAGE);
-        mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
-        mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE);
-
-        mCycle = (SpinnerPreference) findPreference(KEY_CYCLE);
-        mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener);
-
-        if (mAppItem.key > 0) {
-            if (mPackages.size() != 0) {
-                try {
-                    ApplicationInfo info = mPackageManager.getApplicationInfoAsUser(
-                            mPackages.valueAt(0), 0, UserHandle.getUserId(mAppItem.key));
-                    mIcon = IconDrawableFactory.newInstance(getActivity()).getBadgedIcon(info);
-                    mLabel = info.loadLabel(mPackageManager);
-                    mPackageName = info.packageName;
-                } catch (PackageManager.NameNotFoundException e) {
-                }
-            }
-            if (!UserHandle.isApp(mAppItem.key)) {
-                removePreference(KEY_UNRESTRICTED_DATA);
-                removePreference(KEY_RESTRICT_BACKGROUND);
-            } else {
-                mRestrictBackground = (RestrictedSwitchPreference) findPreference(
-                        KEY_RESTRICT_BACKGROUND);
-                mRestrictBackground.setOnPreferenceChangeListener(this);
-                mUnrestrictedData = (RestrictedSwitchPreference) findPreference(
-                        KEY_UNRESTRICTED_DATA);
-                mUnrestrictedData.setOnPreferenceChangeListener(this);
-            }
-            mDataSaverBackend = new DataSaverBackend(getContext());
-            mAppSettings = findPreference(KEY_APP_SETTINGS);
-
-            mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
-            mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
-
-            PackageManager pm = getPackageManager();
-            boolean matchFound = false;
-            for (String packageName : mPackages) {
-                mAppSettingsIntent.setPackage(packageName);
-                if (pm.resolveActivity(mAppSettingsIntent, 0) != null) {
-                    matchFound = true;
-                    break;
-                }
-            }
-            if (!matchFound) {
-                removePreference(KEY_APP_SETTINGS);
-                mAppSettings = null;
-            }
-
-            if (mPackages.size() > 1) {
-                mAppList = (PreferenceCategory) findPreference(KEY_APP_LIST);
-                LoaderManager.getInstance(this).restartLoader(LOADER_APP_PREF, Bundle.EMPTY,
-                        mAppPrefCallbacks);
-            } else {
-                removePreference(KEY_APP_LIST);
-            }
-        } else {
-            final Context context = getActivity();
-            UidDetail uidDetail = new UidDetailProvider(context).getUidDetail(mAppItem.key, true);
-            mIcon = uidDetail.icon;
-            mLabel = uidDetail.label;
-            mPackageName = context.getPackageName();
-
-            removePreference(KEY_UNRESTRICTED_DATA);
-            removePreference(KEY_APP_SETTINGS);
-            removePreference(KEY_RESTRICT_BACKGROUND);
-            removePreference(KEY_APP_LIST);
-        }
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (mDataSaverBackend != null) {
-            mDataSaverBackend.addListener(this);
-        }
-        LoaderManager.getInstance(this).restartLoader(LOADER_APP_USAGE_DATA, null /* args */,
-                mUidDataCallbacks);
-        updatePrefs();
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        if (mDataSaverBackend != null) {
-            mDataSaverBackend.remListener(this);
-        }
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (preference == mRestrictBackground) {
-            mDataSaverBackend.setIsBlacklisted(mAppItem.key, mPackageName, !(Boolean) newValue);
-            updatePrefs();
-            return true;
-        } else if (preference == mUnrestrictedData) {
-            mDataSaverBackend.setIsWhitelisted(mAppItem.key, mPackageName, (Boolean) newValue);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onPreferenceTreeClick(Preference preference) {
-        if (preference == mAppSettings) {
-            // TODO: target towards entire UID instead of just first package
-            getActivity().startActivityAsUser(mAppSettingsIntent, new UserHandle(
-                    UserHandle.getUserId(mAppItem.key)));
-            return true;
-        }
-        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 = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted(
-                getContext(), mPackageName, UserHandle.getUserId(mAppItem.key));
-        if (mRestrictBackground != null) {
-            mRestrictBackground.setChecked(!restrictBackground);
-            mRestrictBackground.setDisabledByAdmin(admin);
-        }
-        if (mUnrestrictedData != null) {
-            if (restrictBackground) {
-                mUnrestrictedData.setVisible(false);
-            } else {
-                mUnrestrictedData.setVisible(true);
-                mUnrestrictedData.setChecked(unrestrictData);
-                mUnrestrictedData.setDisabledByAdmin(admin);
-            }
-        }
-    }
-
-    private void addUid(int uid) {
-        String[] packages = getPackageManager().getPackagesForUid(uid);
-        if (packages != null) {
-            for (int i = 0; i < packages.length; i++) {
-                mPackages.add(packages[i]);
-            }
-        }
-    }
-
-    @VisibleForTesting
-    void bindData(int position) {
-        final long backgroundBytes, foregroundBytes;
-        if (mUsageData == null || position >= mUsageData.size()) {
-            backgroundBytes = foregroundBytes = 0;
-            mCycle.setVisible(false);
-        } else {
-            mCycle.setVisible(true);
-            final NetworkCycleDataForUid data = mUsageData.get(position);
-            backgroundBytes = data.getBackgroudUsage();
-            foregroundBytes = data.getForegroudUsage();
-        }
-        final long totalBytes = backgroundBytes + foregroundBytes;
-        final Context context = getContext();
-
-        mTotalUsage.setSummary(DataUsageUtils.formatDataUsage(context, totalBytes));
-        mForegroundUsage.setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
-        mBackgroundUsage.setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
-    }
-
-    private boolean getAppRestrictBackground() {
-        final int uid = mAppItem.key;
-        final int uidPolicy = services.mPolicyManager.getUidPolicy(uid);
-        return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
-    }
-
-    private boolean getUnrestrictData() {
-        if (mDataSaverBackend != null) {
-            return mDataSaverBackend.isWhitelisted(mAppItem.key);
-        }
-        return false;
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-
-        String pkg = mPackages.size() != 0 ? mPackages.valueAt(0) : null;
-        int uid = 0;
-        if (pkg != null) {
-            try {
-                uid = mPackageManager.getPackageUidAsUser(pkg,
-                        UserHandle.getUserId(mAppItem.key));
-            } catch (PackageManager.NameNotFoundException e) {
-                Log.w(TAG, "Skipping UID because cannot find package " + pkg);
-            }
-        }
-
-        final boolean showInfoButton = mAppItem.key > 0;
-
-        final Activity activity = getActivity();
-        final Preference pref = EntityHeaderController
-                .newInstance(activity, this, null /* header */)
-                .setRecyclerView(getListView(), getSettingsLifecycle())
-                .setUid(uid)
-                .setHasAppInfoLink(showInfoButton)
-                .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
-                        EntityHeaderController.ActionType.ACTION_NONE)
-                .setIcon(mIcon)
-                .setLabel(mLabel)
-                .setPackageName(pkg)
-                .done(activity, getPrefContext());
-        getPreferenceScreen().addPreference(pref);
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.APP_DATA_USAGE;
-    }
-
-    private AdapterView.OnItemSelectedListener mCycleListener =
-            new AdapterView.OnItemSelectedListener() {
-        @Override
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            bindData(position);
-        }
-
-        @Override
-        public void onNothingSelected(AdapterView<?> parent) {
-            // ignored
-        }
-    };
-
-    private final LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>> mUidDataCallbacks =
-        new LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>() {
-            @Override
-            public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
-                return NetworkCycleDataForUidLoader.builder(getContext())
-                    .setUid(mAppItem.key)
-                    .setRetrieveDetail(true)
-                    .setNetworkTemplate(mTemplate)
-                    .setSubscriberId(mTemplate.getSubscriberId())
-                    .build();
-            }
-
-            @Override
-            public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
-                    List<NetworkCycleDataForUid> data) {
-                mUsageData = data;
-                mCycleAdapter.updateCycleList(data);
-                bindData(0 /* position */);
-            }
-
-            @Override
-            public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
-            }
-        };
-
-    private final LoaderManager.LoaderCallbacks<ArraySet<Preference>> mAppPrefCallbacks =
-        new LoaderManager.LoaderCallbacks<ArraySet<Preference>>() {
-            @Override
-            public Loader<ArraySet<Preference>> onCreateLoader(int i, Bundle bundle) {
-                return new AppPrefLoader(getPrefContext(), mPackages, getPackageManager());
-            }
-
-            @Override
-            public void onLoadFinished(Loader<ArraySet<Preference>> loader,
-                    ArraySet<Preference> preferences) {
-                if (preferences != null && mAppList != null) {
-                    for (Preference preference : preferences) {
-                        mAppList.addPreference(preference);
-                    }
-                }
-            }
-
-            @Override
-            public void onLoaderReset(Loader<ArraySet<Preference>> loader) {
-            }
-        };
-
-    @Override
-    public void onDataSaverChanged(boolean isDataSaving) {
-
-    }
-
-    @Override
-    public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
-        if (mAppItem.uids.get(uid, false)) {
-            updatePrefs(getAppRestrictBackground(), isWhitelisted);
-        }
-    }
-
-    @Override
-    public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
-        if (mAppItem.uids.get(uid, false)) {
-            updatePrefs(isBlacklisted, getUnrestrictData());
-        }
-    }
-}
diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java
index a0cef3a..17f23c4 100644
--- a/src/com/android/settings/datausage/ChartDataUsagePreference.java
+++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java
@@ -16,14 +16,12 @@
 
 import android.content.Context;
 import android.net.NetworkPolicy;
-import android.net.NetworkStatsHistory;
 import android.net.TrafficStats;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.text.style.ForegroundColorSpan;
 import android.util.AttributeSet;
-import android.util.FeatureFlagUtils;
 import android.util.SparseIntArray;
 
 import androidx.annotation.VisibleForTesting;
@@ -32,7 +30,6 @@
 
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.widget.UsageView;
 import com.android.settingslib.net.NetworkCycleChartData;
 import com.android.settingslib.net.NetworkCycleData;
@@ -51,8 +48,6 @@
     private NetworkPolicy mPolicy;
     private long mStart;
     private long mEnd;
-    @Deprecated
-    private NetworkStatsHistory mNetwork;
     private NetworkCycleChartData mNetworkCycleChartData;
     private int mSecondaryColor;
     private int mSeriesColor;
@@ -69,24 +64,14 @@
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
         final UsageView chart = (UsageView) holder.findViewById(R.id.data_usage);
-        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
-            if (mNetworkCycleChartData == null) {
-                return;
-            }
-        } else {
-            if (mNetwork == null) {
-                return;
-            }
+        if (mNetworkCycleChartData == null) {
+            return;
         }
 
         final int top = getTop();
         chart.clearPaths();
         chart.configureGraph(toInt(mEnd - mStart), top);
-        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
-            calcPoints(chart, mNetworkCycleChartData.getUsageBuckets());
-        } else {
-            calcPoints(chart);
-        }
+        calcPoints(chart, mNetworkCycleChartData.getUsageBuckets());
         chart.setBottomLabels(new CharSequence[] {
                 Utils.formatDateRange(getContext(), mStart, mStart),
                 Utils.formatDateRange(getContext(), mEnd, mEnd),
@@ -96,58 +81,12 @@
     }
 
     public int getTop() {
-        long totalData = 0;
-        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
-            totalData = mNetworkCycleChartData.getTotalUsage();
-        } else {
-            NetworkStatsHistory.Entry entry = null;
-            final int start = mNetwork.getIndexBefore(mStart);
-            final int end = mNetwork.getIndexAfter(mEnd);
-
-            for (int i = start; i <= end; i++) {
-                entry = mNetwork.getValues(i, entry);
-
-                // increment by current bucket total
-                totalData += entry.rxBytes + entry.txBytes;
-            }
-        }
-        long policyMax = mPolicy != null ? Math.max(mPolicy.limitBytes, mPolicy.warningBytes) : 0;
+        final long totalData = mNetworkCycleChartData.getTotalUsage();
+        final long policyMax =
+            mPolicy != null ? Math.max(mPolicy.limitBytes, mPolicy.warningBytes) : 0;
         return (int) (Math.max(totalData, policyMax) / RESOLUTION);
     }
 
-    @Deprecated
-    @VisibleForTesting
-    void calcPoints(UsageView chart) {
-        SparseIntArray points = new SparseIntArray();
-        NetworkStatsHistory.Entry entry = null;
-
-        long totalData = 0;
-
-        final int start = mNetwork.getIndexAfter(mStart);
-        final int end = mNetwork.getIndexAfter(mEnd);
-        if (start < 0) return;
-
-        points.put(0, 0);
-        for (int i = start; i <= end; i++) {
-            entry = mNetwork.getValues(i, entry);
-
-            final long startTime = entry.bucketStart;
-            final long endTime = startTime + entry.bucketDuration;
-
-            // increment by current bucket total
-            totalData += entry.rxBytes + entry.txBytes;
-
-            if (i == 0) {
-                points.put(toInt(startTime - mStart) - 1, -1);
-            }
-            points.put(toInt(startTime - mStart + 1), (int) (totalData / RESOLUTION));
-            points.put(toInt(endTime - mStart), (int) (totalData / RESOLUTION));
-        }
-        if (points.size() > 1) {
-            chart.addPath(points);
-        }
-    }
-
     @VisibleForTesting
     void calcPoints(UsageView chart, List<NetworkCycleData> usageSummary) {
         if (usageSummary == null) {
@@ -156,9 +95,13 @@
         final SparseIntArray points = new SparseIntArray();
         points.put(0, 0);
 
+        final long now = System.currentTimeMillis();
         long totalData = 0;
         for (NetworkCycleData data : usageSummary) {
             final long startTime = data.getStartTime();
+            if (startTime > now) {
+                break;
+            }
             final long endTime = data.getEndTime();
 
             // increment by current bucket total
@@ -220,13 +163,6 @@
         notifyChanged();
     }
 
-    @Deprecated
-    public void setVisibleRange(long start, long end) {
-        mStart = start;
-        mEnd = end;
-        notifyChanged();
-    }
-
     public long getInspectStart() {
         return mStart;
     }
@@ -235,12 +171,6 @@
         return mEnd;
     }
 
-    @Deprecated
-    public void setNetworkStats(NetworkStatsHistory network) {
-        mNetwork = network;
-        notifyChanged();
-    }
-
     public void setNetworkCycleData(NetworkCycleChartData data) {
         mNetworkCycleChartData = data;
         mStart = data.getStartTime();
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 24192cd..326b0d4 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.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. You may obtain a copy of the License at
@@ -15,20 +15,22 @@
 package com.android.settings.datausage;
 
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
+import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
 import static android.net.TrafficStats.UID_REMOVED;
 import static android.net.TrafficStats.UID_TETHERING;
 
+import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStats.Bucket;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.UserInfo;
 import android.graphics.Color;
-import android.net.INetworkStatsSession;
+import android.net.ConnectivityManager;
 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;
@@ -37,6 +39,7 @@
 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;
@@ -58,9 +61,9 @@
 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.NetworkCycleChartDataLoader;
+import com.android.settingslib.net.NetworkCycleChartData;
+import com.android.settingslib.net.NetworkStatsSummaryLoader;
 import com.android.settingslib.net.UidDetailProvider;
 
 import java.util.ArrayList;
@@ -70,16 +73,12 @@
 /**
  * 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
  */
-@Deprecated
 public class DataUsageList extends DataUsageBaseFragment {
 
-    public static final String EXTRA_SUB_ID = "sub_id";
-    public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+    static final String EXTRA_SUB_ID = "sub_id";
+    static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+    static final String EXTRA_NETWORK_TYPE = "network_type";
 
     private static final String TAG = "DataUsageList";
     private static final boolean LOGD = false;
@@ -87,6 +86,9 @@
     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 String KEY_TEMPLATE = "template";
+    private static final String KEY_APP = "app";
+    private static final String KEY_FIELDS = "fields";
 
     private static final int LOADER_CHART_DATA = 2;
     private static final int LOADER_SUMMARY = 3;
@@ -99,14 +101,16 @@
                 }
             };
 
-    private INetworkStatsSession mStatsSession;
     private ChartDataUsagePreference mChart;
+    private TelephonyManager mTelephonyManager;
 
     @VisibleForTesting
     NetworkTemplate mTemplate;
     @VisibleForTesting
     int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    private ChartData mChartData;
+    @VisibleForTesting
+    int mNetworkType;
+    private List<NetworkCycleChartData> mCycleData;
 
     private LoadingViewController mLoadingViewController;
     private UidDetailProvider mUidDetailProvider;
@@ -116,7 +120,6 @@
     private PreferenceGroup mApps;
     private View mHeader;
 
-
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.DATA_USAGE_LIST;
@@ -125,21 +128,15 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        final Context context = getActivity();
+        final Activity activity = getActivity();
 
         if (!isBandwidthControlEnabled()) {
             Log.w(TAG, "No bandwidth control; leaving");
-            getActivity().finish();
+            activity.finish();
         }
 
-        try {
-            mStatsSession = services.mStatsService.openSession();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-
-        mUidDetailProvider = new UidDetailProvider(context);
-
+        mUidDetailProvider = new UidDetailProvider(activity);
+        mTelephonyManager = activity.getSystemService(TelephonyManager.class);
         mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
         mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
         mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
@@ -193,23 +190,7 @@
     public void onResume() {
         super.onResume();
         mDataStateListener.setListener(true, mSubId, getContext());
-
-        // kick off background task to update stats
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                try {
-                    services.mStatsService.forceUpdate();
-                } catch (RemoteException e) {
-                }
-                return null;
-            }
-
-            @Override
-            protected void onPostExecute(Void result) {
-                updateBody();
-            }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        updateBody();
     }
 
     @Override
@@ -223,8 +204,6 @@
         mUidDetailProvider.clearCache();
         mUidDetailProvider = null;
 
-        TrafficStats.closeQuietly(mStatsSession);
-
         super.onDestroy();
     }
 
@@ -243,6 +222,7 @@
         if (args != null) {
             mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
             mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
+            mNetworkType = args.getInt(EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_MOBILE);
         }
         if (mTemplate == null && mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
             final Intent intent = getIntent();
@@ -253,8 +233,7 @@
     }
 
     /**
-     * Update body content based on current tab. Loads
-     * {@link NetworkStatsHistory} and {@link NetworkPolicy} from system, and
+     * Update body content based on current tab. Loads network cycle data from system, and
      * binds them to visible controls.
      */
     private void updateBody() {
@@ -266,7 +245,7 @@
         // 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);
+                buildArgs(mTemplate), mNetworkCycleDataCallbacks);
 
         // detail mode can change visible menus, invalidate
         getActivity().invalidateOptionsMenu();
@@ -286,6 +265,14 @@
         mChart.setColors(seriesColor, secondaryColor);
     }
 
+    private Bundle buildArgs(NetworkTemplate template) {
+        final Bundle args = new Bundle();
+        args.putParcelable(KEY_TEMPLATE, template);
+        args.putParcelable(KEY_APP, null);
+        args.putInt(KEY_FIELDS, FIELD_RX_BYTES | FIELD_TX_BYTES);
+        return args;
+    }
+
     /**
      * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
      * current {@link #mTemplate}.
@@ -305,7 +292,7 @@
         }
 
         // generate cycle list based on policy and available history
-        if (mCycleAdapter.updateCycleList(policy, mChartData)) {
+        if (mCycleAdapter.updateCycleList(mCycleData)) {
             updateDetailData();
         }
     }
@@ -318,23 +305,13 @@
     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);
+        getLoaderManager().restartLoader(LOADER_SUMMARY, null /* args */,
+                mNetworkStatsDetailCallbacks);
 
-        final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
-        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(context, totalBytes);
+        final long totalBytes = mCycleData != null
+            ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0;
+        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
         mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
     }
 
@@ -342,22 +319,26 @@
      * Bind the given {@link NetworkStats}, or {@code null} to clear list.
      */
     private void bindStats(NetworkStats stats, int[] restrictedUids) {
-        ArrayList<AppItem> items = new ArrayList<>();
+        mApps.removeAll();
+        if (stats == null) {
+            if (LOGD) {
+                Log.d(TAG, "No network stats data. App list cleared.");
+            }
+            return;
+        }
+
+        final ArrayList<AppItem> items = new ArrayList<>();
         long largest = 0;
 
         final int currentUserId = ActivityManager.getCurrentUser();
-        UserManager userManager = UserManager.get(getContext());
+        final 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);
-
+        final Bucket bucket = new Bucket();
+        while (stats.hasNextBucket() && stats.getNextBucket(bucket)) {
             // Decide how to collapse items together
-            final int uid = entry.uid;
-
+            final int uid = bucket.getUid();
             final int collapseKey;
             final int category;
             final int userId = UserHandle.getUserId(uid);
@@ -366,8 +347,8 @@
                     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);
+                        largest = accumulate(managedKey, knownItems, bucket,
+                            AppItem.CATEGORY_USER, items, largest);
                     }
                     // Add to app item.
                     collapseKey = uid;
@@ -391,8 +372,9 @@
                 collapseKey = android.os.Process.SYSTEM_UID;
                 category = AppItem.CATEGORY_APP;
             }
-            largest = accumulate(collapseKey, knownItems, entry, category, items, largest);
+            largest = accumulate(collapseKey, knownItems, bucket, category, items, largest);
         }
+        stats.close();
 
         final int restrictedUidsMax = restrictedUids.length;
         for (int i = 0; i < restrictedUidsMax; ++i) {
@@ -413,7 +395,6 @@
         }
 
         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(),
@@ -450,12 +431,12 @@
      *
      * @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 bucket       the network stats bucket to extract data usage from.
      * @param itemCategory the item is categorized on the list view by this category. Must be
      */
-    private long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
-            NetworkStats.Entry entry, int itemCategory, ArrayList<AppItem> items, long largest) {
-        final int uid = entry.uid;
+    private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
+            Bucket bucket, int itemCategory, ArrayList<AppItem> items, long largest) {
+        final int uid = bucket.getUid();
         AppItem item = knownItems.get(collapseKey);
         if (item == null) {
             item = new AppItem(collapseKey);
@@ -464,7 +445,7 @@
             knownItems.put(item.key, item);
         }
         item.addUid(uid);
-        item.total += entry.rxBytes + entry.txBytes;
+        item.total += bucket.getRxBytes() + bucket.getTxBytes();
         return Math.max(largest, item.total);
     }
 
@@ -481,7 +462,7 @@
 
             // update chart to show selected cycle, and update detail data
             // to match updated sweep bounds.
-            mChart.setVisibleRange(cycle.start, cycle.end);
+            mChart.setNetworkCycleData(mCycleData.get(position));
 
             updateDetailData();
         }
@@ -492,35 +473,41 @@
         }
     };
 
-    private final LoaderCallbacks<ChartData> mChartDataCallbacks = new LoaderCallbacks<
-            ChartData>() {
+    private final LoaderCallbacks<List<NetworkCycleChartData>> mNetworkCycleDataCallbacks =
+            new LoaderCallbacks<List<NetworkCycleChartData>>() {
         @Override
-        public Loader<ChartData> onCreateLoader(int id, Bundle args) {
-            return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
+        public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
+            return NetworkCycleChartDataLoader.builder(getContext())
+                    .setNetworkTemplate(mTemplate)
+                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
+                    .build();
         }
 
         @Override
-        public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
+        public void onLoadFinished(Loader<List<NetworkCycleChartData>> loader,
+                List<NetworkCycleChartData> data) {
             mLoadingViewController.showContent(false /* animate */);
-            mChartData = data;
-            mChart.setNetworkStats(mChartData.network);
-
+            mCycleData = data;
             // calculate policy cycles based on available data
             updatePolicy();
         }
 
         @Override
-        public void onLoaderReset(Loader<ChartData> loader) {
-            mChartData = null;
-            mChart.setNetworkStats(null);
+        public void onLoaderReset(Loader<List<NetworkCycleChartData>> loader) {
+            mCycleData = null;
         }
     };
 
-    private final LoaderCallbacks<NetworkStats> mSummaryCallbacks = new LoaderCallbacks<
-            NetworkStats>() {
+    private final LoaderCallbacks<NetworkStats> mNetworkStatsDetailCallbacks =
+            new LoaderCallbacks<NetworkStats>() {
         @Override
         public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
-            return new SummaryForAllUidLoaderCompat(getActivity(), mStatsSession, args);
+            return new NetworkStatsSummaryLoader.Builder(getContext())
+                    .setStartTime(mChart.getInspectStart())
+                    .setEndTime(mChart.getInspectEnd())
+                    .setNetworkType(mNetworkType)
+                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
+                    .build();
         }
 
         @Override
diff --git a/src/com/android/settings/datausage/DataUsageListV2.java b/src/com/android/settings/datausage/DataUsageListV2.java
deleted file mode 100644
index 3a71935..0000000
--- a/src/com/android/settings/datausage/DataUsageListV2.java
+++ /dev/null
@@ -1,527 +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.datausage;
-
-import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.TrafficStats.UID_REMOVED;
-import static android.net.TrafficStats.UID_TETHERING;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.usage.NetworkStats;
-import android.app.usage.NetworkStats.Bucket;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.UserInfo;
-import android.graphics.Color;
-import android.net.ConnectivityManager;
-import android.net.NetworkPolicy;
-import android.net.NetworkTemplate;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.RemoteException;
-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.ChartDataLoaderCompat;
-import com.android.settingslib.net.NetworkCycleChartDataLoader;
-import com.android.settingslib.net.NetworkCycleChartData;
-import com.android.settingslib.net.NetworkStatsSummaryLoader;
-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 {
-
-    static final String EXTRA_SUB_ID = "sub_id";
-    static final String EXTRA_NETWORK_TEMPLATE = "network_template";
-    static final String EXTRA_NETWORK_TYPE = "network_type";
-
-    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 ChartDataUsagePreference mChart;
-    private TelephonyManager mTelephonyManager;
-
-    @VisibleForTesting
-    NetworkTemplate mTemplate;
-    @VisibleForTesting
-    int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    @VisibleForTesting
-    int mNetworkType;
-    private List<NetworkCycleChartData> mCycleData;
-
-    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 Activity activity = getActivity();
-
-        if (!isBandwidthControlEnabled()) {
-            Log.w(TAG, "No bandwidth control; leaving");
-            activity.finish();
-        }
-
-        mUidDetailProvider = new UidDetailProvider(activity);
-        mTelephonyManager = activity.getSystemService(TelephonyManager.class);
-        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);
-
-        mLoadingViewController = new LoadingViewController(
-                getView().findViewById(R.id.loading_container), getListView());
-        mLoadingViewController.showLoadingViewDelayed();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mDataStateListener.setListener(true, mSubId, getContext());
-        updateBody();
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mDataStateListener.setListener(false, mSubId, getContext());
-    }
-
-    @Override
-    public void onDestroy() {
-        mUidDetailProvider.clearCache();
-        mUidDetailProvider = null;
-
-        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);
-            mNetworkType = args.getInt(EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_MOBILE);
-        }
-        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 network cycle data 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), mNetworkCycleDataCallbacks);
-
-        // 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(mCycleData)) {
-            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()");
-
-        // kick off loader for detailed stats
-        getLoaderManager().restartLoader(LOADER_SUMMARY, null /* args */,
-                mNetworkStatsDetailCallbacks);
-
-        final long totalBytes = mCycleData != null
-            ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0;
-        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
-        mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
-    }
-
-    /**
-     * Bind the given {@link NetworkStats}, or {@code null} to clear list.
-     */
-    private void bindStats(NetworkStats stats, int[] restrictedUids) {
-        mApps.removeAll();
-        if (stats == null) {
-            if (LOGD) {
-                Log.d(TAG, "No network stats data. App list cleared.");
-            }
-            return;
-        }
-
-        final ArrayList<AppItem> items = new ArrayList<>();
-        long largest = 0;
-
-        final int currentUserId = ActivityManager.getCurrentUser();
-        final UserManager userManager = UserManager.get(getContext());
-        final List<UserHandle> profiles = userManager.getUserProfiles();
-        final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
-
-        final Bucket bucket = new Bucket();
-        while (stats.hasNextBucket() && stats.getNextBucket(bucket)) {
-            // Decide how to collapse items together
-            final int uid = bucket.getUid();
-            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, bucket,
-                            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, bucket, category, items, largest);
-        }
-        stats.close();
-
-        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);
-        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(AppDataUsageV2.ARG_APP_ITEM, item);
-        args.putParcelable(AppDataUsageV2.ARG_NETWORK_TEMPLATE, mTemplate);
-
-        new SubSettingLauncher(getContext())
-                .setDestination(AppDataUsageV2.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 bucket       the network stats bucket 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,
-            Bucket bucket, int itemCategory, ArrayList<AppItem> items, long largest) {
-        final int uid = bucket.getUid();
-        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 += bucket.getRxBytes() + bucket.getTxBytes();
-        return Math.max(largest, item.total);
-    }
-
-    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.setNetworkCycleData(mCycleData.get(position));
-
-            updateDetailData();
-        }
-
-        @Override
-        public void onNothingSelected(AdapterView<?> parent) {
-            // ignored
-        }
-    };
-
-    private final LoaderCallbacks<List<NetworkCycleChartData>> mNetworkCycleDataCallbacks =
-            new LoaderCallbacks<List<NetworkCycleChartData>>() {
-        @Override
-        public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
-            return NetworkCycleChartDataLoader.builder(getContext())
-                    .setNetworkTemplate(mTemplate)
-                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
-                    .build();
-        }
-
-        @Override
-        public void onLoadFinished(Loader<List<NetworkCycleChartData>> loader,
-                List<NetworkCycleChartData> data) {
-            mLoadingViewController.showContent(false /* animate */);
-            mCycleData = data;
-            // calculate policy cycles based on available data
-            updatePolicy();
-        }
-
-        @Override
-        public void onLoaderReset(Loader<List<NetworkCycleChartData>> loader) {
-            mCycleData = null;
-        }
-    };
-
-    private final LoaderCallbacks<NetworkStats> mNetworkStatsDetailCallbacks =
-            new LoaderCallbacks<NetworkStats>() {
-        @Override
-        public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
-            return new NetworkStatsSummaryLoader.Builder(getContext())
-                    .setStartTime(mChart.getInspectStart())
-                    .setEndTime(mChart.getInspectEnd())
-                    .setNetworkType(mNetworkType)
-                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
-                    .build();
-        }
-
-        @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 aa4e646..21c0503 100644
--- a/src/com/android/settings/datausage/DataUsagePreference.java
+++ b/src/com/android/settings/datausage/DataUsagePreference.java
@@ -21,7 +21,6 @@
 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;
@@ -29,7 +28,6 @@
 
 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;
 
@@ -78,23 +76,14 @@
     public Intent getIntent() {
         final Bundle args = new Bundle();
         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);
-            args.putInt(DataUsageListV2.EXTRA_NETWORK_TYPE, mTemplate.isMatchRuleMobile()
-                ? ConnectivityManager.TYPE_MOBILE : ConnectivityManager.TYPE_WIFI);
-            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);
-        }
+        args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
+        args.putInt(DataUsageList.EXTRA_SUB_ID, mSubId);
+        args.putInt(DataUsageList.EXTRA_NETWORK_TYPE, mTemplate.isMatchRuleMobile()
+            ? ConnectivityManager.TYPE_MOBILE : ConnectivityManager.TYPE_WIFI);
+        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/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index 53565ac..b3d0e61 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -22,12 +22,8 @@
 import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
 import android.net.NetworkTemplate;
-import android.net.TrafficStats;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -35,11 +31,8 @@
 import android.text.BidiFormatter;
 import android.text.format.Formatter;
 import android.text.format.Formatter.BytesResult;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 
-import com.android.settings.core.FeatureFlags;
-
 import java.util.List;
 
 /**
@@ -78,44 +71,21 @@
             return false;
         }
 
-        if (FeatureFlagUtils.isEnabled(context, FeatureFlags.DATA_USAGE_V2)) {
-            final TelephonyManager telephonyManager = TelephonyManager.from(context);;
-            final NetworkStatsManager networkStatsManager =
-                context.getSystemService(NetworkStatsManager.class);
-            boolean hasEthernetUsage = false;
-            try {
-                final Bucket bucket = networkStatsManager.querySummaryForUser(
-                    ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(),
-                    0L /* startTime */, System.currentTimeMillis() /* endTime */);
-                if (bucket != null) {
-                    hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0;
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Exception querying network detail.", e);
+        final TelephonyManager telephonyManager = TelephonyManager.from(context);;
+        final NetworkStatsManager networkStatsManager =
+            context.getSystemService(NetworkStatsManager.class);
+        boolean hasEthernetUsage = false;
+        try {
+            final Bucket bucket = networkStatsManager.querySummaryForUser(
+                ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(),
+                0L /* startTime */, System.currentTimeMillis() /* endTime */);
+            if (bucket != null) {
+                hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0;
             }
-            return hasEthernetUsage;
-        } else {
-            final long ethernetBytes;
-            try {
-                INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-
-                INetworkStatsSession statsSession = statsService.openSession();
-                if (statsSession != null) {
-                    ethernetBytes = statsSession.getSummaryForNetwork(
-                        NetworkTemplate.buildTemplateEthernet(), Long.MIN_VALUE, Long.MAX_VALUE)
-                        .getTotalBytes();
-                    TrafficStats.closeQuietly(statsSession);
-                } else {
-                    ethernetBytes = 0;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException(e);
-            }
-
-            // only show ethernet when both hardware present and traffic has occurred
-            return ethernetBytes > 0;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception querying network detail.", e);
         }
+        return hasEthernetUsage;
     }
 
     /**
diff --git a/src/com/android/settings/development/AngleEnabledAppPreferenceController.java b/src/com/android/settings/development/AngleEnabledAppPreferenceController.java
deleted file mode 100644
index 3a7f6bf..0000000
--- a/src/com/android/settings/development/AngleEnabledAppPreferenceController.java
+++ /dev/null
@@ -1,119 +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.development;
-
-import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes
-        .REQUEST_CODE_ANGLE_ENABLED_APP;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.development.DeveloperOptionsPreferenceController;
-
-public class AngleEnabledAppPreferenceController extends DeveloperOptionsPreferenceController
-        implements PreferenceControllerMixin, OnActivityResultListener {
-
-    private static final String ANGLE_ENABLED_APP_KEY = "angle_enabled_app";
-
-    private final DevelopmentSettingsDashboardFragment mFragment;
-    private final PackageManager mPackageManager;
-
-    public AngleEnabledAppPreferenceController(Context context,
-            DevelopmentSettingsDashboardFragment fragment) {
-        super(context);
-        mFragment = fragment;
-        mPackageManager = mContext.getPackageManager();
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return ANGLE_ENABLED_APP_KEY;
-    }
-
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        if (ANGLE_ENABLED_APP_KEY.equals(preference.getKey())) {
-            // pass it on to settings
-            final Intent intent = getActivityStartIntent();
-            mFragment.startActivityForResult(intent, REQUEST_CODE_ANGLE_ENABLED_APP);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        updatePreferenceSummary();
-    }
-
-    @Override
-    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (requestCode != REQUEST_CODE_ANGLE_ENABLED_APP || resultCode != Activity.RESULT_OK) {
-            return false;
-        }
-        Settings.Global.putString(mContext.getContentResolver(), Settings.Global.ANGLE_ENABLED_APP,
-                data.getAction());
-        updatePreferenceSummary();
-        return true;
-    }
-
-    @Override
-    protected void onDeveloperOptionsSwitchDisabled() {
-        super.onDeveloperOptionsSwitchDisabled();
-        mPreference.setSummary(mContext.getResources().getString(
-                R.string.angle_enabled_app_not_set));
-    }
-
-    @VisibleForTesting
-    Intent getActivityStartIntent() {
-        Intent intent = new Intent(mContext, AppPicker.class);
-        intent.putExtra(AppPicker.EXTRA_NON_SYSTEM, true /* value */);
-        return intent;
-    }
-
-    private void updatePreferenceSummary() {
-        final String angleEnabledApp = Settings.Global.getString(
-                mContext.getContentResolver(), Settings.Global.ANGLE_ENABLED_APP);
-        if (angleEnabledApp != null && angleEnabledApp.length() > 0) {
-            mPreference.setSummary(mContext.getResources().getString(
-                    R.string.angle_enabled_app_set,
-                    getAppLabel(angleEnabledApp)));
-        } else {
-            mPreference.setSummary(mContext.getResources().getString(
-                    R.string.angle_enabled_app_not_set));
-        }
-    }
-
-    private String getAppLabel(String angleEnabledApp) {
-        try {
-            final ApplicationInfo ai = mPackageManager.getApplicationInfo(angleEnabledApp,
-                    PackageManager.GET_DISABLED_COMPONENTS);
-            final CharSequence lab = mPackageManager.getApplicationLabel(ai);
-            return lab != null ? lab.toString() : angleEnabledApp;
-        } catch (PackageManager.NameNotFoundException e) {
-            return angleEnabledApp;
-        }
-    }
-}
diff --git a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
index 0fcec05..95e663b 100644
--- a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
@@ -66,6 +66,25 @@
         }
     }
 
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        final boolean offloadSupported =
+                SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false);
+        if (offloadSupported) {
+            ((SwitchPreference) mPreference).setChecked(false);
+            SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, "false");
+        }
+    }
+
+    public boolean isDefaultValue() {
+        final boolean offloadSupported =
+                SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false);
+        final boolean offloadDisabled =
+                    SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
+        return offloadSupported ? !offloadDisabled : true;
+    }
+
     public void onA2dpHwDialogConfirmed() {
         final boolean offloadDisabled =
                 SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
diff --git a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
index 3532a15..e65d2ad 100644
--- a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
+++ b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
@@ -26,7 +26,11 @@
 
     int REQUEST_MOCK_LOCATION_APP = 2;
 
-    int REQUEST_CODE_ANGLE_ENABLED_APP = 3;
+    int REQUEST_CODE_ANGLE_ALL_USE_ANGLE = 3;
 
-    int REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP = 4;
+    int REQUEST_CODE_ANGLE_DRIVER_PKGS = 4;
+
+    int REQUEST_CODE_ANGLE_DRIVER_VALUES = 5;
+
+    int REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP = 6;
 }
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 762686a..aa9918c 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -221,7 +221,16 @@
             if (isChecked) {
                 EnableDevelopmentSettingWarningDialog.show(this /* host */);
             } else {
-                disableDeveloperOptions();
+                final BluetoothA2dpHwOffloadPreferenceController controller =
+                        getDevelopmentOptionsController(
+                                BluetoothA2dpHwOffloadPreferenceController.class);
+                // If A2DP hardware offload isn't default value, we must reboot after disable
+                // developer options. Show a dialog for the user to confirm.
+                if (controller == null || controller.isDefaultValue()) {
+                    disableDeveloperOptions();
+                } else {
+                    DisableDevSettingsDialogFragment.show(this /* host */);
+                }
             }
         }
     }
@@ -380,6 +389,15 @@
         mSwitchBar.setChecked(false);
     }
 
+    void onDisableDevelopmentOptionsConfirmed() {
+        disableDeveloperOptions();
+    }
+
+    void onDisableDevelopmentOptionsRejected() {
+        // Reset the toggle
+        mSwitchBar.setChecked(true);
+    }
+
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment,
             BluetoothA2dpConfigStore bluetoothA2dpConfigStore) {
@@ -405,7 +423,6 @@
         controllers.add(new SelectDebugAppPreferenceController(context, fragment));
         controllers.add(new WaitForDebuggerPreferenceController(context));
         controllers.add(new EnableGpuDebugLayersPreferenceController(context));
-        controllers.add(new AngleEnabledAppPreferenceController(context, fragment));
         controllers.add(new UpdatedGfxDriverDevOptInPreferenceController(context, fragment));
         controllers.add(new VerifyAppsOverUsbPreferenceController(context));
         controllers.add(new LogdSizePreferenceController(context));
diff --git a/src/com/android/settings/development/DisableDevSettingsDialogFragment.java b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java
new file mode 100644
index 0000000..9b3ba58
--- /dev/null
+++ b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java
@@ -0,0 +1,88 @@
+/*
+ * 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.development;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.Fragment;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment
+        implements DialogInterface.OnClickListener {
+
+    public static final String TAG = "DisableDevSettingDlg";
+
+    @VisibleForTesting
+    static DisableDevSettingsDialogFragment newInstance() {
+        final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment();
+        return dialog;
+    }
+
+    public static void show(DevelopmentSettingsDashboardFragment host) {
+        final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment();
+        dialog.setTargetFragment(host, 0 /* requestCode */);
+        final FragmentManager manager = host.getActivity().getSupportFragmentManager();
+        dialog.show(manager, TAG);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.DIALOG_DISABLE_DEVELOPMENT_OPTIONS;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // Reuse the same text of disable_a2dp_hw_offload_dialog.
+        // The text is generic enough to be used for turning off Dev options.
+        return new AlertDialog.Builder(getActivity())
+                .setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message)
+                .setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title)
+                .setPositiveButton(
+                        R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this)
+                .setNegativeButton(
+                        R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this)
+                .create();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        Fragment fragment = getTargetFragment();
+        if (!(fragment instanceof DevelopmentSettingsDashboardFragment)){
+            Log.e(TAG, "getTargetFragment return unexpected type");
+        }
+
+        final DevelopmentSettingsDashboardFragment host =
+                (DevelopmentSettingsDashboardFragment) fragment;
+        if (which == DialogInterface.BUTTON_POSITIVE) {
+            host.onDisableDevelopmentOptionsConfirmed();
+            PowerManager pm = getContext().getSystemService(PowerManager.class);
+            pm.reboot(null);
+        } else {
+            host.onDisableDevelopmentOptionsRejected();
+        }
+    }
+}
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java b/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
index ce425c6..00a79a0 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
@@ -67,7 +67,8 @@
         if (migrate != null) {
             migrate.setVisible((privateVol != null)
                     && (privateVol.getType() == VolumeInfo.TYPE_PRIVATE)
-                    && !Objects.equals(mVolumeInfo, privateVol));
+                    && !Objects.equals(mVolumeInfo, privateVol)
+                    && privateVol.isMountedWritable());
         }
     }
 
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
index 1812974..f516926 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
@@ -416,7 +416,8 @@
                 .getPrimaryStorageCurrentVolume();
         migrate.setVisible((privateVol != null)
                 && (privateVol.getType() == VolumeInfo.TYPE_PRIVATE)
-                && !Objects.equals(mVolume, privateVol));
+                && !Objects.equals(mVolume, privateVol)
+                && privateVol.isMountedWritable());
     }
 
     @Override
diff --git a/src/com/android/settings/display/ColorModePreferenceController.java b/src/com/android/settings/display/ColorModePreferenceController.java
index 4679436..5d6a412 100644
--- a/src/com/android/settings/display/ColorModePreferenceController.java
+++ b/src/com/android/settings/display/ColorModePreferenceController.java
@@ -14,11 +14,7 @@
 package com.android.settings.display;
 
 import android.content.Context;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
+import android.hardware.display.ColorDisplayManager;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -29,19 +25,16 @@
 public class ColorModePreferenceController extends BasePreferenceController {
     private static final String TAG = "ColorModePreference";
 
-    private static final int SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGEMENT = 1030;
-
-    private final ConfigurationWrapper mConfigWrapper;
     private ColorDisplayController mColorDisplayController;
 
     public ColorModePreferenceController(Context context, String key) {
         super(context, key);
-        mConfigWrapper = new ConfigurationWrapper();
     }
 
     @Override
     public int getAvailabilityStatus() {
-        return mConfigWrapper.isDeviceColorManaged()
+        return mContext.getSystemService(ColorDisplayManager.class)
+                .isDeviceColorManaged()
                 && !getColorDisplayController().getAccessibilityTransformActivated() ?
                 AVAILABLE_UNSEARCHABLE : DISABLED_FOR_USER;
     }
@@ -68,32 +61,4 @@
         }
         return mColorDisplayController;
     }
-
-    @VisibleForTesting
-    static class ConfigurationWrapper {
-        private final IBinder mSurfaceFlinger;
-
-        ConfigurationWrapper() {
-            mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
-        }
-
-        boolean isDeviceColorManaged() {
-            if (mSurfaceFlinger != null) {
-                final Parcel data = Parcel.obtain();
-                final Parcel reply = Parcel.obtain();
-                data.writeInterfaceToken("android.ui.ISurfaceComposer");
-                try {
-                    mSurfaceFlinger.transact(SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGEMENT,
-                            data, reply, 0);
-                    return reply.readBoolean();
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "Failed to query color management support", ex);
-                } finally {
-                    data.recycle();
-                    reply.recycle();
-                }
-            }
-            return false;
-        }
-    }
 }
diff --git a/src/com/android/settings/display/NightDisplayAutoModePreferenceController.java b/src/com/android/settings/display/NightDisplayAutoModePreferenceController.java
index 8ad5e63..1710f51 100644
--- a/src/com/android/settings/display/NightDisplayAutoModePreferenceController.java
+++ b/src/com/android/settings/display/NightDisplayAutoModePreferenceController.java
@@ -17,7 +17,6 @@
 package com.android.settings.display;
 
 import android.content.Context;
-
 import android.hardware.display.ColorDisplayManager;
 
 import androidx.preference.DropDownPreference;
diff --git a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java b/src/com/android/settings/flashlight/FlashlightSlice.java
similarity index 66%
rename from src/com/android/settings/flashlight/FlashlightSliceBuilder.java
rename to src/com/android/settings/flashlight/FlashlightSlice.java
index 5833229..a2c4561 100644
--- a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
+++ b/src/com/android/settings/flashlight/FlashlightSlice.java
@@ -28,6 +28,7 @@
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraManager;
+import android.net.Uri;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.util.Log;
@@ -41,69 +42,78 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.slices.CustomSliceRegistry;
-import com.android.settings.slices.SliceBroadcastReceiver;
+import com.android.settings.slices.CustomSliceable;
 
 
 /**
  * Utility class to build a Flashlight Slice, and handle all associated actions.
  */
-public class FlashlightSliceBuilder {
+public class FlashlightSlice implements CustomSliceable {
 
-    private static final String TAG = "FlashlightSliceBuilder";
-
-    /**
-     * Action notifying a change on the Flashlight Slice.
-     */
-    public static final String ACTION_FLASHLIGHT_SLICE_CHANGED =
-            "com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
+    private static final String TAG = "FlashlightSlice";
 
     /**
      * Action broadcasting a change on whether flashlight is on or off.
      */
-    public static final String ACTION_FLASHLIGHT_CHANGED =
+    private static final String ACTION_FLASHLIGHT_CHANGED =
             "com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
 
-    public static final IntentFilter INTENT_FILTER = new IntentFilter(ACTION_FLASHLIGHT_CHANGED);
+    private final Context mContext;
 
-    private FlashlightSliceBuilder() {
+    public FlashlightSlice(Context context) {
+        mContext = context;
     }
 
-    public static Slice getSlice(Context context) {
-        if (!isFlashlightAvailable(context)) {
+    @Override
+    public Slice getSlice() {
+        if (!isFlashlightAvailable(mContext)) {
             return null;
         }
-        final PendingIntent toggleAction = getBroadcastIntent(context);
-        @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
+        final PendingIntent toggleAction = getBroadcastIntent(mContext);
+        @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
         final IconCompat icon =
-                IconCompat.createWithResource(context, R.drawable.ic_signal_flashlight);
-        return new ListBuilder(context, CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+                IconCompat.createWithResource(mContext, R.drawable.ic_signal_flashlight);
+        return new ListBuilder(mContext, CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
                 ListBuilder.INFINITY)
                 .setAccentColor(color)
                 .addRow(new RowBuilder()
-                        .setTitle(context.getText(R.string.power_flashlight))
+                        .setTitle(mContext.getText(R.string.power_flashlight))
                         .setTitleItem(icon, ICON_IMAGE)
                         .setPrimaryAction(
-                                SliceAction.createToggle(toggleAction, null, isFlashlightEnabled(context))))
+                                SliceAction.createToggle(toggleAction, null,
+                                        isFlashlightEnabled(mContext))))
                 .build();
     }
 
-    /**
-     * Update the current flashlight status to the boolean value keyed by
-     * {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
-     */
-    public static void handleUriChange(Context context, Intent intent) {
+    @Override
+    public Uri getUri() {
+        return CustomSliceRegistry.FLASHLIGHT_SLICE_URI;
+    }
+
+    @Override
+    public IntentFilter getIntentFilter() {
+        return new IntentFilter(ACTION_FLASHLIGHT_CHANGED);
+    }
+
+    @Override
+    public void onNotifyChange(Intent intent) {
         try {
-            final String cameraId = getCameraId(context);
+            final String cameraId = getCameraId(mContext);
             if (cameraId != null) {
                 final boolean state = intent.getBooleanExtra(
-                        EXTRA_TOGGLE_STATE, isFlashlightEnabled(context));
-                final CameraManager cameraManager = context.getSystemService(CameraManager.class);
+                        EXTRA_TOGGLE_STATE, isFlashlightEnabled(mContext));
+                final CameraManager cameraManager = mContext.getSystemService(CameraManager.class);
                 cameraManager.setTorchMode(cameraId, state);
             }
         } catch (CameraAccessException e) {
             Log.e(TAG, "Camera couldn't set torch mode.", e);
         }
-        context.getContentResolver().notifyChange(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, null);
+        mContext.getContentResolver().notifyChange(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, null);
+    }
+
+    @Override
+    public Intent getIntent() {
+        return null;
     }
 
     private static String getCameraId(Context context) throws CameraAccessException {
@@ -121,12 +131,6 @@
         return null;
     }
 
-    private static PendingIntent getBroadcastIntent(Context context) {
-        final Intent intent = new Intent(ACTION_FLASHLIGHT_SLICE_CHANGED);
-        intent.setClass(context, SliceBroadcastReceiver.class);
-        return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
-                PendingIntent.FLAG_CANCEL_CURRENT);
-    }
 
     private static boolean isFlashlightAvailable(Context context) {
         return Settings.Secure.getInt(
diff --git a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
index 2e9b5a5..00b7a0c 100644
--- a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
+++ b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
@@ -52,7 +52,7 @@
         for (AbstractPreferenceController controller : mGestureControllers) {
             isAvailable = isAvailable || controller.isAvailable();
         }
-        return isAvailable ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
+        return isAvailable ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     /**
@@ -101,4 +101,4 @@
         }
         return mContext.getText(R.string.language_input_gesture_summary_off);
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
index e437e2b..32a86e8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
@@ -16,8 +16,10 @@
 
 package com.android.settings.homepage.contextualcards;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.Intent;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -25,6 +27,7 @@
 import androidx.slice.widget.EventInfo;
 
 import com.android.settings.R;
+import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
 
 import java.util.List;
 
@@ -38,10 +41,6 @@
     // Contextual card shows, log card name and rank
     private static final int CONTEXTUAL_CARD_SHOW = 39;
 
-    // Contextual card is eligible to be shown, but doesn't rank high
-    // enough, log card name and score
-    private static final int CONTEXTUAL_CARD_NOT_SHOW = 40;
-
     // Contextual card is dismissed, log card name
     private static final int CONTEXTUAL_CARD_DISMISS = 41;
 
@@ -67,6 +66,11 @@
     // log type
     private static final String EXTRA_CONTEXTUALCARD_ACTION_TYPE = "type";
 
+    // displayed contextual cards
+    private static final String EXTRA_CONTEXTUALCARD_VISIBLE = "visible";
+
+    // hidden contextual cards
+    private static final String EXTRA_CONTEXTUALCARD_HIDDEN = "hidden";
 
     // Contextual card tap target
     private static final int TARGET_DEFAULT = 0;
@@ -82,6 +86,10 @@
 
     @Override
     public void logHomepageDisplay(Context context, Long latency) {
+        final Intent intent = new Intent();
+        intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_HOME_SHOW);
+        intent.putExtra(EXTRA_LATENCY, latency);
+        sendBroadcast(context, intent);
     }
 
     @Override
@@ -94,8 +102,13 @@
     }
 
     @Override
-    public void logContextualCardDisplay(Context context, List<ContextualCard> showCards,
+    public void logContextualCardDisplay(Context context, List<ContextualCard> visibleCards,
             List<ContextualCard> hiddenCards) {
+        final Intent intent = new Intent();
+        intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_SHOW);
+        intent.putExtra(EXTRA_CONTEXTUALCARD_VISIBLE, serialize(visibleCards));
+        intent.putExtra(EXTRA_CONTEXTUALCARD_HIDDEN, serialize(hiddenCards));
+        sendBroadcast(context, intent);
     }
 
     @Override
@@ -116,7 +129,7 @@
         final String action = context.getString(R.string.config_settingsintelligence_log_action);
         if (!TextUtils.isEmpty(action)) {
             intent.setAction(action);
-            context.sendBroadcast(intent);
+            context.sendBroadcastAsUser(intent, UserHandle.ALL);
         }
     }
 
@@ -133,4 +146,16 @@
                 return TARGET_DEFAULT;
         }
     }
+
+    @VisibleForTesting
+    @NonNull
+    byte[] serialize(List<ContextualCard> cards) {
+        final ContextualCardList.Builder builder = ContextualCardList.newBuilder();
+        cards.stream().forEach(card -> builder.addCard(
+                com.android.settings.intelligence.ContextualCardProto.ContextualCard.newBuilder()
+                        .setSliceUri(card.getSliceUri().toString())
+                        .setCardName(card.getName())
+                        .build()));
+        return builder.build().toByteArray();
+    }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 3ef4653..e631d22 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -20,6 +20,9 @@
 
 import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS;
 
+import static com.android.settings.slices.CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
+
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -34,7 +37,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.slice.Slice;
 
-import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.utils.AsyncLoaderCompat;
 
 import java.util.ArrayList;
@@ -103,27 +106,50 @@
         return getFinalDisplayableCards(result);
     }
 
+    // Get final displayed cards and log what cards will be displayed/hidden
     @VisibleForTesting
     List<ContextualCard> getFinalDisplayableCards(List<ContextualCard> candidates) {
-        List<ContextualCard> eligibleCards = filterEligibleCards(candidates);
-        eligibleCards = eligibleCards.stream().limit(DEFAULT_CARD_COUNT).collect(
-                Collectors.toList());
+        final List<ContextualCard> eligibleCards = filterEligibleCards(candidates);
+        final List<ContextualCard> visibleCards = new ArrayList<>();
+        final List<ContextualCard> hiddenCards = new ArrayList<>();
 
-        if (eligibleCards.size() <= 2 || getNumberOfLargeCard(eligibleCards) == 0) {
-            return eligibleCards;
+        final int size = eligibleCards.size();
+        for (int i = 0; i < size; i++) {
+            if (i < DEFAULT_CARD_COUNT) {
+                visibleCards.add(eligibleCards.get(i));
+            } else {
+                hiddenCards.add(eligibleCards.get(i));
+            }
         }
 
-        if (eligibleCards.size() == DEFAULT_CARD_COUNT) {
-            eligibleCards.remove(eligibleCards.size() - 1);
+        try {
+            // The maximum cards are four small cards OR
+            // one large card with two small cards OR
+            // two large cards
+            if (visibleCards.size() <= 2 || getNumberOfLargeCard(visibleCards) == 0) {
+                // four small cards
+                return visibleCards;
+            }
+
+            if (visibleCards.size() == DEFAULT_CARD_COUNT) {
+                hiddenCards.add(visibleCards.remove(visibleCards.size() - 1));
+            }
+
+            if (getNumberOfLargeCard(visibleCards) == 1) {
+                // One large card with two small cards
+                return visibleCards;
+            }
+
+            hiddenCards.add(visibleCards.remove(visibleCards.size() - 1));
+
+            // Two large cards
+            return visibleCards;
+        } finally {
+            final ContextualCardFeatureProvider contextualCardFeatureProvider =
+                    FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
+            contextualCardFeatureProvider.logContextualCardDisplay(mContext, visibleCards,
+                    hiddenCards);
         }
-
-        if (getNumberOfLargeCard(eligibleCards) == 1) {
-            return eligibleCards;
-        }
-
-        eligibleCards.remove(eligibleCards.size() - 1);
-
-        return eligibleCards;
     }
 
     @VisibleForTesting
@@ -169,8 +195,8 @@
 
     private int getNumberOfLargeCard(List<ContextualCard> cards) {
         return (int) cards.stream()
-                .filter(card -> card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI)
-                        || card.getSliceUri().equals(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI))
+                .filter(card -> card.getSliceUri().equals(WIFI_SLICE_URI)
+                        || card.getSliceUri().equals(BLUETOOTH_DEVICES_SLICE_URI))
                 .count();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 5f397d7..28ad0d3 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -16,8 +16,7 @@
 
 package com.android.settings.homepage.contextualcards;
 
-import static com.android.settings.homepage.contextualcards.ContextualCardLoader
-        .CARD_CONTENT_LOADER_ID;
+import static com.android.settings.homepage.contextualcards.ContextualCardLoader.CARD_CONTENT_LOADER_ID;
 
 import static java.util.stream.Collectors.groupingBy;
 
@@ -33,6 +32,7 @@
 import androidx.loader.app.LoaderManager;
 import androidx.loader.content.Loader;
 
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 
@@ -72,6 +72,7 @@
     private final List<LifecycleObserver> mLifecycleObservers;
 
     private ContextualCardUpdateListener mListener;
+    private long mStartTime;
 
     public ContextualCardManager(Context context, Lifecycle lifecycle) {
         mContext = context;
@@ -86,6 +87,7 @@
     }
 
     void loadContextualCards(ContextualCardsFragment fragment) {
+        mStartTime = System.currentTimeMillis();
         final CardContentLoaderCallbacks cardContentLoaderCallbacks =
                 new CardContentLoaderCallbacks(mContext);
         cardContentLoaderCallbacks.setListener(this);
@@ -168,6 +170,10 @@
     @Override
     public void onFinishCardLoading(List<ContextualCard> cards) {
         onContextualCardUpdated(cards.stream().collect(groupingBy(ContextualCard::getCardType)));
+        final long elapsedTime = System.currentTimeMillis() - mStartTime;
+        final ContextualCardFeatureProvider contextualCardFeatureProvider =
+                FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
+        contextualCardFeatureProvider.logHomepageDisplay(mContext, elapsedTime);
     }
 
     public ControllerRendererPool getControllerRendererPool() {
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 376bb83..d5500fb 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -40,8 +40,8 @@
                         .build();
         final ContextualCard connectedDeviceCard =
                 ContextualCard.newBuilder()
-                        .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
-                        .setCardName(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
+                        .setSliceUri(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI.toString())
+                        .setCardName(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI.toString())
                         .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
         final ContextualCard lowStorageCard =
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
index b0d6963..5271e12 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.homepage.contextualcards.deviceinfo;
 
-import static com.android.settings.slices.CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
-
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -37,6 +35,7 @@
 import com.android.settings.Utils;
 import com.android.settings.fuelgauge.BatteryInfo;
 import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
 import com.android.settings.slices.SliceBuilderUtils;
 
@@ -66,7 +65,8 @@
         final CharSequence title = mContext.getText(R.string.power_usage_summary_title);
         final SliceAction primarySliceAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
                 ListBuilder.ICON_IMAGE, title);
-        final Slice slice = new ListBuilder(mContext, BATTERY_INFO_SLICE_URI, ListBuilder.INFINITY)
+        final Slice slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_INFO_SLICE_URI,
+                ListBuilder.INFINITY)
                 .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
                 .setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
                 .addRow(new ListBuilder.RowBuilder()
@@ -81,7 +81,7 @@
 
     @Override
     public Uri getUri() {
-        return BATTERY_INFO_SLICE_URI;
+        return CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
     }
 
     @Override
@@ -95,7 +95,8 @@
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
                 PowerUsageSummary.class.getName(), "" /* key */, screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+                .setData(CustomSliceRegistry.BATTERY_INFO_SLICE_URI);
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
index bb78586..6e94f6d 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
@@ -94,7 +94,8 @@
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
                 DataUsageSummary.class.getName(), "" /* key */, screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+                .setData(CustomSliceRegistry.DATA_USAGE_SLICE_URI);
     }
 
     private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
index 694336d..1f75ab1 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
@@ -85,7 +85,8 @@
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
                 MyDeviceInfoFragment.class.getName(), "" /* key */, screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+                .setData(CustomSliceRegistry.DEVICE_INFO_SLICE_URI);
     }
 
     private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
index 2484e53..f8be2d6 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
@@ -16,9 +16,12 @@
 
 package com.android.settings.homepage.contextualcards.deviceinfo;
 
+import static com.android.settings.accounts.EmergencyInfoPreferenceController.ACTION_EDIT_EMERGENCY_INFO;
+
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.net.Uri;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -27,37 +30,57 @@
 
 import com.android.settings.R;
 import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
 
 // This is a slice helper class for EmergencyInfo
-public class EmergencyInfoSlice {
+public class EmergencyInfoSlice implements CustomSliceable {
 
-    private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
+    private final Context mContext;
 
-    public static Slice getSlice(Context context) {
-        final ListBuilder listBuilder = new ListBuilder(context,
+    public EmergencyInfoSlice(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public Slice getSlice() {
+        final ListBuilder listBuilder = new ListBuilder(mContext,
                 CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI,
                 ListBuilder.INFINITY);
         listBuilder.addRow(
                 new ListBuilder.RowBuilder()
-                        .setTitle(context.getText(R.string.emergency_info_title))
+                        .setTitle(mContext.getText(R.string.emergency_info_title))
                         .setSubtitle(
-                                context.getText(R.string.emergency_info_contextual_card_summary))
-                        .setPrimaryAction(createPrimaryAction(context)));
+                                mContext.getText(R.string.emergency_info_contextual_card_summary))
+                        .setPrimaryAction(createPrimaryAction()));
         return listBuilder.build();
     }
 
-    private static SliceAction createPrimaryAction(Context context) {
-        PendingIntent pendingIntent =
+    @Override
+    public Uri getUri() {
+        return CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI;
+    }
+
+    @Override
+    public Intent getIntent() {
+        return new Intent(ACTION_EDIT_EMERGENCY_INFO);
+    }
+
+    @Override
+    public void onNotifyChange(Intent intent) {
+    }
+
+    private SliceAction createPrimaryAction() {
+        final PendingIntent pendingIntent =
                 PendingIntent.getActivity(
-                        context,
+                        mContext,
                         0 /* requestCode */,
-                        new Intent(ACTION_EDIT_EMERGENCY_INFO),
+                        getIntent(),
                         PendingIntent.FLAG_UPDATE_CURRENT);
 
         return SliceAction.createDeeplink(
                 pendingIntent,
-                IconCompat.createWithResource(context, R.drawable.empty_icon),
+                IconCompat.createWithResource(mContext, R.drawable.empty_icon),
                 ListBuilder.ICON_IMAGE,
-                context.getText(R.string.emergency_info_title));
+                mContext.getText(R.string.emergency_info_title));
     }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
index eba831a..799a701 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
@@ -80,7 +80,8 @@
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
                 StorageDashboardFragment.class.getName(), "" /* key */, screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+                .setData(CustomSliceRegistry.STORAGE_SLICE_URI);
     }
 
     private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
similarity index 67%
rename from src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
rename to src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index 6a1f1f0..ad8d4a6 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -17,6 +17,7 @@
 package com.android.settings.homepage.contextualcards.slices;
 
 import android.app.PendingIntent;
+import android.app.settings.SettingsEnums;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +41,7 @@
 import com.android.settings.SubSettings;
 import com.android.settings.Utils;
 import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
+import com.android.settings.bluetooth.BluetoothPairingDetail;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.slices.CustomSliceRegistry;
@@ -48,7 +50,6 @@
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.core.instrumentation.Instrumentable;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -56,28 +57,27 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
-/**
- * TODO(b/114807655): Contextual Home Page - Connected Device
- *
- * Show connected device info if one is currently connected. UI for connected device should
- * match Connected Devices > Currently Connected Devices
- *
- * TODO This class will be refactor for Bluetooth connected devices only.
- */
-public class ConnectedDeviceSlice implements CustomSliceable {
+public class BluetoothDevicesSlice implements CustomSliceable {
 
     /**
-     * To sort the Bluetooth devices by {@link CachedBluetoothDevice}.
-     * Refer compareTo method from {@link com.android.settings.bluetooth.BluetoothDevicePreference}.
+     * TODO(b/114807655): Contextual Home Page - Connected Device
+     * Re-design sorting for new rule:
+     * Sorting rule: Audio Streaming > Last connected > Recently connected.
      */
     private static final Comparator<CachedBluetoothDevice> COMPARATOR
             = Comparator.naturalOrder();
 
-    private static final String TAG = "ConnectedDeviceSlice";
+    /**
+     * Add the "Pair new device" in the end of slice, when the number of Bluetooth devices is less
+     * than {@link #DEFAULT_EXPANDED_ROW_COUNT}.
+     */
+    private static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
+
+    private static final String TAG = "BluetoothDevicesSlice";
 
     private final Context mContext;
 
-    public ConnectedDeviceSlice(Context context) {
+    public BluetoothDevicesSlice(Context context) {
         mContext = context;
     }
 
@@ -94,47 +94,53 @@
 
     @Override
     public Uri getUri() {
-        return CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI;
+        return CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI;
     }
 
     @Override
     public Slice getSlice() {
         final IconCompat icon = IconCompat.createWithResource(mContext,
-                R.drawable.ic_homepage_connected_device);
-        final CharSequence title = mContext.getText(R.string.connected_devices_dashboard_title);
-        final CharSequence titleNoConnectedDevices = mContext.getText(
-                R.string.no_connected_devices);
+                R.drawable.ic_settings_bluetooth);
+        final CharSequence title = mContext.getText(R.string.bluetooth_devices);
+        final CharSequence titleNoBluetoothDevices = mContext.getText(
+                R.string.no_bluetooth_devices);
         final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext, 0,
                 getIntent(), 0);
         final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
                 ListBuilder.ICON_IMAGE, title);
         final ListBuilder listBuilder =
-                new ListBuilder(mContext, CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI,
+                new ListBuilder(mContext, CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI,
                         ListBuilder.INFINITY)
                         .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
 
-        // Get row builders by connected devices, e.g. Bluetooth.
+        // Get row builders by Bluetooth devices.
         final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilder(primarySliceAction);
 
-        // Return a header with IsError flag, if no connected devices.
+        // Return a header with IsError flag, if no Bluetooth devices.
         if (rows.isEmpty()) {
             return listBuilder.setHeader(new ListBuilder.HeaderBuilder()
-                    .setTitle(titleNoConnectedDevices)
+                    .setTitle(titleNoBluetoothDevices)
                     .setPrimaryAction(primarySliceAction))
                     .setIsError(true)
                     .build();
         }
 
-        // According the number of connected devices to set sub title of header.
+        // According the number of Bluetooth devices to set sub title of header.
         listBuilder.setHeader(new ListBuilder.HeaderBuilder()
                 .setTitle(title)
                 .setSubtitle(getSubTitle(rows.size()))
                 .setPrimaryAction(primarySliceAction));
 
-        // Add rows.
+        // Add bluetooth device rows.
         for (ListBuilder.RowBuilder rowBuilder : rows) {
             listBuilder.addRow(rowBuilder);
         }
+
+        // Add "Pair new device" if need.
+        if (rows.size() < DEFAULT_EXPANDED_ROW_COUNT) {
+            listBuilder.addRow(getPairNewDeviceRowBuilder());
+        }
+
         return listBuilder.build();
     }
 
@@ -147,7 +153,8 @@
                 ConnectedDeviceDashboardFragment.class.getName(), "" /* key */,
                 screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+                .setData(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI);
     }
 
     @Override
@@ -160,25 +167,30 @@
     }
 
     @VisibleForTesting
-    List<CachedBluetoothDevice> getBluetoothConnectedDevices() {
-        final List<CachedBluetoothDevice> connectedBluetoothList = new ArrayList<>();
+    List<CachedBluetoothDevice> getBluetoothDevices() {
+        final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>();
 
         // If Bluetooth is disable, skip to get the bluetooth devices.
         if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
-            Log.i(TAG, "Cannot get Bluetooth connected devices, Bluetooth is disabled.");
-            return connectedBluetoothList;
+            Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
+            return bluetoothDeviceList;
         }
 
         // Get the Bluetooth devices from LocalBluetoothManager.
         final LocalBluetoothManager bluetoothManager =
                 com.android.settings.bluetooth.Utils.getLocalBtManager(mContext);
         if (bluetoothManager == null) {
-            Log.i(TAG, "Cannot get Bluetooth connected devices, Bluetooth is unsupported.");
-            return connectedBluetoothList;
+            Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is unsupported.");
+            return bluetoothDeviceList;
         }
         final Collection<CachedBluetoothDevice> cachedDevices =
                 bluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
 
+        /**
+         * TODO(b/114807655): Contextual Home Page - Connected Device
+         * Re-design to get all Bluetooth devices and sort them by new rule:
+         * Sorting rule: Audio Streaming > Last connected > Recently connected.
+         */
         // Get connected Bluetooth devices and sort them.
         return cachedDevices.stream().filter(device -> device.isConnected()).sorted(
                 COMPARATOR).collect(Collectors.toList());
@@ -193,7 +205,7 @@
         subSettingLauncher.setDestination(BluetoothDeviceDetailsFragment.class.getName())
                 .setArguments(args)
                 .setTitleRes(R.string.device_details_title)
-                .setSourceMetricsCategory(Instrumentable.METRICS_CATEGORY_UNKNOWN);
+                .setSourceMetricsCategory(SettingsEnums.BLUETOOTH_DEVICE_DETAILS);
 
         // The requestCode should be unique, use the hashcode of device as request code.
         return PendingIntent
@@ -203,25 +215,29 @@
     }
 
     @VisibleForTesting
-    IconCompat getConnectedDeviceIcon(CachedBluetoothDevice device) {
+    IconCompat getBluetoothDeviceIcon(CachedBluetoothDevice device) {
         final Pair<Drawable, String> pair = BluetoothUtils
                 .getBtClassDrawableWithDescription(mContext, device);
 
         if (pair.first != null) {
             return IconCompat.createWithBitmap(getBitmapFromVectorDrawable(pair.first));
         } else {
-            return IconCompat.createWithResource(mContext, R.drawable.ic_homepage_connected_device);
+            return IconCompat.createWithResource(mContext, R.drawable.ic_settings_bluetooth);
         }
     }
 
     private List<ListBuilder.RowBuilder> getBluetoothRowBuilder(SliceAction primarySliceAction) {
         final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
 
-        // According Bluetooth connected device to create row builders.
-        final List<CachedBluetoothDevice> bluetoothDevices = getBluetoothConnectedDevices();
+        /**
+         * TODO(b/114807655): Contextual Home Page - Connected Device
+         * Re-design to do action "activating" in primary action.
+         */
+        // According Bluetooth device to create row builders.
+        final List<CachedBluetoothDevice> bluetoothDevices = getBluetoothDevices();
         for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) {
             bluetoothRows.add(new ListBuilder.RowBuilder()
-                    .setTitleItem(getConnectedDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
+                    .setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
                     .setTitle(bluetoothDevice.getName())
                     .setSubtitle(bluetoothDevice.getConnectionSummary())
                     .setPrimaryAction(primarySliceAction)
@@ -240,7 +256,31 @@
     }
 
     private CharSequence getSubTitle(int deviceCount) {
-        return mContext.getResources().getQuantityString(R.plurals.show_connected_devices,
+        return mContext.getResources().getQuantityString(R.plurals.show_bluetooth_devices,
                 deviceCount, deviceCount);
     }
+
+    private ListBuilder.RowBuilder getPairNewDeviceRowBuilder() {
+        final CharSequence title = mContext.getText(R.string.bluetooth_pairing_pref_title);
+        final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_menu_add);
+        final SliceAction sliceAction = SliceAction.createDeeplink(
+                getPairNewDeviceIntent(),
+                IconCompat.createWithResource(mContext, R.drawable.ic_settings),
+                ListBuilder.ICON_IMAGE, title);
+
+        return new ListBuilder.RowBuilder()
+                .setTitleItem(icon, ListBuilder.ICON_IMAGE)
+                .setTitle(title)
+                .setPrimaryAction(sliceAction);
+    }
+
+    private PendingIntent getPairNewDeviceIntent() {
+        final Intent intent = new SubSettingLauncher(mContext)
+                .setDestination(BluetoothPairingDetail.class.getName())
+                .setTitleRes(R.string.bluetooth_pairing_page_title)
+                .setSourceMetricsCategory(SettingsEnums.BLUETOOTH_PAIRING)
+                .toIntent();
+
+        return PendingIntent.getActivity(mContext, 0  /* requestCode */, intent, 0  /* flags */);
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
index d893587..e0f3116 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
@@ -22,7 +22,6 @@
 import android.net.Uri;
 import android.os.storage.StorageManager;
 import android.text.format.Formatter;
-import android.util.Log;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -45,10 +44,8 @@
 
 public class LowStorageSlice implements CustomSliceable {
 
-    private static final String TAG = "LowStorageSlice";
-
     /**
-     * If user used >= 85% storage.
+     * If used storage >= 85%, it would be low storage.
      */
     private static final double LOW_STORAGE_THRESHOLD = 0.85;
 
@@ -60,45 +57,37 @@
 
     @Override
     public Slice getSlice() {
-        // Get current storage percentage from StorageManager.
+        // Get used storage percentage from StorageManager.
         final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
                 new StorageManagerVolumeProvider(mContext.getSystemService(StorageManager.class)));
-        final double currentStoragePercentage =
-                (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
+        final double usedPercentage = (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
 
-        // Used storage < 85%. NOT show Low storage Slice.
-        if (currentStoragePercentage < LOW_STORAGE_THRESHOLD) {
-            /**
-             * TODO(b/114808204): Contextual Home Page - "Low Storage"
-             * The behavior is under decision making, will update new behavior or remove TODO later.
-             */
-            Log.i(TAG, "Not show low storage slice, not match condition.");
-            return null;
+        // Generate Low storage Slice.
+        final String percentageString = NumberFormat.getPercentInstance().format(usedPercentage);
+        final String freeSizeString = Formatter.formatFileSize(mContext, info.freeBytes);
+        final ListBuilder listBuilder = new ListBuilder(mContext,
+                CustomSliceRegistry.LOW_STORAGE_SLICE_URI, ListBuilder.INFINITY).setAccentColor(
+                Utils.getColorAccentDefaultColor(mContext));
+        final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
+
+        if (usedPercentage < LOW_STORAGE_THRESHOLD) {
+            // For clients that ignore error checking, a generic storage slice will be given.
+            final CharSequence titleStorage = mContext.getText(R.string.storage_settings);
+            final String summaryStorage = mContext.getString(R.string.storage_summary,
+                    percentageString, freeSizeString);
+
+            return listBuilder
+                    .addRow(buildRowBuilder(titleStorage, summaryStorage, icon))
+                    .setIsError(true)
+                    .build();
         }
 
-        // Show Low storage Slice.
-        final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
-        final CharSequence title = mContext.getText(R.string.storage_menu_free);
-        final SliceAction primarySliceAction = SliceAction.createDeeplink(
-                PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon,
-                ListBuilder.ICON_IMAGE, title);
-        final String lowStorageSummary = mContext.getString(R.string.low_storage_summary,
-                NumberFormat.getPercentInstance().format(currentStoragePercentage),
-                Formatter.formatFileSize(mContext, info.freeBytes));
+        final CharSequence titleLowStorage = mContext.getText(R.string.storage_menu_free);
+        final String summaryLowStorage = mContext.getString(R.string.low_storage_summary,
+                percentageString, freeSizeString);
 
-        /**
-         * TODO(b/114808204): Contextual Home Page - "Low Storage"
-         * Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
-         * right aligned. Will update the icon to left until Slices support it.
-         */
-        return new ListBuilder(mContext, CustomSliceRegistry.LOW_STORAGE_SLICE_URI,
-                ListBuilder.INFINITY)
-                .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
-                .addRow(new RowBuilder()
-                        .setTitle(title)
-                        .setSubtitle(lowStorageSummary)
-                        .addEndItem(icon, ListBuilder.ICON_IMAGE)
-                        .setPrimaryAction(primarySliceAction))
+        return listBuilder
+                .addRow(buildRowBuilder(titleLowStorage, summaryLowStorage, icon))
                 .build();
     }
 
@@ -121,6 +110,24 @@
                 StorageSettings.class.getName(), "" /* key */,
                 screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+                .setData(CustomSliceRegistry.LOW_STORAGE_SLICE_URI);
+    }
+
+    private RowBuilder buildRowBuilder(CharSequence title, String summary, IconCompat icon) {
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(
+                PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon,
+                ListBuilder.ICON_IMAGE, title);
+
+        /**
+         * TODO(b/114808204): Contextual Home Page - "Low Storage"
+         * Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
+         * right aligned. Will update the icon to left until Slices support it.
+         */
+        return new RowBuilder()
+                .setTitle(title)
+                .setSubtitle(summary)
+                .addEndItem(icon, ListBuilder.ICON_IMAGE)
+                .setPrimaryAction(primarySliceAction);
     }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
index 4378be3..8720a3c 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
@@ -69,9 +69,9 @@
             dbHelper.markContextualCardAsDismissed(mContext, card.getName());
         });
         showFeedbackDialog(card);
-        final ContextualCardFeatureProvider contexualCardFeatureProvider =
+        final ContextualCardFeatureProvider contextualCardFeatureProvider =
                 FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
-        contexualCardFeatureProvider.logContextualCardDismiss(mContext, card);
+        contextualCardFeatureProvider.logContextualCardDismiss(mContext, card);
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index a2d6e2b..be03c28 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -28,8 +28,11 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.LifecycleOwner;
 import androidx.lifecycle.LiveData;
+import androidx.lifecycle.OnLifecycleEvent;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
@@ -38,6 +41,7 @@
 import androidx.slice.widget.SliceView;
 
 import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.CardContentProvider;
 import com.android.settings.homepage.contextualcards.ContextualCard;
 import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
 import com.android.settings.homepage.contextualcards.ContextualCardRenderer;
@@ -51,13 +55,15 @@
  * Card renderer for {@link ContextualCard} built as slices.
  */
 public class SliceContextualCardRenderer implements ContextualCardRenderer,
-        SliceView.OnSliceActionListener {
+        SliceView.OnSliceActionListener, LifecycleObserver {
     public static final int VIEW_TYPE = R.layout.homepage_slice_tile;
 
     private static final String TAG = "SliceCardRenderer";
 
     @VisibleForTesting
-    final Map<String, LiveData<Slice>> mSliceLiveDataMap;
+    final Map<Uri, LiveData<Slice>> mSliceLiveDataMap;
+    @VisibleForTesting
+    final Set<SliceViewHolder> mFlippedCardSet;
 
     private final Context mContext;
     private final LifecycleOwner mLifecycleOwner;
@@ -71,6 +77,8 @@
         mSliceLiveDataMap = new ArrayMap<>();
         mControllerRendererPool = controllerRendererPool;
         mCardSet = new ArraySet<>();
+        mFlippedCardSet = new ArraySet<>();
+        mLifecycleOwner.getLifecycle().addObserver(this);
     }
 
     @Override
@@ -87,9 +95,9 @@
     public void bindView(RecyclerView.ViewHolder holder, ContextualCard card) {
         final SliceViewHolder cardHolder = (SliceViewHolder) holder;
         final Uri uri = card.getSliceUri();
+        //TODO(b/120629936): Take this out once blank card issue is fixed.
+        Log.d(TAG, "bindView - uri = " + uri);
 
-        //TODO(b/116063073): The URI check should be done earlier when we are performing final
-        // filtering after having the full list.
         if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
             Log.w(TAG, "Invalid uri, skipping slice: " + uri);
             return;
@@ -99,11 +107,11 @@
         cardHolder.sliceView.setTag(uri);
         //TODO(b/114009676): We will soon have a field to decide what slice mode we should set.
         cardHolder.sliceView.setMode(SliceView.MODE_LARGE);
-        LiveData<Slice> sliceLiveData = mSliceLiveDataMap.get(uri.toString());
+        LiveData<Slice> sliceLiveData = mSliceLiveDataMap.get(uri);
 
         if (sliceLiveData == null) {
             sliceLiveData = SliceLiveData.fromUri(mContext, uri);
-            mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
+            mSliceLiveDataMap.put(uri, sliceLiveData);
         }
         mCardSet.add(card);
 
@@ -111,6 +119,11 @@
         sliceLiveData.observe(mLifecycleOwner, slice -> {
             if (slice == null) {
                 Log.w(TAG, "Slice is null");
+                mContext.getContentResolver().notifyChange(CardContentProvider.URI, null);
+                return;
+            } else {
+                //TODO(b/120629936): Take this out once blank card issue is fixed.
+                Log.d(TAG, "Slice callback - uri = " + slice.getUri());
             }
             cardHolder.sliceView.setSlice(slice);
         });
@@ -122,20 +135,24 @@
     }
 
     private void initDismissalActions(SliceViewHolder cardHolder, ContextualCard card) {
-        final ViewFlipper viewFlipper = cardHolder.itemView.findViewById(R.id.viewFlipper);
         cardHolder.sliceView.setOnLongClickListener(v -> {
-            viewFlipper.showNext();
+            cardHolder.viewFlipper.showNext();
+            mFlippedCardSet.add(cardHolder);
             return true;
         });
 
         final Button btnKeep = cardHolder.itemView.findViewById(R.id.keep);
         btnKeep.setOnClickListener(v -> {
-            viewFlipper.showPrevious();
+            cardHolder.resetCard();
+            mFlippedCardSet.remove(cardHolder);
         });
 
         final Button btnRemove = cardHolder.itemView.findViewById(R.id.remove);
         btnRemove.setOnClickListener(v -> {
             mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card);
+            cardHolder.resetCard();
+            mFlippedCardSet.remove(cardHolder);
+            mSliceLiveDataMap.get(card.getSliceUri()).removeObservers(mLifecycleOwner);
         });
     }
 
@@ -158,12 +175,24 @@
         }
     }
 
+    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+    public void onStop() {
+        mFlippedCardSet.stream().forEach(holder -> holder.resetCard());
+        mFlippedCardSet.clear();
+    }
+
     public static class SliceViewHolder extends RecyclerView.ViewHolder {
         public final SliceView sliceView;
+        public final ViewFlipper viewFlipper;
 
         public SliceViewHolder(View view) {
             super(view);
             sliceView = view.findViewById(R.id.slice_view);
+            viewFlipper = view.findViewById(R.id.viewFlipper);
+        }
+
+        public void resetCard() {
+            viewFlipper.setDisplayedChild(0);
         }
     }
 }
diff --git a/src/com/android/settings/location/LocationScanningPreferenceController.java b/src/com/android/settings/location/LocationScanningPreferenceController.java
index 9d1bdc0..2c05a39 100644
--- a/src/com/android/settings/location/LocationScanningPreferenceController.java
+++ b/src/com/android/settings/location/LocationScanningPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.location;
 
 import android.content.Context;
+import android.provider.Settings;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -25,11 +26,31 @@
 
 
 public class LocationScanningPreferenceController extends BasePreferenceController {
-
     @VisibleForTesting static final String KEY_LOCATION_SCANNING = "location_scanning";
+    private final Context mContext;
 
     public LocationScanningPreferenceController(Context context) {
         super(context, KEY_LOCATION_SCANNING);
+        mContext = context;
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        final boolean wifiScanOn = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1;
+        final boolean bleScanOn = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
+        int resId;
+        if (wifiScanOn && bleScanOn) {
+            resId = R.string.scanning_status_text_wifi_on_ble_on;
+        } else if (wifiScanOn && !bleScanOn) {
+            resId = R.string.scanning_status_text_wifi_on_ble_off;
+        } else if (!wifiScanOn && bleScanOn) {
+            resId = R.string.scanning_status_text_wifi_off_ble_on;
+        } else {
+            resId = R.string.scanning_status_text_wifi_off_ble_off;
+        }
+        return mContext.getString(resId);
     }
 
     @AvailabilityStatus
diff --git a/src/com/android/settings/location/LocationSliceBuilder.java b/src/com/android/settings/location/LocationSlice.java
similarity index 66%
rename from src/com/android/settings/location/LocationSliceBuilder.java
rename to src/com/android/settings/location/LocationSlice.java
index f70d09b..6dc4241 100644
--- a/src/com/android/settings/location/LocationSliceBuilder.java
+++ b/src/com/android/settings/location/LocationSlice.java
@@ -38,29 +38,31 @@
 import com.android.settings.SubSettings;
 import com.android.settings.Utils;
 import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
 import com.android.settings.slices.SliceBuilderUtils;
 
 /**
  * Utility class to build an intent-based Location Slice.
  */
-public class LocationSliceBuilder {
+public class LocationSlice implements CustomSliceable {
 
-    private LocationSliceBuilder() {
+    private final Context mContext;
+
+    public LocationSlice(Context context) {
+        mContext = context;
     }
 
-    /**
-     * Return a Location Slice bound to {@link CustomSliceRegistry#LOCATION_SLICE_URI}.
-     */
-    public static Slice getSlice(Context context) {
-        final IconCompat icon = IconCompat.createWithResource(context,
+    @Override
+    public Slice getSlice() {
+        final IconCompat icon = IconCompat.createWithResource(mContext,
                 R.drawable.ic_signal_location);
-        final String title = context.getString(R.string.location_settings_title);
-        @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
-        final PendingIntent primaryAction = getPrimaryAction(context);
+        final CharSequence title = mContext.getText(R.string.location_settings_title);
+        @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
+        final PendingIntent primaryAction = getPrimaryAction();
         final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
                 ListBuilder.ICON_IMAGE, title);
 
-        return new ListBuilder(context, CustomSliceRegistry.LOCATION_SLICE_URI,
+        return new ListBuilder(mContext, CustomSliceRegistry.LOCATION_SLICE_URI,
                 ListBuilder.INFINITY)
                 .setAccentColor(color)
                 .addRow(new RowBuilder()
@@ -70,19 +72,30 @@
                 .build();
     }
 
-    public static Intent getIntent(Context context) {
-        final String screenTitle = context.getText(R.string.location_settings_title).toString();
+    @Override
+    public Uri getUri() {
+        return CustomSliceRegistry.LOCATION_SLICE_URI;
+    }
+
+    @Override
+    public void onNotifyChange(Intent intent) {
+
+    }
+
+    @Override
+    public Intent getIntent() {
+        final String screenTitle = mContext.getText(R.string.location_settings_title).toString();
         final Uri contentUri = new Uri.Builder().appendPath(KEY_LOCATION).build();
-        return SliceBuilderUtils.buildSearchResultPageIntent(context,
+        return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
                 LocationSettings.class.getName(), KEY_LOCATION, screenTitle,
                 MetricsEvent.LOCATION)
-                .setClassName(context.getPackageName(), SubSettings.class.getName())
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
                 .setData(contentUri);
     }
 
-    private static PendingIntent getPrimaryAction(Context context) {
-        final Intent intent = getIntent(context);
-        return PendingIntent.getActivity(context, 0 /* requestCode */,
+    private PendingIntent getPrimaryAction() {
+        final Intent intent = getIntent();
+        return PendingIntent.getActivity(mContext, 0 /* requestCode */,
                 intent, 0 /* flags */);
     }
 }
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
index 633fc45..a16be66 100644
--- a/src/com/android/settings/network/ApnEditor.java
+++ b/src/com/android/settings/network/ApnEditor.java
@@ -167,7 +167,7 @@
             Telephony.Carriers.ROAMING_PROTOCOL, // 20
             Telephony.Carriers.MVNO_TYPE,   // 21
             Telephony.Carriers.MVNO_MATCH_DATA,  // 22
-            Telephony.Carriers.EDITED,   // 23
+            Telephony.Carriers.EDITED_STATUS,   // 23
             Telephony.Carriers.USER_EDITABLE    //24
     };
 
@@ -1035,7 +1035,7 @@
                 callUpdate,
                 CARRIER_ENABLED_INDEX);
 
-        values.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
+        values.put(Telephony.Carriers.EDITED_STATUS, Telephony.Carriers.USER_EDITED);
 
         if (callUpdate) {
             final Uri uri = mApnData.getUri() == null ? mCarrierUri : mApnData.getUri();
diff --git a/src/com/android/settings/network/ApnSettings.java b/src/com/android/settings/network/ApnSettings.java
index 4bd964e..261d889 100755
--- a/src/com/android/settings/network/ApnSettings.java
+++ b/src/com/android/settings/network/ApnSettings.java
@@ -82,7 +82,7 @@
             Telephony.Carriers.TYPE,
             Telephony.Carriers.MVNO_TYPE,
             Telephony.Carriers.MVNO_MATCH_DATA,
-            Telephony.Carriers.EDITED,
+            Telephony.Carriers.EDITED_STATUS,
     };
 
     private static final int ID_INDEX = 0;
diff --git a/src/com/android/settings/network/MultiNetworkHeaderController.java b/src/com/android/settings/network/MultiNetworkHeaderController.java
new file mode 100644
index 0000000..1c0fc74
--- /dev/null
+++ b/src/com/android/settings/network/MultiNetworkHeaderController.java
@@ -0,0 +1,36 @@
+/*
+ * 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.network;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+
+// This controls a header at the top of the Network & internet page that only appears when there
+// are two or more active mobile subscriptions. It shows an overview of available network
+// connections with an entry for wifi (if connected) and an entry for each subscription.
+public class MultiNetworkHeaderController extends BasePreferenceController {
+
+    public MultiNetworkHeaderController(Context context, String key) {
+      super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return UNSUPPORTED_ON_DEVICE;
+    }
+}
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
new file mode 100644
index 0000000..cfe27db
--- /dev/null
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -0,0 +1,44 @@
+/*
+ * 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.network;
+
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class SubscriptionUtil {
+    public static List<SubscriptionInfo> getAvailableSubscriptions(SubscriptionManager manager) {
+        List<SubscriptionInfo> subscriptions = manager.getAvailableSubscriptionInfoList();
+        if (subscriptions == null) {
+            subscriptions = new ArrayList<>();
+        }
+        // With some carriers such as Google Fi which provide a sort of virtual service that spans
+        // across multiple underlying networks, we end up with subscription entries for the
+        // underlying networks that need to be hidden from the user in the UI.
+        for (Iterator<SubscriptionInfo> iter = subscriptions.iterator(); iter.hasNext(); ) {
+            SubscriptionInfo info = iter.next();
+            if (TextUtils.isEmpty(info.getMncString())) {
+                iter.remove();
+            }
+        }
+        return subscriptions;
+    }
+}
diff --git a/src/com/android/settings/network/SubscriptionsChangeListener.java b/src/com/android/settings/network/SubscriptionsChangeListener.java
new file mode 100644
index 0000000..c3bb22b
--- /dev/null
+++ b/src/com/android/settings/network/SubscriptionsChangeListener.java
@@ -0,0 +1,97 @@
+/*
+ * 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.network;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
+
+import com.android.internal.telephony.TelephonyIntents;
+
+/** Helper class for listening to changes in availability of telephony subscriptions */
+public class SubscriptionsChangeListener extends ContentObserver {
+
+    public interface SubscriptionsChangeListenerClient {
+        void onAirplaneModeChanged(boolean airplaneModeEnabled);
+        void onSubscriptionsChanged();
+    }
+
+    private Context mContext;
+    private SubscriptionsChangeListenerClient mClient;
+    private SubscriptionManager mSubscriptionManager;
+    private OnSubscriptionsChangedListener mSubscriptionsChangedListener;
+    private Uri mAirplaneModeSettingUri;
+    private BroadcastReceiver mBroadcastReceiver;
+
+    public SubscriptionsChangeListener(Context context, SubscriptionsChangeListenerClient client) {
+        super(new Handler());
+        mContext = context;
+        mClient = client;
+        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+        mSubscriptionsChangedListener = new OnSubscriptionsChangedListener() {
+            @Override
+            public void onSubscriptionsChanged() {
+                subscriptionsChangedCallback();
+            }
+        };
+        mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
+        mBroadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                subscriptionsChangedCallback();
+            }
+        };
+    }
+
+    public void start() {
+        mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
+        mContext.getContentResolver()
+                .registerContentObserver(mAirplaneModeSettingUri, false, this);
+        final IntentFilter radioTechnologyChangedFilter = new IntentFilter(
+                TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+        mContext.registerReceiver(mBroadcastReceiver, radioTechnologyChangedFilter);
+    }
+
+    public void stop() {
+        mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
+        mContext.getContentResolver().unregisterContentObserver(this);
+        mContext.unregisterReceiver(mBroadcastReceiver);
+    }
+
+    public boolean isAirplaneModeOn() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
+    }
+
+    private void subscriptionsChangedCallback() {
+        mClient.onSubscriptionsChanged();
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        if (uri.equals(mAirplaneModeSettingUri)) {
+            mClient.onAirplaneModeChanged(isAirplaneModeOn());
+        }
+    }
+}
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index b1124f8..9ebeda0 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -22,7 +22,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings;
-import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -131,16 +130,12 @@
     @VisibleForTesting
     boolean isDialogNeeded() {
         final boolean enableData = !mTelephonyManager.isDataEnabled();
-        final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(
-                mSubId);
-        final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo();
         final boolean isMultiSim = (mTelephonyManager.getSimCount() > 1);
-        final boolean isMultipleDataOnCapable =
-                (mTelephonyManager.getNumberOfModemsWithSimultaneousDataConnections() > 1);
-        final boolean isDefaultDataSubscription = (nextSir != null && currentSir != null
-                && currentSir.getSubscriptionId() == nextSir.getSubscriptionId());
+        final int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId();
+        final boolean needToDisableOthers = mSubscriptionManager
+                .isActiveSubscriptionId(defaultSubId) && defaultSubId != mSubId;
         if (enableData) {
-            if (isMultiSim && !isMultipleDataOnCapable && !isDefaultDataSubscription) {
+            if (isMultiSim && needToDisableOthers) {
                 mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG;
                 return true;
             }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index dc184d3..27cc367 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -230,7 +230,8 @@
                     subscriptionManager.getActiveSubscriptionInfoList();
             if (subInfoList != null) {
                 for (SubscriptionInfo subInfo : subInfoList) {
-                    if (subInfo.getSubscriptionId() != subId) {
+                    // We never disable mobile data for opportunistic subscriptions.
+                    if (subInfo.getSubscriptionId() != subId && !subInfo.isOpportunistic()) {
                         context.getSystemService(TelephonyManager.class).createForSubscriptionId(
                                 subInfo.getSubscriptionId()).setDataEnabled(false);
                     }
diff --git a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
index 5b4c245..d0f1ee6 100644
--- a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
+++ b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
@@ -25,7 +25,6 @@
 import android.content.pm.ServiceInfo;
 import android.provider.Settings;
 import android.service.notification.ConditionProviderService;
-import android.service.notification.ZenModeConfig;
 
 import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
@@ -34,20 +33,15 @@
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 abstract public class AbstractZenModeAutomaticRulePreferenceController extends
         AbstractZenModePreferenceController implements PreferenceControllerMixin {
 
     protected ZenModeBackend mBackend;
     protected Fragment mParent;
-    protected Set<Map.Entry<String, AutomaticZenRule>> mRules;
+    protected Map.Entry<String, AutomaticZenRule>[] mRules;
     protected PackageManager mPm;
-    private static List<String> mDefaultRuleIds;
 
     public AbstractZenModeAutomaticRulePreferenceController(Context context, String key, Fragment
             parent, Lifecycle lifecycle) {
@@ -60,20 +54,14 @@
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
-        mRules = getZenModeRules();
+        mRules = mBackend.getAutomaticZenRules();
     }
 
-    private static List<String> getDefaultRuleIds() {
-        if (mDefaultRuleIds == null) {
-            mDefaultRuleIds = ZenModeConfig.DEFAULT_RULE_IDS;
+    protected Map.Entry<String, AutomaticZenRule>[] getRules() {
+        if (mRules == null) {
+            mRules = mBackend.getAutomaticZenRules();
         }
-        return mDefaultRuleIds;
-    }
-
-    private Set<Map.Entry<String, AutomaticZenRule>> getZenModeRules() {
-        Map<String, AutomaticZenRule> ruleMap =
-                NotificationManager.from(mContext).getAutomaticZenRules();
-        return ruleMap.entrySet();
+        return mRules;
     }
 
     protected void showNameRuleDialog(final ZenRuleInfo ri, Fragment parent) {
@@ -81,16 +69,6 @@
                 RuleNameChangeListener(ri));
     }
 
-    protected Map.Entry<String, AutomaticZenRule>[] sortedRules() {
-        if (mRules == null) {
-            mRules = getZenModeRules();
-        }
-        final Map.Entry<String, AutomaticZenRule>[] rt =
-                mRules.toArray(new Map.Entry[mRules.size()]);
-        Arrays.sort(rt, RULE_COMPARATOR);
-        return rt;
-    }
-
     protected static Intent getRuleIntent(String settingsAction,
             ComponentName configurationActivity, String ruleId) {
         final Intent intent = new Intent()
@@ -104,35 +82,6 @@
         return intent;
     }
 
-    private static final Comparator<Map.Entry<String, AutomaticZenRule>> RULE_COMPARATOR =
-            new Comparator<Map.Entry<String, AutomaticZenRule>>() {
-                @Override
-                public int compare(Map.Entry<String, AutomaticZenRule> lhs,
-                        Map.Entry<String, AutomaticZenRule> rhs) {
-                    // if it's a default rule, should be at the top of automatic rules
-                    boolean lhsIsDefaultRule = getDefaultRuleIds().contains(lhs.getKey());
-                    boolean rhsIsDefaultRule = getDefaultRuleIds().contains(rhs.getKey());
-                    if (lhsIsDefaultRule != rhsIsDefaultRule) {
-                        return lhsIsDefaultRule ? -1 : 1;
-                    }
-
-                    int byDate = Long.compare(lhs.getValue().getCreationTime(),
-                            rhs.getValue().getCreationTime());
-                    if (byDate != 0) {
-                        return byDate;
-                    } else {
-                        return key(lhs.getValue()).compareTo(key(rhs.getValue()));
-                    }
-                }
-
-                private String key(AutomaticZenRule rule) {
-                    final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
-                            ? 1 : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
-                            ? 2 : 3;
-                    return type + rule.getName().toString();
-                }
-            };
-
     public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
         if (si == null || si.metaData == null) {
             return null;
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
index 72bb0e3..c2db773 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
@@ -136,7 +136,7 @@
                     MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
             mRule.setName(ruleName);
             mRule.setModified(true);
-            mBackend.setZenRule(mId, mRule);
+            mBackend.updateZenRule(mId, mRule);
         }
     }
 }
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
index f38deb3..e5ca754 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
@@ -88,6 +88,6 @@
         final boolean enabled = isChecked;
         if (enabled == mRule.isEnabled()) return;
         mRule.setEnabled(enabled);
-        mBackend.setZenRule(mId, mRule);
+        mBackend.updateZenRule(mId, mRule);
     }
 }
diff --git a/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java b/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
index 67d9e93..b877668 100644
--- a/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
@@ -21,12 +21,12 @@
 import android.provider.Settings;
 import android.util.Log;
 
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
 import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
 
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
 public class ZenModeAlarmsPreferenceController extends
         AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener {
 
@@ -78,6 +78,7 @@
         mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_ALARMS,
                 allowAlarms);
         mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_ALARMS, allowAlarms);
+
         return true;
     }
 }
diff --git a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
index 7679b0b..7da90c8 100644
--- a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
@@ -28,6 +28,7 @@
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import java.util.Map;
+import java.util.Objects;
 
 public class ZenModeAutomaticRulesPreferenceController extends
         AbstractZenModeAutomaticRulePreferenceController {
@@ -62,16 +63,39 @@
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
+        Map.Entry<String, AutomaticZenRule>[] sortedRules = getRules();
+        final int currNumPreferences = mPreferenceCategory.getPreferenceCount();
+        if (currNumPreferences == sortedRules.length) {
+            for (int i = 0; i < sortedRules.length; i++) {
+                ZenRulePreference pref = (ZenRulePreference) mPreferenceCategory.getPreference(i);
+                // we are either:
+                // 1. updating the enabled state or name of the rule
+                // 2. rule was added or deleted, so reload the entire list
+                if (Objects.equals(pref.mId, sortedRules[i].getKey())) {
+                    AutomaticZenRule rule = sortedRules[i].getValue();
+                    pref.updatePreference(rule);
+                } else {
+                    reloadAllRules(sortedRules);
+                    break;
+                }
+            }
+        } else {
+            reloadAllRules(sortedRules);
+        }
+    }
 
+    @VisibleForTesting
+    void reloadAllRules(Map.Entry<String, AutomaticZenRule>[] rules) {
         mPreferenceCategory.removeAll();
-        Map.Entry<String, AutomaticZenRule>[] sortedRules = sortedRules();
-        for (Map.Entry<String, AutomaticZenRule> sortedRule : sortedRules) {
-            ZenRulePreference pref = new ZenRulePreference(mPreferenceCategory.getContext(),
-                    sortedRule, mParent, mMetricsFeatureProvider);
+        for (Map.Entry<String, AutomaticZenRule> rule : rules) {
+            ZenRulePreference pref = createZenRulePreference(rule);
             mPreferenceCategory.addPreference(pref);
         }
     }
+
+    @VisibleForTesting
+    ZenRulePreference createZenRulePreference(Map.Entry<String, AutomaticZenRule> rule) {
+        return new ZenRulePreference(mPreferenceCategory.getContext(),
+                rule, mParent, mMetricsFeatureProvider);
+    }
 }
-
-
-
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index 44bc5f1..c559a28 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -16,9 +16,15 @@
 
 package com.android.settings.notification;
 
+import android.app.AlertDialog;
+import android.app.AutomaticZenRule;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.provider.SearchIndexableResource;
 import android.service.notification.ConditionProviderService;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 
 import androidx.fragment.app.Fragment;
 
@@ -34,10 +40,14 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 @SearchIndexable
 public class ZenModeAutomationSettings extends ZenModeSettingsBase {
     protected final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
+    private CharSequence[] mDeleteDialogRuleNames;
+    private String[] mDeleteDialogRuleIds;
+    private boolean[] mDeleteDialogChecked;
 
     @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
@@ -74,6 +84,52 @@
                 .setNoun("condition provider")
                 .build();
     }
+    private final int DELETE_RULES = 1;
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        menu.add(Menu.NONE, DELETE_RULES, Menu.NONE, R.string.zen_mode_delete_automatic_rules);
+        super.onCreateOptionsMenu(menu, inflater);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case DELETE_RULES:
+                Map.Entry<String, AutomaticZenRule>[] rules = mBackend.getAutomaticZenRules();
+                mDeleteDialogRuleNames = new CharSequence[rules.length];
+                mDeleteDialogRuleIds = new String[rules.length];
+                mDeleteDialogChecked = new boolean[rules.length];
+                for (int i = 0; i < rules.length; i++) {
+                    mDeleteDialogRuleNames[i] = rules[i].getValue().getName();
+                    mDeleteDialogRuleIds[i] = rules[i].getKey();
+                }
+                new AlertDialog.Builder(mContext)
+                        .setTitle(R.string.zen_mode_delete_automatic_rules)
+                        .setMultiChoiceItems(mDeleteDialogRuleNames, null,
+                                new DialogInterface.OnMultiChoiceClickListener() {
+                                    @Override
+                                    public void onClick(DialogInterface dialog, int which,
+                                            boolean isChecked) {
+                                        mDeleteDialogChecked[which] = isChecked;
+                                    }
+                                })
+                        .setPositiveButton(R.string.zen_mode_schedule_delete,
+                                new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                for (int i = 0; i < rules.length; i++) {
+                                    if (mDeleteDialogChecked[i]) {
+                                        mBackend.removeZenRule(mDeleteDialogRuleIds[i]);
+                                    }
+                                }
+                            }
+                        }).show();
+                return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
 
     /**
      * For Search.
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index de30e5d..a75f51c 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -32,6 +32,11 @@
 
 import com.android.settings.R;
 
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
 public class ZenModeBackend {
     @VisibleForTesting
     protected static final String ZEN_MODE_FROM_ANYONE = "zen_mode_from_anyone";
@@ -42,6 +47,7 @@
     @VisibleForTesting
     protected static final String ZEN_MODE_FROM_NONE = "zen_mode_from_none";
     protected static final int SOURCE_NONE = -1;
+    private static List<String> mDefaultRuleIds;
 
     private static ZenModeBackend sInstance;
 
@@ -79,7 +85,7 @@
                 Settings.Global.ZEN_MODE, mZenMode);
     }
 
-    protected boolean setZenRule(String id, AutomaticZenRule rule) {
+    protected boolean updateZenRule(String id, AutomaticZenRule rule) {
         return NotificationManager.from(mContext).updateAutomaticZenRule(id, rule);
     }
 
@@ -244,15 +250,17 @@
         }
     }
 
+    protected int getAlarmsTotalSilenceCallsMessagesSummary(int category) {
+        if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
+            return R.string.zen_mode_from_none_messages;
+        } else if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CALLS){
+            return R.string.zen_mode_from_none_calls;
+        }
+        return 0;
+    }
+
     protected int getContactsSummary(int category) {
         int contactType = -1;
-
-        // SOURCE_NONE can be used when in total silence or alarms only
-        // (policy is based on user's preferences but the UI displayed is based on zenMode)
-        if (category == SOURCE_NONE) {
-            return R.string.zen_mode_from_none;
-        }
-
         if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
             if (isPriorityCategoryEnabled(category)) {
                 contactType = getPriorityMessageSenders();
@@ -267,12 +275,16 @@
             case NotificationManager.Policy.PRIORITY_SENDERS_ANY:
                 return R.string.zen_mode_from_anyone;
             case NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS:
-                return  R.string.zen_mode_from_contacts;
+                return R.string.zen_mode_from_contacts;
             case NotificationManager.Policy.PRIORITY_SENDERS_STARRED:
-                return  R.string.zen_mode_from_starred;
+                return R.string.zen_mode_from_starred;
             case SOURCE_NONE:
             default:
-                return R.string.zen_mode_from_none;
+                if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
+                    return R.string.zen_mode_from_none_messages;
+                } else {
+                    return R.string.zen_mode_from_none_calls;
+                }
         }
     }
 
@@ -294,13 +306,65 @@
         return NotificationManager.from(mContext).removeAutomaticZenRule(ruleId);
     }
 
+    public NotificationManager.Policy getConsolidatedPolicy() {
+        return NotificationManager.from(mContext).getConsolidatedNotificationPolicy();
+    }
+
     protected String addZenRule(AutomaticZenRule rule) {
         try {
-            String id = NotificationManager.from(mContext).addAutomaticZenRule(rule);
-            NotificationManager.from(mContext).getAutomaticZenRule(id);
-            return id;
+            return NotificationManager.from(mContext).addAutomaticZenRule(rule);
         } catch (Exception e) {
             return null;
         }
     }
+
+    protected Map.Entry<String, AutomaticZenRule>[] getAutomaticZenRules() {
+        Map<String, AutomaticZenRule> ruleMap =
+                NotificationManager.from(mContext).getAutomaticZenRules();
+        final Map.Entry<String, AutomaticZenRule>[] rt = ruleMap.entrySet().toArray(
+                new Map.Entry[ruleMap.size()]);
+        Arrays.sort(rt, RULE_COMPARATOR);
+        return rt;
+    }
+
+    protected AutomaticZenRule getAutomaticZenRule(String id) {
+        return NotificationManager.from(mContext).getAutomaticZenRule(id);
+    }
+
+    private static List<String> getDefaultRuleIds() {
+        if (mDefaultRuleIds == null) {
+            mDefaultRuleIds = ZenModeConfig.DEFAULT_RULE_IDS;
+        }
+        return mDefaultRuleIds;
+    }
+
+    @VisibleForTesting
+    public static final Comparator<Map.Entry<String, AutomaticZenRule>> RULE_COMPARATOR =
+            new Comparator<Map.Entry<String, AutomaticZenRule>>() {
+                @Override
+                public int compare(Map.Entry<String, AutomaticZenRule> lhs,
+                        Map.Entry<String, AutomaticZenRule> rhs) {
+                    // if it's a default rule, should be at the top of automatic rules
+                    boolean lhsIsDefaultRule = getDefaultRuleIds().contains(lhs.getKey());
+                    boolean rhsIsDefaultRule = getDefaultRuleIds().contains(rhs.getKey());
+                    if (lhsIsDefaultRule != rhsIsDefaultRule) {
+                        return lhsIsDefaultRule ? -1 : 1;
+                    }
+
+                    int byDate = Long.compare(lhs.getValue().getCreationTime(),
+                            rhs.getValue().getCreationTime());
+                    if (byDate != 0) {
+                        return byDate;
+                    } else {
+                        return key(lhs.getValue()).compareTo(key(rhs.getValue()));
+                    }
+                }
+
+                private String key(AutomaticZenRule rule) {
+                    final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
+                            ? 1 : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
+                            ? 2 : 3;
+                    return type + rule.getName().toString();
+                }
+            };
 }
diff --git a/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java b/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java
index 19ee809..2e41f20 100644
--- a/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java
@@ -18,11 +18,11 @@
 
 import android.content.Context;
 
+import androidx.preference.Preference;
+
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
-import androidx.preference.Preference;
-
 public class ZenModeMessagesPreferenceController extends
         AbstractZenModePreferenceController implements PreferenceControllerMixin {
 
@@ -48,6 +48,7 @@
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
-        // TODO: (b/111475013 - beverlyt) set messages summary
+
+        preference.setSummary(mSummaryBuilder.getMessagesSettingSummary(getPolicy()));
     }
 }
diff --git a/src/com/android/settings/notification/ZenModePriorityCallsPreferenceController.java b/src/com/android/settings/notification/ZenModePriorityCallsPreferenceController.java
index 44b6c24..9872188 100644
--- a/src/com/android/settings/notification/ZenModePriorityCallsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePriorityCallsPreferenceController.java
@@ -21,14 +21,14 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 
-import com.android.settings.R;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.ListPreference;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
 public class ZenModePriorityCallsPreferenceController extends AbstractZenModePreferenceController
         implements Preference.OnPreferenceChangeListener {
 
@@ -80,7 +80,8 @@
             case Settings.Global.ZEN_MODE_ALARMS:
                 mPreference.setEnabled(false);
                 mPreference.setValue(ZenModeBackend.ZEN_MODE_FROM_NONE);
-                mPreference.setSummary(mBackend.getContactsSummary(ZenModeBackend.SOURCE_NONE));
+                mPreference.setSummary(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
+                        NotificationManager.Policy.PRIORITY_CATEGORY_CALLS));
                 break;
             default:
                 preference.setEnabled(true);
diff --git a/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceController.java b/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceController.java
index 56829a7..cfda367 100644
--- a/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceController.java
@@ -21,14 +21,14 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 
-import com.android.settings.R;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.ListPreference;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
 public class ZenModePriorityMessagesPreferenceController extends AbstractZenModePreferenceController
         implements Preference.OnPreferenceChangeListener {
 
@@ -80,7 +80,8 @@
             case Settings.Global.ZEN_MODE_ALARMS:
                 mPreference.setEnabled(false);
                 mPreference.setValue(ZenModeBackend.ZEN_MODE_FROM_NONE);
-                mPreference.setSummary(mBackend.getContactsSummary(ZenModeBackend.SOURCE_NONE));
+                mPreference.setSummary(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
+                        NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES));
                 break;
             default:
                 preference.setEnabled(true);
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
index 9e5dbc3..11b8084 100644
--- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -124,7 +124,7 @@
 
     protected void updateRule(Uri newConditionId) {
         mRule.setConditionId(newConditionId);
-        mBackend.setZenRule(mId, mRule);
+        mBackend.updateZenRule(mId, mRule);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
index f65a8b0..0b2e1bc 100644
--- a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
@@ -64,7 +64,6 @@
     private TimePickerPreference mEnd;
     private SwitchPreference mExitAtAlarm;
     private AlertDialog mDayDialog;
-
     private ScheduleInfo mSchedule;
 
     @Override
@@ -186,7 +185,6 @@
         final int summaryFormat = nextDay ? R.string.zen_mode_end_time_next_day_summary_format : 0;
         mEnd.setSummaryFormat(summaryFormat);
     }
-
     @Override
     protected void updateControlsInternal() {
         updateDays();
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 293c429..a3f59c6 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -145,7 +145,7 @@
                             || PRIORITY_CATEGORY_REPEAT_CALLERS == category, false);
             int numCategories = enabledCategories.size();
             if (numCategories == 0) {
-                return mContext.getString(R.string.zen_mode_no_exceptions);
+                return mContext.getString(R.string.zen_mode_from_none_calls);
             } else if (numCategories == 1) {
                 return mContext.getString(R.string.zen_mode_calls_summary_one,
                         enabledCategories.get(0));
@@ -156,34 +156,14 @@
             }
         }
 
-        String getMsgEventReminderSettingSummary(Policy policy) {
+        String getMessagesSettingSummary(Policy policy) {
             List<String> enabledCategories = getEnabledCategories(policy,
-                    category -> PRIORITY_CATEGORY_EVENTS == category
-                            || PRIORITY_CATEGORY_REMINDERS == category
-                            || PRIORITY_CATEGORY_MESSAGES == category, true);
+                    category -> PRIORITY_CATEGORY_MESSAGES == category, false);
             int numCategories = enabledCategories.size();
             if (numCategories == 0) {
-                return mContext.getString(R.string.zen_mode_no_exceptions);
-            } else if (numCategories == 1) {
-                return enabledCategories.get(0);
-            } else if (numCategories == 2) {
-                return mContext.getString(R.string.join_two_items, enabledCategories.get(0),
-                        enabledCategories.get(1));
-            } else if (numCategories == 3){
-                final List<String> summaries = new ArrayList<>();
-                summaries.add(enabledCategories.get(0));
-                summaries.add(enabledCategories.get(1));
-                summaries.add(enabledCategories.get(2));
-
-                return ListFormatter.getInstance().format(summaries);
+                return mContext.getString(R.string.zen_mode_from_none_messages);
             } else {
-                final List<String> summaries = new ArrayList<>();
-                summaries.add(enabledCategories.get(0));
-                summaries.add(enabledCategories.get(1));
-                summaries.add(enabledCategories.get(2));
-                summaries.add(mContext.getString(R.string.zen_mode_other_options));
-
-                return ListFormatter.getInstance().format(summaries);
+                return enabledCategories.get(0);
             }
         }
 
@@ -292,17 +272,11 @@
                 }
             } else if (category == Policy.PRIORITY_CATEGORY_MESSAGES) {
                 if (policy.priorityMessageSenders == Policy.PRIORITY_SENDERS_ANY) {
-                    if (isFirst) {
-                        return mContext.getString(R.string.zen_mode_all_messages);
-                    } else {
-                        return mContext.getString(R.string.zen_mode_all_messages_list);
-                    }
+                    return mContext.getString(R.string.zen_mode_from_anyone);
+                } else if (policy.priorityMessageSenders == Policy.PRIORITY_SENDERS_CONTACTS){
+                    return mContext.getString(R.string.zen_mode_from_contacts);
                 } else {
-                    if (isFirst) {
-                        return mContext.getString(R.string.zen_mode_selected_messages);
-                    } else {
-                        return mContext.getString(R.string.zen_mode_selected_messages_list);
-                    }
+                    return mContext.getString(R.string.zen_mode_from_starred);
                 }
             } else if (category == Policy.PRIORITY_CATEGORY_EVENTS) {
                 if (isFirst) {
diff --git a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
index 6d5aac9..f69eac7 100644
--- a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
@@ -16,16 +16,23 @@
 
 package com.android.settings.notification;
 
+import android.app.NotificationManager;
 import android.content.Context;
+import android.icu.text.ListFormatter;
 import android.net.Uri;
 import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
+import android.util.Log;
 
 import androidx.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
 public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePreferenceController {
 
     protected static final String KEY = "footer_preference";
@@ -65,6 +72,31 @@
 
     protected String getFooterText() {
         ZenModeConfig config = getZenModeConfig();
+
+        NotificationManager.Policy appliedPolicy = mBackend.getConsolidatedPolicy();
+        NotificationManager.Policy defaultPolicy = config.toNotificationPolicy();
+        final boolean usingCustomPolicy = !Objects.equals(appliedPolicy, defaultPolicy);
+
+        if (usingCustomPolicy) {
+            final List<ZenModeConfig.ZenRule> activeRules = getActiveRules(config);
+            final List<String> rulesNames = new ArrayList<>();
+            for (ZenModeConfig.ZenRule rule : activeRules) {
+                if (rule.name != null) {
+                    rulesNames.add(rule.name);
+                }
+            }
+            if (rulesNames.size() > 0) {
+                String rules = ListFormatter.getInstance().format(rulesNames);
+                if (!rules.isEmpty()) {
+                    return mContext.getString(R.string.zen_mode_settings_dnd_custom_settings_footer,
+                            rules);
+                }
+            }
+        }
+        return getFooterUsingDefaultPolicy(config);
+    }
+
+    private String getFooterUsingDefaultPolicy(ZenModeConfig config) {
         String footerText = "";
         long latestEndTime = -1;
 
@@ -116,4 +148,18 @@
         }
         return footerText;
     }
+
+    private List<ZenModeConfig.ZenRule> getActiveRules(ZenModeConfig config) {
+        List<ZenModeConfig.ZenRule> zenRules = new ArrayList<>();
+        if (config.manualRule != null) {
+            zenRules.add(config.manualRule);
+        }
+
+        for (ZenModeConfig.ZenRule automaticRule : config.automaticRules.values()) {
+            if (automaticRule.isAutomaticActive()) {
+                zenRules.add(automaticRule);
+            }
+        }
+        return zenRules;
+    }
 }
diff --git a/src/com/android/settings/notification/ZenRulePreference.java b/src/com/android/settings/notification/ZenRulePreference.java
index 8058e6c..10b49eb 100644
--- a/src/com/android/settings/notification/ZenRulePreference.java
+++ b/src/com/android/settings/notification/ZenRulePreference.java
@@ -19,17 +19,19 @@
 import android.app.AutomaticZenRule;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.service.notification.ZenModeConfig;
 import android.view.View;
+import android.widget.CheckBox;
 
 import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
-import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.utils.ManagedServiceSettings;
 import com.android.settings.utils.ZenServiceListing;
@@ -37,11 +39,11 @@
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 import java.util.Map;
+import java.util.Objects;
 
 public class ZenRulePreference extends TwoTargetPreference {
     private static final ManagedServiceSettings.Config CONFIG =
             ZenModeAutomationSettings.getConditionProviderConfig();
-    final CharSequence mName;
     final String mId;
     boolean appExists;
     final Fragment mParent;
@@ -51,16 +53,23 @@
     final ZenServiceListing mServiceListing;
     final PackageManager mPm;
     final MetricsFeatureProvider mMetricsFeatureProvider;
+    final AutomaticZenRule mRule;
+    CharSequence mName;
+
+    private boolean mIsSystemRule;
+    private Intent mIntent;
+    private boolean mChecked;
+    private CheckBox mCheckBox;
 
     public ZenRulePreference(Context context,
             final Map.Entry<String, AutomaticZenRule> ruleEntry,
             Fragment parent, MetricsFeatureProvider metricsProvider) {
         super(context);
-
+        setLayoutResource(R.layout.preference_checkable_two_target);
         mBackend = ZenModeBackend.getInstance(context);
         mContext = context;
-        final AutomaticZenRule rule = ruleEntry.getValue();
-        mName = rule.getName();
+        mRule = ruleEntry.getValue();
+        mName = mRule.getName();
         mId = ruleEntry.getKey();
         mParent = parent;
         mPm = mContext.getPackageManager();
@@ -68,65 +77,104 @@
         mServiceListing.reloadApprovedServices();
         mPref = this;
         mMetricsFeatureProvider = metricsProvider;
-
-        setAttributes(rule);
+        mChecked = mRule.isEnabled();
+        setAttributes(mRule);
+        setWidgetLayoutResource(getSecondTargetResId());
     }
 
-    @Override
     protected int getSecondTargetResId() {
-        if (mId != null && ZenModeConfig.DEFAULT_RULE_IDS.contains(mId)) {
-            return 0;
+        if (mIntent != null) {
+            return R.layout.zen_rule_widget;
         }
-
-        return R.layout.zen_rule_widget;
+        return 0;
     }
 
     @Override
     public void onBindViewHolder(PreferenceViewHolder view) {
         super.onBindViewHolder(view);
+        View settingsWidget = view.findViewById(android.R.id.widget_frame);
+        View divider = view.findViewById(R.id.two_target_divider);
+        if (mIntent != null) {
+            divider.setVisibility(View.VISIBLE);
+            settingsWidget.setVisibility(View.VISIBLE);
+            settingsWidget.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mContext.startActivity(mIntent);
+                }
+            });
+        } else {
+            divider.setVisibility(View.GONE);
+            settingsWidget.setVisibility(View.GONE);
+            settingsWidget.setOnClickListener(null);
+        }
 
-        View v = view.findViewById(R.id.delete_zen_rule);
-        if (v != null) {
-            v.setOnClickListener(mDeleteListener);
+        View checkboxContainer = view.findViewById(R.id.checkbox_container);
+        if (checkboxContainer != null) {
+            checkboxContainer.setOnClickListener(mOnCheckBoxClickListener);
+        }
+        mCheckBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
+        if (mCheckBox != null) {
+            mCheckBox.setChecked(mChecked);
         }
     }
 
-    private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
+    public boolean isChecked() {
+        return mChecked;
+    }
+
+    public void updatePreference(AutomaticZenRule rule) {
+        if (!mRule.getName().equals(rule.getName())) {
+            mName = rule.getName();
+            setTitle(mName);
+            mRule.setName(mName.toString());
+        }
+
+        if (mRule.isEnabled() != rule.isEnabled()) {
+            mRule.setEnabled(rule.isEnabled());
+            setChecked(mRule.isEnabled());
+            setSummary(computeRuleSummary(mRule));
+        }
+    }
+
+    @Override
+    public void onClick() {
+        mOnCheckBoxClickListener.onClick(null);
+    }
+
+    private void setChecked(boolean checked) {
+        mChecked = checked;
+        if (mCheckBox != null) {
+            mCheckBox.setChecked(checked);
+        }
+    }
+
+    private View.OnClickListener mOnCheckBoxClickListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            showDeleteRuleDialog(mParent, mId, mName.toString());
+            mRule.setEnabled(!mChecked);
+            mBackend.updateZenRule(mId, mRule);
+            setChecked(mRule.isEnabled());
+            setAttributes(mRule);
         }
     };
 
-    private void showDeleteRuleDialog(final Fragment parent, final String ruleId,
-            final String ruleName) {
-        ZenDeleteRuleDialog.show(parent, ruleName, ruleId,
-                new ZenDeleteRuleDialog.PositiveClickListener() {
-                    @Override
-                    public void onOk(String id) {
-                        mMetricsFeatureProvider.action(mContext,
-                                MetricsProto.MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
-                        mBackend.removeZenRule(id);
-                    }
-                });
-    }
-
     protected void setAttributes(AutomaticZenRule rule) {
         final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
                 rule.getConditionId(), true);
         final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
-        final boolean isSystemRule = isSchedule || isEvent;
+        mIsSystemRule = isSchedule || isEvent;
 
         try {
             ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
-            setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
+            setSummary(computeRuleSummary(rule));
         } catch (PackageManager.NameNotFoundException e) {
             appExists = false;
             return;
         }
 
         appExists = true;
-        setTitle(rule.getName());
+        setTitle(mName);
         setPersistent(false);
 
         final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
@@ -134,14 +182,12 @@
         ServiceInfo si = mServiceListing.findService(rule.getOwner());
         ComponentName settingsActivity = AbstractZenModeAutomaticRulePreferenceController.
                 getSettingsActivity(si);
-        setIntent(AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
-                settingsActivity, mId));
-        setSelectable(settingsActivity != null || isSystemRule);
+        mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
+                settingsActivity, mId);
         setKey(mId);
     }
 
-    private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
-            CharSequence providerLabel) {
+    private String computeRuleSummary(AutomaticZenRule rule) {
         return (rule == null || !rule.isEnabled())
                 ? mContext.getResources().getString(R.string.switch_off_text)
                 : mContext.getResources().getString(R.string.switch_on_text);
diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java
index 5b7bc32..aae42f8 100644
--- a/src/com/android/settings/panel/InternetConnectivityPanel.java
+++ b/src/com/android/settings/panel/InternetConnectivityPanel.java
@@ -47,8 +47,8 @@
     }
 
     @Override
-    public String getTitle() {
-        return (String) mContext.getText(R.string.internet_connectivity_panel_title);
+    public CharSequence getTitle() {
+        return mContext.getText(R.string.internet_connectivity_panel_title);
     }
 
     @Override
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 2e84078..503a5c3 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -25,6 +25,8 @@
         switch (panelType) {
             case SettingsPanelActivity.PANEL_TYPE_WIFI:
                 return InternetConnectivityPanel.create(context);
+            case SettingsPanelActivity.PANEL_TYPE_VOLUME:
+                return VolumePanel.create(context);
         }
 
         throw new IllegalStateException("No matching panel for: "  + panelType);
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index db1f60d..09bead4 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -54,6 +54,9 @@
     // TODO (b/117804442) move to framework
     public static final String PANEL_TYPE_WIFI = "wifi_panel";
 
+    // TODO (b/117804442) move to framework
+    public static final String PANEL_TYPE_VOLUME = "volume_panel";
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
new file mode 100644
index 0000000..c0118d7
--- /dev/null
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -0,0 +1,64 @@
+/*
+ * 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.panel;
+
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_ALARM_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_CALL_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_RINGER_URI;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import java.util.ArrayList;
+import java.util.List;
+
+public class VolumePanel implements PanelContent {
+
+    private final Context mContext;
+
+    public static VolumePanel create(Context context) {
+        return new VolumePanel(context);
+    }
+
+    private VolumePanel(Context context) {
+        mContext = context.getApplicationContext();
+    }
+
+    @Override
+    public CharSequence getTitle() {
+        return mContext.getText(R.string.volume_connectivity_panel_title);
+    }
+
+    @Override
+    public List<Uri> getSlices() {
+        final List<Uri> uris = new ArrayList<>();
+        uris.add(VOLUME_MEDIA_URI);
+        uris.add(VOLUME_CALL_URI);
+        uris.add(VOLUME_RINGER_URI);
+        uris.add(VOLUME_ALARM_URI);
+        return uris;
+    }
+
+    @Override
+    public Intent getSeeMoreIntent() {
+        return new Intent(Settings.ACTION_SOUND_SETTINGS);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
index bef72b7..4a9de15 100644
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ b/src/com/android/settings/slices/CustomSliceManager.java
@@ -22,13 +22,16 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import com.android.settings.flashlight.FlashlightSlice;
 import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
 import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
 import com.android.settings.homepage.contextualcards.deviceinfo.DeviceInfoSlice;
+import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
 import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
 import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
+import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
 import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
+import com.android.settings.location.LocationSlice;
 import com.android.settings.wifi.WifiSlice;
 
 import java.util.Map;
@@ -103,9 +106,12 @@
     private void addSlices() {
         mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
         mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class);
-        mUriMap.put(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI, ConnectedDeviceSlice.class);
+        mUriMap.put(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
         mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class);
         mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
+        mUriMap.put(CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
+        mUriMap.put(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
+        mUriMap.put(CustomSliceRegistry.LOCATION_SLICE_URI, LocationSlice.class);
         mUriMap.put(CustomSliceRegistry.LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
         mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class);
         mUriMap.put(CustomSliceRegistry.WIFI_SLICE_URI, WifiSlice.class);
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index f2b3299..1b8cffe 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -72,13 +72,13 @@
             .build();
 
     /**
-     * Backing Uri for Connected device Slice.
+     * Backing Uri for Bluetooth devices Slice.
      */
-    public static final Uri CONNECTED_DEVICE_SLICE_URI = new Uri.Builder()
+    public static final Uri BLUETOOTH_DEVICES_SLICE_URI = new Uri.Builder()
             .scheme(ContentResolver.SCHEME_CONTENT)
             .authority(SettingsSliceProvider.SLICE_AUTHORITY)
             .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
-            .appendPath("connected_device")
+            .appendPath("bluetooth_devices")
             .build();
     /**
      * Backing Uri for the Data usage Slice.
@@ -86,6 +86,7 @@
     public static final Uri DATA_USAGE_SLICE_URI = new Uri.Builder()
             .scheme(ContentResolver.SCHEME_CONTENT)
             .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
             .appendPath("data_usage_card")
             .build();
     /**
@@ -94,6 +95,7 @@
     public static final Uri DEVICE_INFO_SLICE_URI = new Uri.Builder()
             .scheme(ContentResolver.SCHEME_CONTENT)
             .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
             .appendPath("device_info_card")
             .build();
     /**
@@ -102,6 +104,7 @@
     public static final Uri EMERGENCY_INFO_SLICE_URI = new Uri.Builder()
             .scheme(ContentResolver.SCHEME_CONTENT)
             .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
             .appendPath("emergency_info_card")
             .build();
     /**
@@ -110,6 +113,7 @@
     public static final Uri ENHANCED_4G_SLICE_URI = new Uri.Builder()
             .scheme(ContentResolver.SCHEME_CONTENT)
             .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
             .appendPath("enhanced_4g_lte")
             .build();
     /**
@@ -145,14 +149,53 @@
     public static final Uri STORAGE_SLICE_URI = new Uri.Builder()
             .scheme(ContentResolver.SCHEME_CONTENT)
             .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
             .appendPath("storage_card")
             .build();
     /**
+     * Full {@link Uri} for the Alarm volume Slice.
+     */
+    public static final Uri VOLUME_ALARM_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("alarm_volume")
+            .build();
+    /**
+     * Full {@link Uri} for the Call Volume Slice.
+     */
+    public static final Uri VOLUME_CALL_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("call_volume")
+            .build();
+    /**
+     * Full {@link Uri} for the Media Volume Slice.
+     */
+    public static final Uri VOLUME_MEDIA_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("media_volume")
+            .build();
+    /**
+     * Full {@link Uri} for the Ringer volume Slice.
+     */
+    public static final Uri VOLUME_RINGER_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("ring_volume")
+            .build();
+
+    /**
      * Full {@link Uri} for the Wifi Calling Slice.
      */
     public static final Uri WIFI_CALLING_URI = new Uri.Builder()
             .scheme(ContentResolver.SCHEME_CONTENT)
             .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
             .appendPath(WifiCallingSliceHelper.PATH_WIFI_CALLING)
             .build();
     /**
@@ -161,6 +204,7 @@
     public static final Uri WIFI_CALLING_PREFERENCE_URI = new Uri.Builder()
             .scheme(ContentResolver.SCHEME_CONTENT)
             .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
             .appendPath(WifiCallingSliceHelper.PATH_WIFI_CALLING_PREFERENCE)
             .build();
     /**
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 109f02e..80b7133 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -41,9 +41,6 @@
 import com.android.settings.R;
 import com.android.settings.bluetooth.BluetoothSliceBuilder;
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.flashlight.FlashlightSliceBuilder;
-import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
-import com.android.settings.location.LocationSliceBuilder;
 import com.android.settings.notification.ZenModeSliceBuilder;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.SliceBroadcastRelay;
@@ -182,12 +179,6 @@
         } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
             registerIntentToUri(BluetoothSliceBuilder.INTENT_FILTER, sliceUri);
             return;
-        } else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
-            registerIntentToUri(FlashlightSliceBuilder.INTENT_FILTER, sliceUri);
-            mRegisteredUris.add(sliceUri);
-            return;
-        } else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
-            return;
         }
 
         // Start warming the slice, we expect someone will want it soon.
@@ -240,8 +231,6 @@
                 return ZenModeSliceBuilder.getSlice(getContext());
             } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
                 return BluetoothSliceBuilder.getSlice(getContext());
-            } else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
-                return LocationSliceBuilder.getSlice(getContext());
             } else if (CustomSliceRegistry.ENHANCED_4G_SLICE_URI.equals(sliceUri)) {
                 return FeatureFactory.getFactory(getContext())
                         .getSlicesFeatureProvider()
@@ -252,10 +241,6 @@
                         .getSlicesFeatureProvider()
                         .getNewWifiCallingSliceHelper(getContext())
                         .createWifiCallingPreferenceSlice(sliceUri);
-            } else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
-                return FlashlightSliceBuilder.getSlice(getContext());
-            } else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
-                return EmergencyInfoSlice.getSlice(getContext());
             }
 
             SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 2860e9a..823c729 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -17,7 +17,6 @@
 package com.android.settings.slices;
 
 import static com.android.settings.bluetooth.BluetoothSliceBuilder.ACTION_BLUETOOTH_SLICE_CHANGED;
-import static com.android.settings.flashlight.FlashlightSliceBuilder.ACTION_FLASHLIGHT_SLICE_CHANGED;
 import static com.android.settings.network.telephony.Enhanced4gLteSliceHelper.ACTION_ENHANCED_4G_LTE_CHANGED;
 import static com.android.settings.notification.ZenModeSliceBuilder.ACTION_ZEN_MODE_SLICE_CHANGED;
 import static com.android.settings.slices.SettingsSliceProvider.ACTION_COPY;
@@ -46,7 +45,6 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.SliderPreferenceController;
 import com.android.settings.core.TogglePreferenceController;
-import com.android.settings.flashlight.FlashlightSliceBuilder;
 import com.android.settings.notification.ZenModeSliceBuilder;
 import com.android.settings.overlay.FeatureFactory;
 
@@ -108,9 +106,6 @@
                         .getNewWifiCallingSliceHelper(context)
                         .handleWifiCallingPreferenceChanged(intent);
                 break;
-            case ACTION_FLASHLIGHT_SLICE_CHANGED:
-                FlashlightSliceBuilder.handleUriChange(context, intent);
-                break;
             case ACTION_COPY:
                 handleCopyAction(context, key, isPlatformSlice);
                 break;
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index 76eefac..d75eaa2 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -168,10 +168,11 @@
      * @return {@link PendingIntent} for a non-primary {@link SliceAction}.
      */
     public static PendingIntent getActionIntent(Context context, String action, SliceData data) {
-        final Intent intent = new Intent(action);
-        intent.setClass(context, SliceBroadcastReceiver.class);
-        intent.putExtra(EXTRA_SLICE_KEY, data.getKey());
-        intent.putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
+        final Intent intent = new Intent(action)
+                .setData(data.getUri())
+                .setClass(context, SliceBroadcastReceiver.class)
+                .putExtra(EXTRA_SLICE_KEY, data.getKey())
+                .putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
         return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
                 PendingIntent.FLAG_CANCEL_CURRENT);
     }
@@ -193,8 +194,9 @@
         CharSequence summaryText = controller.getSummary();
 
         // Priority 1 : User prefers showing the dynamic summary in slice view rather than static
-        // summary.
-        if (isDynamicSummaryAllowed && isValidSummary(context, summaryText)) {
+        // summary. Note it doesn't require a valid summary - so we can force some slices to have
+        // empty summaries (ex: volume).
+        if (isDynamicSummaryAllowed) {
             return summaryText;
         }
 
@@ -447,6 +449,12 @@
         if (iconResource == 0) {
             iconResource = R.drawable.ic_settings;
         }
-        return IconCompat.createWithResource(context, iconResource);
+        try {
+            return IconCompat.createWithResource(context, iconResource);
+        } catch (Exception e) {
+            Log.w(TAG, "Falling back to settings icon because there is an error getting slice icon "
+                    + data.getUri(), e);
+            return IconCompat.createWithResource(context, R.drawable.ic_settings);
+        }
     }
 }
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index 01708af..d633b7a 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -24,7 +24,6 @@
 import androidx.annotation.Keep;
 
 import com.android.settings.bluetooth.BluetoothSliceBuilder;
-import com.android.settings.location.LocationSliceBuilder;
 import com.android.settings.notification.ZenModeSliceBuilder;
 import com.android.settings.overlay.FeatureFactory;
 
@@ -66,8 +65,6 @@
                     launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
                 } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
                     launchIntent = BluetoothSliceBuilder.getIntent(this /* context */);
-                } else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
-                    launchIntent = LocationSliceBuilder.getIntent(this /* context */);
                 } else {
                     final SlicesDatabaseAccessor slicesDatabaseAccessor =
                             new SlicesDatabaseAccessor(this /* context */);
diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java
index b1a1f8f..bd85ef3 100644
--- a/src/com/android/settings/tts/TextToSpeechSettings.java
+++ b/src/com/android/settings/tts/TextToSpeechSettings.java
@@ -44,15 +44,14 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settings.widget.GearPreference;
 import com.android.settings.widget.SeekBarPreference;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -113,7 +112,7 @@
 
     private SeekBarPreference mDefaultPitchPref;
     private SeekBarPreference mDefaultRatePref;
-    private ActionButtonPreference mActionButtons;
+    private ActionButtonsPreference mActionButtons;
 
     private int mDefaultPitch = TextToSpeech.Engine.DEFAULT_PITCH;
     private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
@@ -169,7 +168,7 @@
         mDefaultPitchPref = (SeekBarPreference) findPreference(KEY_DEFAULT_PITCH);
         mDefaultRatePref = (SeekBarPreference) findPreference(KEY_DEFAULT_RATE);
 
-        mActionButtons = ((ActionButtonPreference) findPreference(KEY_ACTION_BUTTONS))
+        mActionButtons = ((ActionButtonsPreference) findPreference(KEY_ACTION_BUTTONS))
                 .setButton1Text(R.string.tts_play)
                 .setButton1OnClickListener(v -> speakSampleText())
                 .setButton1Enabled(false)
diff --git a/src/com/android/settings/widget/ActionButtonPreference.java b/src/com/android/settings/widget/ActionButtonPreference.java
deleted file mode 100644
index a34d735..0000000
--- a/src/com/android/settings/widget/ActionButtonPreference.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.StringRes;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-/**
- * This preference provides a four buttons layout with Settings style.
- * It looks like below
- *
- * --------------------------------------------------
- *  button1     | button2   | button3   | button4   |
- * --------------------------------------------------
- *
- * User can set title / icon / click listener for each button.
- *
- * By default, four buttons are visible.
- * However, there are two cases which button should be invisible(View.GONE).
- *
- * 1. User sets invisible for button. ex: ActionButtonPreference.setButton1Visible(false)
- * 2. User doesn't set any title or icon for button.
- *
- */
-public class ActionButtonPreference extends Preference {
-
-    private final String TAG = "ActionButtonPreference";
-    private final ButtonInfo mButton1Info = new ButtonInfo();
-    private final ButtonInfo mButton2Info = new ButtonInfo();
-    private final ButtonInfo mButton3Info = new ButtonInfo();
-    private final ButtonInfo mButton4Info = new ButtonInfo();
-
-    public ActionButtonPreference(Context context, AttributeSet attrs,
-            int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        init();
-    }
-
-    public ActionButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        init();
-    }
-
-    public ActionButtonPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public ActionButtonPreference(Context context) {
-        super(context);
-        init();
-    }
-
-    private void init() {
-        setLayoutResource(R.layout.settings_action_buttons);
-        setSelectable(false);
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-        holder.setDividerAllowedAbove(true);
-        holder.setDividerAllowedBelow(true);
-
-        mButton1Info.mButton = (Button) holder.findViewById(R.id.button1);
-        mButton2Info.mButton = (Button) holder.findViewById(R.id.button2);
-        mButton3Info.mButton = (Button) holder.findViewById(R.id.button3);
-        mButton4Info.mButton = (Button) holder.findViewById(R.id.button4);
-
-        mButton1Info.setUpButton();
-        mButton2Info.setUpButton();
-        mButton3Info.setUpButton();
-        mButton4Info.setUpButton();
-    }
-
-    public ActionButtonPreference setButton1Visible(boolean isVisible) {
-        if (isVisible != mButton1Info.mIsVisible) {
-            mButton1Info.mIsVisible = isVisible;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton1Text(@StringRes int textResId) {
-        final String newText = getContext().getString(textResId);
-        if (!TextUtils.equals(newText, mButton1Info.mText)) {
-            mButton1Info.mText = newText;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton1Icon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return this;
-        }
-
-        final Drawable icon;
-        try {
-            icon = getContext().getDrawable(iconResId);
-            mButton1Info.mIcon = icon;
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton1Enabled(boolean isEnabled) {
-        if (isEnabled != mButton1Info.mIsEnabled) {
-            mButton1Info.mIsEnabled = isEnabled;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton1OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton1Info.mListener) {
-            mButton1Info.mListener = listener;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2Visible(boolean isVisible) {
-        if (isVisible != mButton2Info.mIsVisible) {
-            mButton2Info.mIsVisible = isVisible;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2Text(@StringRes int textResId) {
-        final String newText = getContext().getString(textResId);
-        if (!TextUtils.equals(newText, mButton2Info.mText)) {
-            mButton2Info.mText = newText;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2Icon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return this;
-        }
-
-        final Drawable icon;
-        try {
-            icon = getContext().getDrawable(iconResId);
-            mButton2Info.mIcon = icon;
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2Enabled(boolean isEnabled) {
-        if (isEnabled != mButton2Info.mIsEnabled) {
-            mButton2Info.mIsEnabled = isEnabled;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton2Info.mListener) {
-            mButton2Info.mListener = listener;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3Visible(boolean isVisible) {
-        if (isVisible != mButton3Info.mIsVisible) {
-            mButton3Info.mIsVisible = isVisible;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3Text(@StringRes int textResId) {
-        final String newText = getContext().getString(textResId);
-        if (!TextUtils.equals(newText, mButton3Info.mText)) {
-            mButton3Info.mText = newText;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3Icon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return this;
-        }
-
-        final Drawable icon;
-        try {
-            icon = getContext().getDrawable(iconResId);
-            mButton3Info.mIcon = icon;
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3Enabled(boolean isEnabled) {
-        if (isEnabled != mButton3Info.mIsEnabled) {
-            mButton3Info.mIsEnabled = isEnabled;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton3Info.mListener) {
-            mButton3Info.mListener = listener;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4Visible(boolean isVisible) {
-        if (isVisible != mButton4Info.mIsVisible) {
-            mButton4Info.mIsVisible = isVisible;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4Text(@StringRes int textResId) {
-        final String newText = getContext().getString(textResId);
-        if (!TextUtils.equals(newText, mButton4Info.mText)) {
-            mButton4Info.mText = newText;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4Icon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return this;
-        }
-
-        final Drawable icon;
-        try {
-            icon = getContext().getDrawable(iconResId);
-            mButton4Info.mIcon = icon;
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4Enabled(boolean isEnabled) {
-        if (isEnabled != mButton4Info.mIsEnabled) {
-            mButton4Info.mIsEnabled = isEnabled;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton4Info.mListener) {
-            mButton4Info.mListener = listener;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    static class ButtonInfo {
-        private Button mButton;
-        private CharSequence mText;
-        private Drawable mIcon;
-        private View.OnClickListener mListener;
-        private boolean mIsEnabled = true;
-        private boolean mIsVisible = true;
-
-        void setUpButton() {
-            mButton.setText(mText);
-            mButton.setOnClickListener(mListener);
-            mButton.setEnabled(mIsEnabled);
-            mButton.setCompoundDrawablesWithIntrinsicBounds(
-                    null /* left */, mIcon /* top */, null /* right */, null /* bottom */);
-
-            if (shouldBeVisible()) {
-                mButton.setVisibility(View.VISIBLE);
-            } else {
-                mButton.setVisibility(View.GONE);
-            }
-        }
-
-        /**
-         * By default, four buttons are visible.
-         * However, there are two cases which button should be invisible.
-         *
-         * 1. User set invisible for this button. ex: mIsVisible = false.
-         * 2. User didn't set any title or icon.
-         *
-         */
-        private boolean shouldBeVisible() {
-            return mIsVisible && (!TextUtils.isEmpty(mText) || mIcon != null);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/widget/FloatingAppBarScrollingViewBehavior.java b/src/com/android/settings/widget/FloatingAppBarScrollingViewBehavior.java
new file mode 100644
index 0000000..23f6ccd
--- /dev/null
+++ b/src/com/android/settings/widget/FloatingAppBarScrollingViewBehavior.java
@@ -0,0 +1,61 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+
+import com.google.android.material.appbar.AppBarLayout;
+
+/**
+ * This scrolling view behavior will set the background of the {@link AppBarLayout} as
+ * transparent and without the elevation. Also make header overlapped the scrolling child view.
+ */
+public class FloatingAppBarScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior {
+    private boolean initialized;
+
+    public FloatingAppBarScrollingViewBehavior(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
+        boolean changed = super.onDependentViewChanged(parent, child, dependency);
+        if (!initialized && dependency instanceof AppBarLayout) {
+            initialized = true;
+            AppBarLayout appBarLayout = (AppBarLayout) dependency;
+            setAppBarLayoutTransparent(appBarLayout);
+        }
+        return changed;
+    }
+
+    @VisibleForTesting
+    void setAppBarLayoutTransparent(AppBarLayout appBarLayout) {
+        appBarLayout.setBackgroundColor(Color.TRANSPARENT);
+        appBarLayout.setTargetElevation(0);
+    }
+
+    @Override
+    protected boolean shouldHeaderOverlapScrollingChild() {
+        return true;
+    }
+}
diff --git a/src/com/android/settings/widget/RadioButtonPickerFragment.java b/src/com/android/settings/widget/RadioButtonPickerFragment.java
index 89df487..50c1b58 100644
--- a/src/com/android/settings/widget/RadioButtonPickerFragment.java
+++ b/src/com/android/settings/widget/RadioButtonPickerFragment.java
@@ -22,10 +22,12 @@
 import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import android.widget.Toast;
 import androidx.annotation.LayoutRes;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -34,16 +36,23 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.core.PreferenceXmlParserUtils;
+import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
 import com.android.settingslib.widget.CandidateInfo;
 
+import java.io.IOException;
 import java.util.List;
 import java.util.Map;
+import org.xmlpull.v1.XmlPullParserException;
 
 public abstract class RadioButtonPickerFragment extends InstrumentedPreferenceFragment implements
         RadioButtonPreference.OnClickListener {
 
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    @VisibleForTesting
     static final String EXTRA_FOR_WORK = "for_work";
+    private static final String TAG = "RadioButtonPckrFrgmt";
+    @VisibleForTesting
+    boolean mAppendStaticPreferences = false;
 
     private final Map<String, CandidateInfo> mCandidates = new ArrayMap<>();
 
@@ -69,6 +78,19 @@
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         super.onCreatePreferences(savedInstanceState, rootKey);
+        try {
+            // Check if the xml specifies if static preferences should go on the top or bottom
+            final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(getContext(),
+                getPreferenceScreenResId(),
+                MetadataFlag.FLAG_INCLUDE_PREF_SCREEN |
+                MetadataFlag.FLAG_NEED_PREF_APPEND);
+            mAppendStaticPreferences = metadata.get(0)
+                    .getBoolean(PreferenceXmlParserUtils.METADATA_APPEND);
+        } catch (IOException e) {
+            Log.e(TAG, "Error trying to open xml file", e);
+        } catch (XmlPullParserException e) {
+            Log.e(TAG, "Error parsing xml", e);
+        }
         updateCandidates();
     }
 
@@ -142,7 +164,9 @@
         final String systemDefaultKey = getSystemDefaultKey();
         final PreferenceScreen screen = getPreferenceScreen();
         screen.removeAll();
-        addStaticPreferences(screen);
+        if (!mAppendStaticPreferences) {
+            addStaticPreferences(screen);
+        }
 
         final int customLayoutResId = getRadioButtonPreferenceCustomLayoutResId();
         if (shouldShowItemNone()) {
@@ -168,6 +192,9 @@
             }
         }
         mayCheckOnlyRadioButton();
+        if (mAppendStaticPreferences) {
+            addStaticPreferences(screen);
+        }
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/wifi/CellularFallbackPreferenceController.java b/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
index a883826..cbb8fb8 100644
--- a/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
+++ b/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
@@ -18,62 +18,34 @@
 
 import android.content.Context;
 import android.provider.Settings;
-import android.text.TextUtils;
 
-import androidx.preference.Preference;
-import androidx.preference.SwitchPreference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settings.core.TogglePreferenceController;
 
 /**
- * {@link AbstractPreferenceController} that controls whether we should fall back to celluar when
+ * CellularFallbackPreferenceController controls whether we should fall back to celluar when
  * wifi is bad.
  */
-public class CellularFallbackPreferenceController extends AbstractPreferenceController
-        implements PreferenceControllerMixin {
+public class CellularFallbackPreferenceController extends TogglePreferenceController {
 
-    private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
-
-
-    public CellularFallbackPreferenceController(Context context) {
-        super(context);
+    public CellularFallbackPreferenceController(Context context, String key) {
+        super(context, key);
     }
 
     @Override
-    public boolean isAvailable() {
-        return !avoidBadWifiConfig();
+    public int getAvailabilityStatus() {
+        return !avoidBadWifiConfig() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
-    public String getPreferenceKey() {
-        return KEY_CELLULAR_FALLBACK;
+    public boolean isChecked() {
+        return avoidBadWifiCurrentSettings();
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        if (!TextUtils.equals(preference.getKey(), KEY_CELLULAR_FALLBACK)) {
-            return false;
-        }
-        if (!(preference instanceof SwitchPreference)) {
-            return false;
-        }
+    public boolean setChecked(boolean isChecked) {
         // On: avoid bad wifi. Off: prompt.
-        String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
-        Settings.Global.putString(mContext.getContentResolver(), settingName,
-                ((SwitchPreference) preference).isChecked() ? "1" : null);
-        return true;
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        final boolean currentSetting = avoidBadWifiCurrentSettings();
-        // TODO: can this ever be null? The return value of avoidBadWifiConfig() can only
-        // change if the resources change, but if that happens the activity will be recreated...
-        if (preference != null) {
-            SwitchPreference pref = (SwitchPreference) preference;
-            pref.setChecked(currentSetting);
-        }
+        return Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.NETWORK_AVOID_BAD_WIFI, isChecked ? "1" : null);
     }
 
     private boolean avoidBadWifiConfig() {
@@ -85,4 +57,4 @@
         return "1".equals(Settings.Global.getString(mContext.getContentResolver(),
                 Settings.Global.NETWORK_AVOID_BAD_WIFI));
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index 1d1c30c..8df4a41 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -85,7 +85,6 @@
         controllers.add(mUseOpenWifiPreferenceController);
         controllers.add(new WifiInfoPreferenceController(context, getSettingsLifecycle(),
                 wifiManager));
-        controllers.add(new CellularFallbackPreferenceController(context));
         controllers.add(new WifiP2pPreferenceController(context, getSettingsLifecycle(),
                 wifiManager));
         return controllers;
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index a1d8620..efb3f8c 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -44,12 +44,18 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
 import com.android.settingslib.Utils;
 import com.android.settingslib.wifi.AccessPoint;
 
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * The Fragment sets up callback {@link NetworkRequestMatchCallback} with framework. To handle most
+ * behaviors of the callback when requesting wifi network, except for error message. When error
+ * happens, {@link NetworkRequestErrorDialogFragment} will be called to display error message.
+ */
 public class NetworkRequestDialogFragment extends InstrumentedDialogFragment implements
         DialogInterface.OnClickListener, NetworkRequestMatchCallback {
 
@@ -131,7 +137,7 @@
     @Override
     public void onCancel(@NonNull DialogInterface dialog) {
         super.onCancel(dialog);
-        // Finishes activity when user clicks back key or outside of dialog.
+        // Finishes the activity when user clicks back key or outside of the dialog.
         getActivity().finish();
     }
 
@@ -166,7 +172,7 @@
             switch (msg.what) {
                 case MESSAGE_STOP_SCAN_WIFI_LIST:
                     removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
-                    stopScanningAndPopTimeoutDialog();
+                    stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT);
                     break;
                 default:
                     // Do nothing.
@@ -175,14 +181,18 @@
         }
     };
 
-    protected void stopScanningAndPopTimeoutDialog() {
+    protected void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
         // Dismisses current dialog.
         dismiss();
 
         // Throws new timeout dialog.
-        final NetworkRequestTimeoutDialogFragment fragment = NetworkRequestTimeoutDialogFragment
+        final NetworkRequestErrorDialogFragment fragment = NetworkRequestErrorDialogFragment
                 .newInstance();
-        fragment.show(getActivity().getSupportFragmentManager(), null);
+        final Bundle bundle = new Bundle();
+        bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type);
+        fragment.setArguments(bundle);
+        fragment.show(getActivity().getSupportFragmentManager(),
+                NetworkRequestDialogFragment.class.getSimpleName());
     }
 
     @Override
@@ -239,7 +249,7 @@
 
     @Override
     public void onAbort() {
-        // TODO(b/117399926): We should have a UI notify user here.
+        stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/NetworkRequestErrorDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestErrorDialogFragment.java
new file mode 100644
index 0000000..762b467
--- /dev/null
+++ b/src/com/android/settings/wifi/NetworkRequestErrorDialogFragment.java
@@ -0,0 +1,86 @@
+/*
+ * 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.wifi;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/**
+ * The dialog shows an error message when requesting network {@link NetworkRequestDialogFragment}.
+ * Contains multi-error types in {@code ERROR_DIALOG_TYPE}.
+ */
+public class NetworkRequestErrorDialogFragment extends InstrumentedDialogFragment {
+
+    public static final String DIALOG_TYPE = "DIALOG_ERROR_TYPE";
+
+    public enum ERROR_DIALOG_TYPE {TIME_OUT, ABORT}
+
+    public static NetworkRequestErrorDialogFragment newInstance() {
+        return new NetworkRequestErrorDialogFragment();
+    }
+
+    private NetworkRequestErrorDialogFragment() {
+        super();
+    }
+
+    @Override
+    public void onCancel(@NonNull DialogInterface dialog) {
+        super.onCancel(dialog);
+        // Wants to finish the activity when user clicks back key or outside of the dialog.
+        getActivity().finish();
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // Gets error type to construct dialog. Default is TIME_OUT dialog.
+        ERROR_DIALOG_TYPE msgType = ERROR_DIALOG_TYPE.TIME_OUT;
+        if (getArguments() != null) {
+            msgType = (ERROR_DIALOG_TYPE) getArguments().getSerializable(DIALOG_TYPE);
+        }
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+        if (msgType == ERROR_DIALOG_TYPE.TIME_OUT) {
+            builder.setMessage(R.string.network_connection_timeout_dialog_message)
+                    .setPositiveButton(R.string.network_connection_timeout_dialog_ok,
+                            (dialog, which) -> startScanningDialog())
+                    .setNegativeButton(R.string.cancel, (dialog, which) -> getActivity().finish());
+        } else {
+            builder.setMessage(R.string.network_connection_errorstate_dialog_message)
+                    .setPositiveButton(R.string.okay, (dialog, which) -> getActivity().finish());
+        }
+        return builder.create();
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.WIFI_SCANNING_NEEDED_DIALOG;
+    }
+
+    protected void startScanningDialog() {
+        final NetworkRequestDialogFragment fragment = NetworkRequestDialogFragment.newInstance();
+        fragment.show(getActivity().getSupportFragmentManager(),
+                NetworkRequestErrorDialogFragment.class.getSimpleName());
+    }
+}
diff --git a/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragment.java
deleted file mode 100644
index 08f285b..0000000
--- a/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragment.java
+++ /dev/null
@@ -1,66 +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.wifi;
-
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import androidx.appcompat.app.AlertDialog;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.R;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-
-public class NetworkRequestTimeoutDialogFragment extends InstrumentedDialogFragment implements
-    DialogInterface.OnClickListener {
-
-  public static NetworkRequestTimeoutDialogFragment newInstance() {
-    NetworkRequestTimeoutDialogFragment fragment = new NetworkRequestTimeoutDialogFragment();
-    return fragment;
-  }
-
-  @Override
-  public Dialog onCreateDialog(Bundle savedInstanceState) {
-    AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
-        .setMessage(R.string.network_connection_timeout_dialog_message)
-        .setPositiveButton(R.string.network_connection_timeout_dialog_ok, this)
-        .setNegativeButton(R.string.cancel, null);
-    return builder.create();
-  }
-
-  @Override
-  public int getMetricsCategory() {
-    return MetricsProto.MetricsEvent.WIFI_SCANNING_NEEDED_DIALOG;
-  }
-
-  @Override
-  public void onClick(DialogInterface dialog, int which) {
-    switch (which) {
-      case DialogInterface.BUTTON_POSITIVE:
-        startScanningDialog();
-        break;
-      case DialogInterface.BUTTON_NEGATIVE:
-      default:
-        // Do nothing.
-        break;
-    }
-  }
-
-  protected void startScanningDialog() {
-    NetworkRequestDialogFragment fragment = NetworkRequestDialogFragment.newInstance();
-    fragment.show(getActivity().getSupportFragmentManager(), null);
-  }
-}
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/WifiSlice.java
index 2382abb..64e3fc3 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/WifiSlice.java
@@ -37,7 +37,6 @@
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
 import androidx.slice.builders.ListBuilder;
-import androidx.slice.builders.ListBuilder.RowBuilder;
 import androidx.slice.builders.SliceAction;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -64,9 +63,11 @@
     static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
 
     private final Context mContext;
+    private final WifiManager mWifiManager;
 
     public WifiSlice(Context context) {
         mContext = context;
+        mWifiManager = mContext.getSystemService(WifiManager.class);
     }
 
     @Override
@@ -100,7 +101,7 @@
         final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_SLICE_URI,
                 ListBuilder.INFINITY)
                 .setAccentColor(color)
-                .addRow(new RowBuilder()
+                .addRow(new ListBuilder.RowBuilder()
                         .setTitle(title)
                         .setSubtitle(summary)
                         .addEndItem(toggleSliceAction)
@@ -110,18 +111,25 @@
             return listBuilder.build();
         }
 
-        List<AccessPoint> results = SliceBackgroundWorker.getInstance(mContext, this).getResults();
-        if (results == null) {
-            results = new ArrayList<>();
-        }
-        final int apCount = results.size();
+        final List<AccessPoint> results =
+                SliceBackgroundWorker.getInstance(mContext, this).getResults();
+
+        // Need a loading text when results are not ready.
+        boolean needLoadingRow = results == null;
+        final int apCount = needLoadingRow ? 0 : results.size();
+
         // Add AP rows
         final CharSequence placeholder = mContext.getText(R.string.summary_placeholder);
         for (int i = 0; i < DEFAULT_EXPANDED_ROW_COUNT; i++) {
             if (i < apCount) {
                 listBuilder.addRow(getAccessPointRow(results.get(i)));
+            } else if (needLoadingRow) {
+                listBuilder.addRow(new ListBuilder.RowBuilder()
+                        .setTitle(mContext.getText(R.string.wifi_empty_list_wifi_on))
+                        .setSubtitle(placeholder));
+                needLoadingRow = false;
             } else {
-                listBuilder.addRow(new RowBuilder()
+                listBuilder.addRow(new ListBuilder.RowBuilder()
                         .setTitle(placeholder)
                         .setSubtitle(placeholder));
             }
@@ -129,12 +137,12 @@
         return listBuilder.build();
     }
 
-    private RowBuilder getAccessPointRow(AccessPoint accessPoint) {
+    private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) {
         final String title = accessPoint.getConfigName();
         final IconCompat levelIcon = IconCompat.createWithResource(mContext,
                 com.android.settingslib.Utils.getWifiIconResource(accessPoint.getLevel()));
         final CharSequence apSummary = accessPoint.getSettingsSummary();
-        final RowBuilder rowBuilder = new RowBuilder()
+        final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
                 .setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
                 .setTitle(title)
                 .setSubtitle(!TextUtils.isEmpty(apSummary)
@@ -188,10 +196,9 @@
      */
     @Override
     public void onNotifyChange(Intent intent) {
-        final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
         final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
-                wifiManager.isWifiEnabled());
-        wifiManager.setWifiEnabled(newState);
+                mWifiManager.isWifiEnabled());
+        mWifiManager.setWifiEnabled(newState);
         // Do not notifyChange on Uri. The service takes longer to update the current value than it
         // does for the Slice to check the current value again. Let {@link SliceBroadcastRelay}
         // handle it.
@@ -211,26 +218,19 @@
     }
 
     private boolean isWifiEnabled() {
-        final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
-
-        switch (wifiManager.getWifiState()) {
+        switch (mWifiManager.getWifiState()) {
             case WifiManager.WIFI_STATE_ENABLED:
             case WifiManager.WIFI_STATE_ENABLING:
                 return true;
-            case WifiManager.WIFI_STATE_DISABLED:
-            case WifiManager.WIFI_STATE_DISABLING:
-            case WifiManager.WIFI_STATE_UNKNOWN:
             default:
                 return false;
         }
     }
 
     private CharSequence getSummary() {
-        final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
-
-        switch (wifiManager.getWifiState()) {
+        switch (mWifiManager.getWifiState()) {
             case WifiManager.WIFI_STATE_ENABLED:
-                final String ssid = WifiInfo.removeDoubleQuotes(wifiManager.getConnectionInfo()
+                final String ssid = WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo()
                         .getSSID());
                 if (TextUtils.equals(ssid, WifiSsid.NONE)) {
                     return mContext.getText(R.string.disconnected);
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index ba8241a..e1179f8 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -20,6 +20,7 @@
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
 import android.app.Activity;
+import android.app.KeyguardManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +41,7 @@
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.widget.ImageView;
 import android.widget.Toast;
@@ -54,9 +56,11 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settings.widget.EntityHeaderController;
+import com.android.settings.wifi.dpp.WifiDppConfiguratorActivity;
+import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settings.wifi.WifiDialog;
 import com.android.settings.wifi.WifiDialog.WifiDialogListener;
 import com.android.settings.wifi.WifiUtils;
@@ -66,6 +70,7 @@
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.AccessPoint;
 
@@ -130,7 +135,7 @@
     private final MetricsFeatureProvider mMetricsFeatureProvider;
 
     // UI elements - in order of appearance
-    private ActionButtonPreference mButtonsPref;
+    private ActionButtonsPreference mButtonsPref;
     private EntityHeaderController mEntityHeaderController;
     private Preference mSignalStrengthPref;
     private Preference mLinkSpeedPref;
@@ -275,12 +280,15 @@
 
         setupEntityHeader(screen);
 
-        mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_BUTTONS_PREF))
+        mButtonsPref = ((ActionButtonsPreference) screen.findPreference(KEY_BUTTONS_PREF))
                 .setButton1Text(R.string.forget)
                 .setButton1Icon(R.drawable.ic_settings_delete)
                 .setButton1OnClickListener(view -> forgetNetwork())
                 .setButton2Text(R.string.wifi_sign_in_button_text)
-                .setButton2OnClickListener(view -> signIntoNetwork());
+                .setButton2OnClickListener(view -> signIntoNetwork())
+                .setButton3Text(R.string.share)
+                .setButton3Icon(R.drawable.ic_qrcode_24dp)
+                .setButton3OnClickListener(view -> shareNetwork());
 
         mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
         mLinkSpeedPref = screen.findPreference(KEY_LINK_SPEED);
@@ -296,7 +304,7 @@
         mIpv6Category = (PreferenceCategory) screen.findPreference(KEY_IPV6_CATEGORY);
         mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
 
-        mSecurityPref.setSummary(mAccessPoint.getSecurityString(false /* concise */));
+        mSecurityPref.setSummary(mAccessPoint.getSecurityString(/* concise */ false));
     }
 
     private void setupEntityHeader(PreferenceScreen screen) {
@@ -425,7 +433,9 @@
 
     private void updateIpLayerInfo() {
         mButtonsPref.setButton2Visible(canSignIntoNetwork());
-        mButtonsPref.setVisible(canSignIntoNetwork() || canForgetNetwork());
+        mButtonsPref.setButton3Visible(isSharingNetworkEnabled());
+        mButtonsPref.setVisible(
+                canSignIntoNetwork() || canForgetNetwork() || isSharingNetworkEnabled());
 
         if (mNetwork == null || mLinkProperties == null) {
             mIpAddressPref.setVisible(false);
@@ -511,6 +521,13 @@
     }
 
     /**
+     * Returns whether the user can share the network represented by this preference with QR code.
+     */
+    private boolean isSharingNetworkEnabled() {
+        return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.WIFI_SHARING);
+    }
+
+    /**
      * Forgets the wifi network associated with this preference.
      */
     private void forgetNetwork() {
@@ -529,6 +546,42 @@
     }
 
     /**
+     * Show QR code to share the network represented by this preference.
+     */
+    public void launchQRCodeGenerator() {
+        final Intent intent = new Intent(
+                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY,
+                mAccessPoint.getSecurityString(/* concise */ false));
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, mAccessPoint.getSsidStr());
+        mContext.startActivity(intent);
+    }
+
+    /**
+     * Share the wifi network with QR code.
+     */
+    private void shareNetwork() {
+        final KeyguardManager keyguardManager = (KeyguardManager) mContext.getSystemService(
+                Context.KEYGUARD_SERVICE);
+        if (keyguardManager.isKeyguardSecure()) {
+            // Show authentication screen to confirm credentials (pin, pattern or password) for
+            // the current user of the device.
+            final String description = String.format(
+                    mContext.getString(R.string.wifi_sharing_message),
+                    mAccessPoint.getSsidStr());
+            final Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(
+                    mContext.getString(R.string.lockpassword_confirm_your_pattern_header),
+                    description);
+            if (intent != null) {
+                mFragment.startActivityForResult(intent,
+                        WifiNetworkDetailsFragment.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
+            }
+        } else {
+            launchQRCodeGenerator();
+        }
+    }
+
+    /**
      * Sign in to the captive portal found on this wifi network associated with this preference.
      */
     private void signIntoNetwork() {
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 7f0e8ee..9814486 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -17,8 +17,10 @@
 
 import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID;
 
+import android.app.Activity;
 import android.app.Dialog;
 import android.content.Context;
+import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
@@ -52,6 +54,8 @@
 
     private static final String TAG = "WifiNetworkDetailsFrg";
 
+    public static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;
+
     private AccessPoint mAccessPoint;
     private WifiDetailPreferenceController mWifiDetailPreferenceController;
 
@@ -142,4 +146,14 @@
 
         return controllers;
     }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+
+        if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS
+                && resultCode == Activity.RESULT_OK) {
+            mWifiDetailPreferenceController.launchQRCodeGenerator();
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index 72fa7fe..d81c19b 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.ActionBar;
 import android.app.Activity;
+import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 
@@ -30,32 +31,22 @@
 import com.android.settings.core.InstrumentedActivity;
 import com.android.settings.R;
 
-public class WifiDppConfiguratorActivity extends InstrumentedActivity {
+public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
+        WifiNetworkConfig.Retriever {
     private static final String TAG = "WifiDppConfiguratorActivity";
 
+    public static final String ACTION_CONFIGURATOR_QR_CODE_SCANNER =
+            "android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER";
+    public static final String ACTION_CONFIGURATOR_QR_CODE_GENERATOR =
+            "android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR";
+    public static final String ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK =
+            "android.settings.WIFI_DPP_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK";
+
     private FragmentManager mFragmentManager;
     private FragmentTransaction mFragmentTransaction;
 
-    public static final String EXTRA_LAUNCH_MODE =
-            "com.android.settings.wifi.dpp.EXTRA_LAUNCH_MODE";
-    public static final String EXTRA_SSID = "com.android.settings.wifi.dpp.EXTRA_SSID";
-
-    public enum LaunchMode {
-        LAUNCH_MODE_QR_CODE_SCANNER(1),
-        LAUNCH_MODE_QR_CODE_GENERATOR(2),
-        LAUNCH_MODE_CHOOSE_SAVED_WIFI_NETWORK(3),
-        LAUNCH_MODE_NOT_DEFINED(-1);
-
-        private int mMode;
-
-        LaunchMode(int mode) {
-            this.mMode = mode;
-        }
-
-        public int getMode() {
-            return mMode;
-        }
-    }
+    /** The Wi-Fi network which will be configured */
+    private WifiNetworkConfig mWifiNetworkConfig;
 
     @Override
     public int getMetricsCategory() {
@@ -71,37 +62,59 @@
         mFragmentManager = getSupportFragmentManager();
         mFragmentTransaction = getSupportFragmentManager().beginTransaction();
 
-        final int launchMode = getIntent().getIntExtra(EXTRA_LAUNCH_MODE,
-            LaunchMode.LAUNCH_MODE_NOT_DEFINED.getMode());
-        if (launchMode == LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode()) {
-            addQrCodeScannerFragment();
-        } else if (launchMode == LaunchMode.LAUNCH_MODE_QR_CODE_GENERATOR.getMode()) {
-            addQrCodeGeneratorFragment();
-        } else if (launchMode == LaunchMode.LAUNCH_MODE_CHOOSE_SAVED_WIFI_NETWORK.getMode()) {
-            addChooseSavedWifiNetworkFragment();
-        } else {
-            Log.e(TAG, "Launch with an invalid mode extra");
+        Intent intent = getIntent();
+        boolean cancelActivity = false;
+        WifiNetworkConfig config;
+        switch (intent.getAction()) {
+            case ACTION_CONFIGURATOR_QR_CODE_SCANNER:
+                config = WifiNetworkConfig.getValidConfigOrNull(intent);
+                if (config == null) {
+                    cancelActivity = true;
+                } else {
+                    mWifiNetworkConfig = config;
+                    addQrCodeScannerFragment(/* addToBackStack= */ false);
+                }
+                break;
+            case ACTION_CONFIGURATOR_QR_CODE_GENERATOR:
+                config = WifiNetworkConfig.getValidConfigOrNull(intent);
+                if (config == null) {
+                    cancelActivity = true;
+                } else {
+                    mWifiNetworkConfig = config;
+                    addQrCodeGeneratorFragment();
+                }
+                break;
+            case ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK:
+                addChooseSavedWifiNetworkFragment(/* addToBackStack */ false);
+                break;
+            default:
+                cancelActivity = true;
+                Log.e(TAG, "Launch with an invalid action");
+        }
+
+        if (cancelActivity) {
             setResult(Activity.RESULT_CANCELED);
             finish();
         }
     }
 
-    private void addQrCodeScannerFragment() {
-        final WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
+    private void addQrCodeScannerFragment(boolean addToBackStack) {
+        WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
         mFragmentTransaction.add(R.id.fragment_container, fragment);
-        mFragmentTransaction.addToBackStack(/* name */ null);
+        if (addToBackStack) {
+            mFragmentTransaction.addToBackStack(/* name */ null);
+        }
         mFragmentTransaction.commit();
     }
 
     private void addQrCodeGeneratorFragment() {
-        final WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
+        WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
         mFragmentTransaction.add(R.id.fragment_container, fragment);
-        mFragmentTransaction.addToBackStack(/* name */ null);
         mFragmentTransaction.commit();
     }
 
-    private void addChooseSavedWifiNetworkFragment() {
-        final ActionBar action = getActionBar();
+    private void addChooseSavedWifiNetworkFragment(boolean addToBackStack) {
+        ActionBar action = getActionBar();
         if (action != null) {
             action.hide();
         }
@@ -109,13 +122,15 @@
         WifiDppChooseSavedWifiNetworkFragment fragment =
                 new WifiDppChooseSavedWifiNetworkFragment();
         mFragmentTransaction.add(R.id.fragment_container, fragment);
-        mFragmentTransaction.addToBackStack(/* name */ null);
+        if (addToBackStack) {
+            mFragmentTransaction.addToBackStack(/* name */ null);
+        }
         mFragmentTransaction.commit();
     }
 
     @Override
     protected void onStop() {
-        final Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
+        Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
         if (fragment != null) {
             // Remove it to prevent stacking multiple fragments after screen rotated.
             mFragmentManager.beginTransaction().remove(fragment).commit();
@@ -123,4 +138,19 @@
 
         super.onStop();
     }
+
+    @Override
+    public WifiNetworkConfig getWifiNetworkConfig() {
+        return mWifiNetworkConfig;
+    }
+
+    @Override
+    public boolean setWifiNetworkConfig(WifiNetworkConfig config) {
+        if(!WifiNetworkConfig.isValidConfig(config)) {
+            return false;
+        } else {
+            mWifiNetworkConfig = new WifiNetworkConfig(config);
+            return true;
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
index 0d30a79..c86fc98 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
@@ -30,6 +30,7 @@
 import com.android.internal.logging.nano.MetricsProto;
 
 import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.wifi.qrcode.QrDecorateView;
 import com.android.settings.R;
 
 /**
@@ -46,7 +47,7 @@
     private TextView mDescription;
 
     private SurfaceView mPreviewView;       //optional, for WifiDppQrCodeScannerFragment
-    private ImageView mDecorateViiew;       //optional, for WifiDppQrCodeScannerFragment
+    private QrDecorateView mDecorateViiew;  //optional, for WifiDppQrCodeScannerFragment
     private TextView mErrorMessage;         //optional, for WifiDppQrCodeScannerFragment
 
     private ImageView mBarcodeView;         //optional, for WifiDppQrCodeGeneratorFragment
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 3e4ac61..70dade5 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -49,15 +49,12 @@
 
         setTitle(getString(R.string.wifi_dpp_add_device_to_network));
 
-        String ssid = null;
-        final Intent intent = getActivity().getIntent();
-        if (intent != null) {
-            ssid = intent.getStringExtra(WifiDppConfiguratorActivity.EXTRA_SSID);
+        WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
+                .getWifiNetworkConfig();
+        if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
+            throw new IllegalArgumentException("Invalid Wi-Fi network for configuring");
         }
-        if (TextUtils.isEmpty(ssid)) {
-            throw new IllegalArgumentException("Invalid SSID");
-        }
-        setDescription(getString(R.string.wifi_dpp_center_qr_code, ssid));
+        setDescription(getString(R.string.wifi_dpp_center_qr_code, wifiNetworkConfig.getSsid()));
 
         hideRightButton();
 
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
new file mode 100644
index 0000000..70ef3a8
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.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.wifi.dpp;
+
+import android.content.Intent;
+
+/**
+ * Here are the items shared by both WifiDppConfiguratorActivity & WifiDppEnrolleeActivity
+ */
+public class WifiDppUtils {
+    /** The data is from {@code com.android.settingslib.wifi.AccessPoint.securityToString} */
+    public static final String EXTRA_WIFI_SECURITY = "security";
+
+    /** The data corresponding to {@code WifiConfiguration} SSID */
+    public static final String EXTRA_WIFI_SSID = "ssid";
+
+    /** The data corresponding to {@code WifiConfiguration} preSharedKey */
+    public static final String EXTRA_WIFI_PRE_SHARED_KEY = "preSharedKey";
+
+    /** The data corresponding to {@code WifiConfiguration} hiddenSSID */
+    public static final String EXTRA_WIFI_HIDDEN_SSID = "hiddenSsid";
+
+    /**
+     * Acceptable QR code string may be a standard W-Fi DPP bootstrapping information or the Wi-Fi
+     * Network config format described in
+     * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+     *
+     * Wi-Fi Network config format example:
+     *
+     *     WIFI:T:WPA;S:mynetwork;P:mypass;;
+     *
+     * parameter Example    Description
+     * T         WPA        Authentication type; can be WEP or WPA, or 'nopass' for no password. Or,
+     *                      omit for no password.
+     * S         mynetwork  Network SSID. Required. Enclose in double quotes if it is an ASCII name,
+     *                      but could be interpreted as hex (i.e. "ABCD")
+     * P         mypass     Password, ignored if T is "nopass" (in which case it may be omitted).
+     *                      Enclose in double quotes if it is an ASCII name, but could be interpreted as
+     *                      hex (i.e. "ABCD")
+     * H         true       Optional. True if the network SSID is hidden.
+     */
+    public static final String EXTRA_QR_CODE = "qrCode";
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
new file mode 100644
index 0000000..439de98
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -0,0 +1,118 @@
+/*
+ * 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.wifi.dpp;
+
+import android.content.Intent;
+import android.text.TextUtils;
+
+/**
+ * Contains the Wi-Fi Network config parameters described in
+ * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+ *
+ * Checks below members of {@code WifiDppUtils} for more information.
+ * EXTRA_WIFI_SECURITY / EXTRA_WIFI_SSID / EXTRA_WIFI_PRE_SHARED_KEY / EXTRA_WIFI_HIDDEN_SSID /
+ * EXTRA_QR_CODE
+ */
+public class WifiNetworkConfig {
+    private String mSecurity;
+    private String mSsid;
+    private String mPreSharedKey;
+    private boolean mHiddenSsid;
+
+    private WifiNetworkConfig(String security, String ssid, String preSharedKey,
+            boolean hiddenSsid) {
+        mSecurity = security;
+        mSsid = ssid;
+        mPreSharedKey = preSharedKey;
+        mHiddenSsid = hiddenSsid;
+    }
+
+    public WifiNetworkConfig(WifiNetworkConfig config) {
+        mSecurity = new String(config.mSecurity);
+        mSsid = new String(config.mSsid);
+        mPreSharedKey = new String(config.mPreSharedKey);
+        mHiddenSsid = config.mHiddenSsid;
+    }
+
+    /**
+     * Wi-Fi DPP activities should implement this interface for fragments to retrieve the
+     * WifiNetworkConfig for configuration
+     */
+    public interface Retriever {
+        public WifiNetworkConfig getWifiNetworkConfig();
+        public boolean setWifiNetworkConfig(WifiNetworkConfig config);
+    }
+
+    /**
+     * Retrieve WifiNetworkConfig from below 2 intents
+     *
+     * android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR
+     * android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER
+     */
+    public static WifiNetworkConfig getValidConfigOrNull(Intent intent) {
+        String security = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SECURITY);
+        String ssid = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SSID);
+        String preSharedKey = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY);
+        boolean hiddenSsid = intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID, false);
+
+        if (!isValidConfig(security, ssid, hiddenSsid)) {
+            return null;
+        }
+
+        if (ssid == null) {
+            ssid = "";
+        }
+
+        return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid);
+    }
+
+    public static boolean isValidConfig(WifiNetworkConfig config) {
+        if (config == null) {
+            return false;
+        } else {
+            return isValidConfig(config.mSecurity, config.mSsid, config.mHiddenSsid);
+        }
+    }
+
+    public static boolean isValidConfig(String security, String ssid, boolean hiddenSsid) {
+        if (TextUtils.isEmpty(security)) {
+            return false;
+        }
+
+        if (!hiddenSsid && TextUtils.isEmpty(ssid)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    public String getSecurity() {
+        return new String(mSecurity);
+    }
+
+    public String getSsid() {
+        return new String(mSsid);
+    }
+
+    public String getPreSharedKey() {
+        return new String(mPreSharedKey);
+    }
+
+    public boolean getHiddenSsid() {
+        return mHiddenSsid;
+    }
+}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 479ffee..ab06f75 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -7,7 +7,6 @@
 com.android.settings.accessibility.ToggleSelectToSpeakPreferenceFragmentForSetupWizard
 com.android.settings.accounts.AccountDetailDashboardFragment
 com.android.settings.accounts.AccountSyncSettings
-com.android.settings.accounts.ManagedProfileSettings
 com.android.settings.applications.appinfo.AppInfoDashboardFragment
 com.android.settings.applications.appinfo.DrawOverlayDetails
 com.android.settings.applications.appinfo.ExternalSourcesDetails
@@ -27,9 +26,7 @@
 com.android.settings.bluetooth.BluetoothPairingDetail
 com.android.settings.bluetooth.DevicePickerFragment
 com.android.settings.datausage.AppDataUsage
-com.android.settings.datausage.AppDataUsageV2
 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/res/values/themes.xml b/tests/robotests/res/values/themes.xml
index 7bfbe10..41ace18 100644
--- a/tests/robotests/res/values/themes.xml
+++ b/tests/robotests/res/values/themes.xml
@@ -15,6 +15,8 @@
         <item name="colorAccent">#ffffff</item>
         <item name="preferenceTheme">@style/PreferenceTheme</item>
         <item name="android:windowLightStatusBar">true</item>
+        <!-- Define this color for material design -->
+        <item name="colorPrimaryVariant">@android:color/white</item>
     </style>
 
     <style name="ThemeOverlay.SwitchBar.Settings" parent="@android:style/ThemeOverlay.Material.ActionBar">
diff --git a/tests/robotests/res/xml-mcc999/battery_saver_schedule_settings.xml b/tests/robotests/res/xml-mcc999/battery_saver_schedule_settings.xml
new file mode 100644
index 0000000..f91e4ca
--- /dev/null
+++ b/tests/robotests/res/xml-mcc999/battery_saver_schedule_settings.xml
@@ -0,0 +1,23 @@
+<?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.
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:title="@string/battery_saver_schedule_settings_title"
+    settings:staticPreferenceLocation="append">
+</PreferenceScreen >
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index cb2aa8b..00980ad 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -18,10 +18,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Vibrator;
 import android.provider.Settings;
@@ -32,6 +32,7 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.XmlTestUtils;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
@@ -42,31 +43,43 @@
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class AccessibilitySettingsTest {
+    private static final String VIBRATION_PREFERENCE_SCREEN = "vibration_preference_screen";
+    private static final String ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE =
+            "accessibility_content_timeout_preference_fragment";
+    private static final String ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE =
+            "accessibility_control_timeout_preference_fragment";
+
+    private Context mContext;
+    private ContentResolver mContentResolver;
+    private AccessibilitySettings mSettings;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mContentResolver = mContext.getContentResolver();
+        mSettings = spy(new AccessibilitySettings());
+        doReturn(mContext).when(mSettings).getContext();
+    }
 
     @Test
     public void testNonIndexableKeys_existInXmlLayout() {
-        final Context context = RuntimeEnvironment.application;
         final List<String> niks = AccessibilitySettings.SEARCH_INDEX_DATA_PROVIDER
-            .getNonIndexableKeys(context);
+            .getNonIndexableKeys(mContext);
         final List<String> keys = new ArrayList<>();
 
-        keys.addAll(XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.accessibility_settings));
+        keys.addAll(XmlTestUtils.getKeysFromPreferenceXml(mContext, R.xml.accessibility_settings));
 
         assertThat(keys).containsAllIn(niks);
     }
 
     @Test
     public void testUpdateVibrationSummary_shouldUpdateSummary() {
-        MockitoAnnotations.initMocks(this);
-        final Context mContext = RuntimeEnvironment.application;
-        final AccessibilitySettings mSettings = spy(new AccessibilitySettings());
-
         final Preference mVibrationPreferenceScreen = new Preference(mContext);
-        doReturn(mVibrationPreferenceScreen).when(mSettings).findPreference(anyString());
+        doReturn(mVibrationPreferenceScreen).when(mSettings).findPreference(
+                VIBRATION_PREFERENCE_SCREEN);
 
-        doReturn(mContext).when(mSettings).getContext();
-
-        mVibrationPreferenceScreen.setKey("vibration_preference_screen");
+        mVibrationPreferenceScreen.setKey(VIBRATION_PREFERENCE_SCREEN);
 
         Settings.System.putInt(mContext.getContentResolver(),
                 Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
@@ -81,4 +94,58 @@
                 VibrationIntensityPreferenceController.getIntensityString(mContext,
                         Vibrator.VIBRATION_INTENSITY_OFF));
     }
+
+    @Test
+    public void testUpdateAccessibilityTimeoutSummary_shouldUpdateSummary() {
+        String[] testingValues = {null, "0", "10000", "30000", "60000", "120000"};
+        int[] exceptedResIds = {R.string.accessibility_timeout_default,
+                R.string.accessibility_timeout_default,
+                R.string.accessibility_timeout_10secs,
+                R.string.accessibility_timeout_30secs,
+                R.string.accessibility_timeout_1min,
+                R.string.accessibility_timeout_2mins
+        };
+
+        for (int i = 0; i < testingValues.length; i++) {
+            Settings.Secure.putString(mContentResolver,
+                    Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, testingValues[i]);
+
+            verifyAccessibilityTimeoutSummary(ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE,
+                    exceptedResIds[i]);
+
+            Settings.Secure.putString(mContentResolver,
+                    Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, testingValues[i]);
+
+            verifyAccessibilityTimeoutSummary(ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE,
+                    exceptedResIds[i]);
+        }
+    }
+
+    @Test
+    public void testUpdateAccessibilityControlTimeoutSummary_invalidData_shouldUpdateSummary() {
+        String[] testingValues = {"-9009", "98277466643738977979666555536362343", "Hello,a prank"};
+
+        for (String value : testingValues) {
+            Settings.Secure.putString(mContentResolver,
+                    Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, value);
+
+            verifyAccessibilityTimeoutSummary(ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE,
+                    R.string.accessibility_timeout_default);
+
+            Settings.Secure.putString(mContentResolver,
+                    Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, value);
+
+            verifyAccessibilityTimeoutSummary(ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE,
+                    R.string.accessibility_timeout_default);
+        }
+    }
+
+    private void verifyAccessibilityTimeoutSummary(String preferenceKey, int resId) {
+        final Preference preference = new Preference(mContext);
+        doReturn(preference).when(mSettings).findPreference(preferenceKey);
+        preference.setKey(preferenceKey);
+        mSettings.updateAccessibilityTimeoutSummary(mContentResolver, preference);
+
+        assertThat(preference.getSummary()).isEqualTo(mContext.getResources().getString(resId));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
new file mode 100644
index 0000000..4469282
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.accounts;
+
+import static android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+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.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowDevicePolicyManager;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CrossProfileCalendarPreferenceControllerTest {
+
+    private static final String PREF_KEY = "cross_profile_calendar";
+    private static final int MANAGED_USER_ID = 10;
+    private static final String TEST_PACKAGE_NAME = "com.test";
+    private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("test", "test");
+
+    @Mock
+    private UserHandle mManagedUser;
+
+    private RestrictedSwitchPreference mPreference;
+    private Context mContext;
+    private CrossProfileCalendarPreferenceController mController;
+    private ShadowDevicePolicyManager dpm;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mController = new CrossProfileCalendarPreferenceController(mContext, PREF_KEY);
+        mController.setManagedUser(mManagedUser);
+        mPreference = spy(new RestrictedSwitchPreference(mContext));
+        dpm = Shadows.shadowOf(application.getSystemService(DevicePolicyManager.class));
+
+        when(mManagedUser.getIdentifier()).thenReturn(MANAGED_USER_ID);
+        doReturn(mContext).when(mContext).createPackageContextAsUser(
+                any(String.class), anyInt(), any(UserHandle.class));
+    }
+
+    @Test
+    public void getAvailabilityStatus_noManagedUser_DISABLED() {
+        mController.setManagedUser(null);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isNotEqualTo(CrossProfileCalendarPreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_hasManagedUser_AVAILABLE() {
+        mController.setManagedUser(mManagedUser);
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(CrossProfileCalendarPreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void updateStateToDisabled_isNotChecked() {
+        Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier());
+
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void updateStateToEnabled_isChecked() throws Exception {
+        // Put 0 first so we know the value is not originally 1.
+        Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier());
+        mController.updateState(mPreference);
+        Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                CROSS_PROFILE_CALENDAR_ENABLED, 1, mManagedUser.getIdentifier());
+
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void updateState_noPackageAllowed_preferenceShouldBeDisabled() throws Exception {
+        dpm.setProfileOwner(TEST_COMPONENT_NAME);
+
+        mController.updateState(mPreference);
+        verify(mPreference).setDisabledByAdmin(any());
+    }
+
+    @Test
+    public void updateState_somePackagesAllowed_preferenceShouldNotBeDisabled() throws Exception {
+        dpm.setProfileOwner(TEST_COMPONENT_NAME);
+        dpm.addCrossProfileCalendarPackage(TEST_COMPONENT_NAME, TEST_PACKAGE_NAME);
+
+        mController.updateState(mPreference);
+        verify(mPreference).setDisabledByAdmin(null);
+    }
+
+    @Test
+    public void onPreferenceChangeToFalse_shouldUpdateProviderValue() {
+        mController.onPreferenceChange(mPreference, false);
+        assertThat(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                CROSS_PROFILE_CALENDAR_ENABLED, 1, mManagedUser.getIdentifier()))
+                .isEqualTo(0);
+    }
+
+    @Test
+    public void onPreferenceChangeToTrue_shouldUpdateProviderValue() {
+        // Change to false first so we know the value is not originally 1.
+        mController.onPreferenceChange(mPreference, false);
+
+        mController.onPreferenceChange(mPreference, true);
+        assertThat(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier()))
+                .isEqualTo(1);
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
index 87eb6a6..114000c 100644
--- a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.applications;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doNothing;
@@ -30,9 +32,8 @@
 import android.widget.Button;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
 import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -46,7 +47,7 @@
 
     @Mock
     private AppStorageSizesController mSizesController;
-    private ActionButtonPreference mButtonsPref;
+    private ActionButtonsPreference mButtonsPref;
     private AppStorageSettings mSettings;
     private Button mLeftButton;
     private Button mRightButton;
@@ -58,7 +59,7 @@
         mRightButton = new Button(RuntimeEnvironment.application);
         mSettings = spy(new AppStorageSettings());
         mSettings.mSizeController = mSizesController;
-        mButtonsPref = ActionButtonPreferenceTest.createMock();
+        mButtonsPref = createMock();
         mSettings.mButtonsPref = mButtonsPref;
 
         when(mButtonsPref.setButton1OnClickListener(any(View.OnClickListener.class)))
@@ -103,5 +104,22 @@
         verify(mSettings).handleClearDataClick();
         verify(mSettings).handleClearCacheClick();
     }
+
+    private ActionButtonsPreference createMock() {
+        final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+        when(pref.setButton1Text(anyInt())).thenReturn(pref);
+        when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton2Text(anyInt())).thenReturn(pref);
+        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        return pref;
+    }
 }
 
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
index 815c76b..f8dd11b 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
@@ -42,18 +43,18 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.UserManager;
+import android.view.View;
 
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -99,9 +100,8 @@
     @Mock
     private PackageInfo mPackageInfo;
 
-    private ActionButtonPreference mButtonPrefs;
-
     private Intent mUninstallIntent;
+    private ActionButtonsPreference mButtonPrefs;
     private AppButtonsPreferenceController mController;
 
     @Before
@@ -127,7 +127,7 @@
         mPackageInfo.packageName = PACKAGE_NAME;
         mPackageInfo.applicationInfo = mAppInfo;
 
-        mButtonPrefs = ActionButtonPreferenceTest.createMock();
+        mButtonPrefs = createMock();
         mController.mButtonsPref = mButtonPrefs;
         mController.mPackageInfo = mPackageInfo;
 
@@ -175,6 +175,22 @@
     }
 
     @Test
+    public void updateOpenButton_noLaunchIntent_buttonShouldBeDisable() {
+        mController.updateOpenButton();
+
+        verify(mButtonPrefs).setButton1Visible(false);
+    }
+
+    @Test
+    public void updateOpenButton_haveLaunchIntent_buttonShouldBeEnable() {
+        doReturn(new Intent()).when(mPackageManger).getLaunchIntentForPackage(anyString());
+
+        mController.updateOpenButton();
+
+        verify(mButtonPrefs).setButton1Visible(true);
+    }
+
+    @Test
     public void updateUninstallButton_isSystemApp_handleAsDisableableButton() {
         doReturn(false).when(mController).handleDisableable();
         mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
@@ -182,7 +198,7 @@
         mController.updateUninstallButton();
 
         verify(mController).handleDisableable();
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -220,7 +236,7 @@
         mController.updateUninstallButton();
 
         verify(mController).handleDisableable();
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -229,7 +245,7 @@
 
         mController.updateUninstallButton();
 
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -239,7 +255,7 @@
 
         mController.updateUninstallButton();
 
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -248,7 +264,7 @@
 
         mController.updateUninstallButton();
 
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -258,7 +274,7 @@
 
         mController.updateUninstallButton();
 
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -308,7 +324,7 @@
 
         final boolean controllable = mController.handleDisableable();
 
-        verify(mButtonPrefs).setButton1Text(R.string.uninstall_text);
+        verify(mButtonPrefs).setButton2Text(R.string.uninstall_text);
         assertThat(controllable).isFalse();
     }
 
@@ -320,7 +336,7 @@
 
         final boolean controllable = mController.handleDisableable();
 
-        verify(mButtonPrefs).setButton1Text(R.string.uninstall_text);
+        verify(mButtonPrefs).setButton2Text(R.string.uninstall_text);
         assertThat(controllable).isTrue();
     }
 
@@ -332,7 +348,7 @@
 
         final boolean controllable = mController.handleDisableable();
 
-        verify(mButtonPrefs).setButton1Text(R.string.install_text);
+        verify(mButtonPrefs).setButton2Text(R.string.install_text);
         assertThat(controllable).isTrue();
     }
 
@@ -390,4 +406,15 @@
             return SettingsEnums.PAGE_UNKNOWN;
         }
     }
+
+    private ActionButtonsPreference createMock() {
+        final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+        when(pref.setButton2Text(anyInt())).thenReturn(pref);
+        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        return pref;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
index 1adc678..fe70c7e 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 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.
@@ -16,13 +16,12 @@
 
 package com.android.settings.applications.appinfo;
 
-import static com.android.settings.core.FeatureFlags.DATA_USAGE_V2;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -33,12 +32,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.net.ConnectivityManager;
-import android.net.INetworkStatsSession;
 import android.os.Bundle;
-import android.util.FeatureFlagUtils;
-
-import androidx.loader.app.LoaderManager;
-import androidx.preference.Preference;
 
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.datausage.AppDataUsage;
@@ -49,9 +43,12 @@
 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 androidx.loader.app.LoaderManager;
+import androidx.preference.Preference;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class AppDataUsagePreferenceControllerTest {
@@ -68,7 +65,6 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application.getApplicationContext());
-        FeatureFlagUtils.setEnabled(mContext, DATA_USAGE_V2, false);
         mController = spy(new AppDataUsagePreferenceController(mContext, "test_key"));
         mController.setParentFragment(mFragment);
     }
@@ -90,8 +86,9 @@
     }
 
     @Test
-    public void onResume_noSession_shouldNotRestartDataLoader() {
+    public void onResume_notAvailable_shouldNotRestartDataLoader() {
         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+        doReturn(BasePreferenceController.CONDITIONALLY_UNAVAILABLE).when(mController).getAvailabilityStatus();
 
         mController.onResume();
 
@@ -100,26 +97,26 @@
     }
 
     @Test
-    public void onResume_hasSession_shouldRestartDataLoader() {
+    public void onResume_isAvailable_shouldRestartDataLoader() {
         final ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(connectivityManager);
         when(connectivityManager.isNetworkSupported(anyInt())).thenReturn(true);
         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-        ReflectionHelpers.setField(mController, "mStatsSession", mock(INetworkStatsSession.class));
+        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
         final AppEntry appEntry = mock(AppEntry.class);
         appEntry.info = new ApplicationInfo();
         when(mFragment.getAppEntry()).thenReturn(appEntry);
 
         mController.onResume();
 
-        verify(mLoaderManager).restartLoader(
-                eq(AppInfoDashboardFragment.LOADER_CHART_DATA), any(Bundle.class), eq(mController));
+        verify(mLoaderManager).restartLoader(eq(AppInfoDashboardFragment.LOADER_CHART_DATA),
+                nullable(Bundle.class), eq(mController));
     }
 
     @Test
     public void onPause_shouldDestroyDataLoader() {
-        ReflectionHelpers.setField(mController, "mStatsSession", mock(INetworkStatsSession.class));
+        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
 
         mController.onPause();
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
deleted file mode 100644
index 708222e..0000000
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
+++ /dev/null
@@ -1,143 +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.applications.appinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.nullable;
-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;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.net.ConnectivityManager;
-import android.os.Bundle;
-
-import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.FeatureFlags;
-import com.android.settings.datausage.AppDataUsageV2;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import android.util.FeatureFlagUtils;
-
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-
-import androidx.loader.app.LoaderManager;
-import androidx.preference.Preference;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class AppDataUsagePreferenceControllerV2Test {
-
-    @Mock
-    private LoaderManager mLoaderManager;
-    @Mock
-    private AppInfoDashboardFragment mFragment;
-
-    private Context mContext;
-    private AppDataUsagePreferenceControllerV2 mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application.getApplicationContext());
-        mController = spy(new AppDataUsagePreferenceControllerV2(mContext, "test_key"));
-        mController.setParentFragment(mFragment);
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, true);
-    }
-
-    @Test
-    public void getAvailabilityStatus_bandwidthControlEnabled_shouldReturnAvailable() {
-        doReturn(true).when(mController).isBandwidthControlEnabled();
-
-        assertThat(mController.getAvailabilityStatus())
-            .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_bandwidthControlDisabled_shouldReturnDisabled() {
-        doReturn(false).when(mController).isBandwidthControlEnabled();
-
-        assertThat(mController.getAvailabilityStatus())
-            .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void onResume_notAvailable_shouldNotRestartDataLoader() {
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, false);
-        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-
-        mController.onResume();
-
-        verify(mLoaderManager, never()).restartLoader(
-                AppInfoDashboardFragment.LOADER_CHART_DATA, Bundle.EMPTY, mController);
-    }
-
-    @Test
-    public void onResume_isAvailable_shouldRestartDataLoader() {
-        final ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
-        when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
-                .thenReturn(connectivityManager);
-        when(connectivityManager.isNetworkSupported(anyInt())).thenReturn(true);
-        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
-        final AppEntry appEntry = mock(AppEntry.class);
-        appEntry.info = new ApplicationInfo();
-        when(mFragment.getAppEntry()).thenReturn(appEntry);
-
-        mController.onResume();
-
-        verify(mLoaderManager).restartLoader(eq(AppInfoDashboardFragment.LOADER_CHART_DATA),
-                nullable(Bundle.class), eq(mController));
-    }
-
-    @Test
-    public void onPause_shouldDestroyDataLoader() {
-        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
-        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-
-        mController.onPause();
-
-        verify(mLoaderManager).destroyLoader(AppInfoDashboardFragment.LOADER_CHART_DATA);
-    }
-
-    @Test
-    public void getDetailFragmentClass_shouldReturnAppDataUsage() {
-        assertThat(mController.getDetailFragmentClass()).isEqualTo(AppDataUsageV2.class);
-    }
-
-    @Test
-    public void updateState_shouldUpdatePreferenceSummary() {
-        final Preference preference = mock(Preference.class);
-
-        mController.updateState(preference);
-
-        verify(preference).setSummary(any());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
index b3f5b5e..4c9cacb 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
@@ -28,11 +28,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -48,9 +49,11 @@
 import android.os.UserManager;
 import android.view.LayoutInflater;
 import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.SearchView;
 
 import androidx.fragment.app.FragmentActivity;
 import androidx.recyclerview.widget.RecyclerView;
@@ -159,6 +162,35 @@
     }
 
     @Test
+    public void onCreateOptionsMenu_shouldSetSearchQueryListener() {
+        final SearchView searchView = mock(SearchView.class);
+        final MenuItem searchMenu = mock(MenuItem.class);
+        final MenuItem helpMenu = mock(MenuItem.class);
+        when(searchMenu.getActionView()).thenReturn(searchView);
+        when(mMenu.findItem(R.id.search_app_list_menu)).thenReturn(searchMenu);
+        when(mMenu.add(anyInt() /* groupId */, anyInt() /* itemId */, anyInt() /* order */,
+            anyInt() /* titleRes */)).thenReturn(helpMenu);
+        doReturn("Test").when(mFragment).getText(anyInt() /* resId */);
+        doNothing().when(mFragment).updateOptionsMenu();
+
+        mFragment.onCreateOptionsMenu(mMenu, mock(MenuInflater.class));
+
+        verify(searchView).setOnQueryTextListener(mFragment);
+    }
+
+    @Test
+    public void onQueryTextChange_shouldFilterSearchInApplicationsAdapter() {
+        final ManageApplications.ApplicationsAdapter adapter =
+            mock(ManageApplications.ApplicationsAdapter.class);
+        final String query = "Test App";
+        ReflectionHelpers.setField(mFragment, "mApplications", adapter);
+
+        mFragment.onQueryTextChange(query);
+
+        verify(adapter).filterSearch(query);
+    }
+
+    @Test
     public void updateLoading_appLoaded_shouldNotDelayCallToHandleLoadingContainer() {
         ReflectionHelpers.setField(mFragment, "mLoadingContainer", mock(View.class));
         ReflectionHelpers.setField(mFragment, "mListContainer", mock(View.class));
@@ -250,6 +282,34 @@
     }
 
     @Test
+    public void onRebuildComplete_hasSearchQuery_shouldFilterSearch() {
+        final String query = "Test";
+        final RecyclerView recyclerView = mock(RecyclerView.class);
+        final View emptyView = mock(View.class);
+        ReflectionHelpers.setField(mFragment, "mRecyclerView", recyclerView);
+        ReflectionHelpers.setField(mFragment, "mEmptyView", emptyView);
+        final SearchView searchView = mock(SearchView.class);
+        ReflectionHelpers.setField(mFragment, "mSearchView", searchView);
+        when(searchView.isVisibleToUser()).thenReturn(true);
+        when(searchView.getQuery()).thenReturn(query);
+        final View listContainer = mock(View.class);
+        when(listContainer.getVisibility()).thenReturn(View.VISIBLE);
+        ReflectionHelpers.setField(mFragment, "mListContainer", listContainer);
+        ReflectionHelpers.setField(
+            mFragment, "mFilterAdapter", mock(ManageApplications.FilterSpinnerAdapter.class));
+        final ArrayList<ApplicationsState.AppEntry> appList = new ArrayList<>();
+        appList.add(mock(ApplicationsState.AppEntry.class));
+        final ManageApplications.ApplicationsAdapter adapter =
+            spy(new ManageApplications.ApplicationsAdapter(mState, mFragment,
+                AppFilterRegistry.getInstance().get(FILTER_APPS_ALL),
+                null /* savedInstanceState */));
+
+        adapter.onRebuildComplete(appList);
+
+        verify(adapter).filterSearch(query);
+    }
+
+    @Test
     public void notifyItemChange_recyclerViewIdle_shouldNotify() {
         final RecyclerView recyclerView = mock(RecyclerView.class);
         final ManageApplications.ApplicationsAdapter adapter =
@@ -344,6 +404,48 @@
     }
 
     @Test
+    public void applicationsAdapter_filterSearch_emptyQuery_shouldShowFullList() {
+        final ManageApplications.ApplicationsAdapter adapter =
+            new ManageApplications.ApplicationsAdapter(
+                mState, mFragment, mock(AppFilterItem.class), Bundle.EMPTY);
+        final String[] appNames = {"Apricot", "Banana", "Cantaloupe", "Fig", "Mango"};
+        ReflectionHelpers.setField(adapter, "mOriginalEntries", getTestAppList(appNames));
+
+        adapter.filterSearch("");
+
+        assertThat(adapter.getItemCount()).isEqualTo(5);
+    }
+
+    @Test
+    public void applicationsAdapter_filterSearch_noMatch_shouldShowEmptyList() {
+        final ManageApplications.ApplicationsAdapter adapter =
+            new ManageApplications.ApplicationsAdapter(
+                mState, mFragment, mock(AppFilterItem.class), Bundle.EMPTY);
+        final String[] appNames = {"Apricot", "Banana", "Cantaloupe", "Fig", "Mango"};
+        ReflectionHelpers.setField(adapter, "mOriginalEntries", getTestAppList(appNames));
+
+        adapter.filterSearch("orange");
+
+        assertThat(adapter.getItemCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void applicationsAdapter_filterSearch_shouldShowMatchedItemsOnly() {
+        final ManageApplications.ApplicationsAdapter adapter =
+            new ManageApplications.ApplicationsAdapter(
+                mState, mFragment, mock(AppFilterItem.class), Bundle.EMPTY);
+        final String[] appNames = {"Apricot", "Banana", "Cantaloupe", "Fig", "Mango"};
+        ReflectionHelpers.setField(adapter, "mOriginalEntries", getTestAppList(appNames));
+
+        adapter.filterSearch("an");
+
+        assertThat(adapter.getItemCount()).isEqualTo(3);
+        assertThat(adapter.getAppEntry(0).label).isEqualTo("Banana");
+        assertThat(adapter.getAppEntry(1).label).isEqualTo("Cantaloupe");
+        assertThat(adapter.getAppEntry(2).label).isEqualTo("Mango");
+    }
+
+    @Test
     public void sortOrderSavedOnRebuild() {
         when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
         ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
@@ -375,4 +477,14 @@
             return new RoboMenuItem(id);
         });
     }
+
+    private ArrayList<ApplicationsState.AppEntry> getTestAppList(String[] appNames) {
+        final ArrayList<ApplicationsState.AppEntry> appList = new ArrayList<>();
+        for (String name : appNames) {
+            final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
+            appEntry.label = name;
+            appList.add(appEntry);
+        }
+        return appList;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
index 094ec80..d8be01f 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -34,8 +36,7 @@
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowBluetoothDevice;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,7 +48,7 @@
 @Config(shadows = SettingsShadowBluetoothDevice.class)
 public class BluetoothDetailsButtonsControllerTest extends BluetoothDetailsControllerTestBase {
     private BluetoothDetailsButtonsController mController;
-    private ActionButtonPreference mButtonsPref;
+    private ActionButtonsPreference mButtonsPref;
     private Button mConnectButton;
     private Button mForgetButton;
 
@@ -60,8 +61,9 @@
         mConnectButton = buttons.findViewById(R.id.button2);
         mForgetButton = buttons.findViewById(R.id.button1);
         mController =
-            new BluetoothDetailsButtonsController(mContext, mFragment, mCachedDevice, mLifecycle);
-        mButtonsPref = ActionButtonPreferenceTest.createMock();
+                new BluetoothDetailsButtonsController(mContext, mFragment, mCachedDevice,
+                        mLifecycle);
+        mButtonsPref = createMock();
         when(mButtonsPref.getKey()).thenReturn(mController.getPreferenceKey());
         when(mButtonsPref.setButton2OnClickListener(any(View.OnClickListener.class)))
                 .thenAnswer(invocation -> {
@@ -186,4 +188,21 @@
 
         verify(mButtonsPref).setButton2Enabled(false);
     }
+
+    private ActionButtonsPreference createMock() {
+        final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+        when(pref.setButton1Text(anyInt())).thenReturn(pref);
+        when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton2Text(anyInt())).thenReturn(pref);
+        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        return pref;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
index 3b1b5af..ebf3252 100644
--- a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
@@ -18,6 +18,7 @@
 
 import static com.android.settings.core.PreferenceXmlParserUtils
         .METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_APPEND;
 import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
 import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEYWORDS;
 import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SEARCHABLE;
@@ -315,6 +316,32 @@
         }
     }
 
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void extractMetadata_requestAppendProperty_shouldDefaultToFalse()
+        throws Exception {
+        final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
+                R.xml.display_settings,
+                MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_NEED_PREF_APPEND);
+
+        for (Bundle bundle : metadata) {
+            assertThat(bundle.getBoolean(METADATA_APPEND)).isFalse();
+        }
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void extractMetadata_requestAppendProperty_shouldReturnCorrectValue()
+        throws Exception {
+        final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
+                R.xml.battery_saver_schedule_settings,
+                MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_NEED_PREF_APPEND);
+
+        for (Bundle bundle : metadata) {
+            assertThat(bundle.getBoolean(METADATA_APPEND)).isTrue();
+        }
+    }
+
     /**
      * @param resId the ID for the XML preference
      * @return an XML resource parser that points to the start tag
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 01fa32f..333c706 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -19,6 +19,7 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.doNothing;
@@ -28,12 +29,14 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.NetworkPolicyManager;
 import android.os.Bundle;
 import android.util.ArraySet;
 import android.view.View;
 
+import androidx.preference.Preference;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
 
@@ -45,6 +48,7 @@
 import com.android.settingslib.AppItem;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.net.NetworkCycleDataForUid;
 
 import org.junit.After;
 import org.junit.Before;
@@ -57,6 +61,9 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
 public class AppDataUsageTest {
@@ -172,4 +179,49 @@
         verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
         verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
     }
+
+    @Test
+    public void bindData_noAppUsageData_shouldHideCycleSpinner() {
+        mFragment = spy(new AppDataUsage());
+        final SpinnerPreference cycle = mock(SpinnerPreference.class);
+        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+        final Preference preference = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", preference);
+        ReflectionHelpers.setField(mFragment, "mForegroundUsage", preference);
+        ReflectionHelpers.setField(mFragment, "mTotalUsage", preference);
+        doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
+
+        mFragment.bindData(0 /* position */);
+
+        verify(cycle).setVisible(false);
+    }
+
+    @Test
+    public void bindData_hasAppUsageData_shouldShowCycleSpinnerAndUpdateUsageSummary() {
+        mFragment = spy(new AppDataUsage());
+        final Context context = RuntimeEnvironment.application;
+        doReturn(context).when(mFragment).getContext();
+        final long backgroundBytes = 1234L;
+        final long foregroundBytes = 5678L;
+        final List<NetworkCycleDataForUid> appUsage = new ArrayList<>();
+        appUsage.add(new NetworkCycleDataForUid.Builder()
+            .setBackgroundUsage(backgroundBytes).setForegroundUsage(foregroundBytes).build());
+        ReflectionHelpers.setField(mFragment, "mUsageData", appUsage);
+        final Preference backgroundPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref);
+        final Preference foregroundPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref);
+        final Preference totalPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref);
+        final SpinnerPreference cycle = mock(SpinnerPreference.class);
+        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+
+        mFragment.bindData(0 /* position */);
+
+        verify(cycle).setVisible(true);
+        verify(totalPref).setSummary(
+            DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
+        verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
+        verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
deleted file mode 100644
index 8796a39..0000000
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.datausage;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.doNothing;
-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.pm.PackageManager;
-import android.net.NetworkPolicyManager;
-import android.os.Bundle;
-import android.util.ArraySet;
-import android.view.View;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-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.ShadowRestrictedLockUtilsInternal;
-import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
-public class AppDataUsageV2Test {
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private EntityHeaderController mHeaderController;
-    @Mock
-    private PackageManager mPackageManager;
-
-    private AppDataUsageV2 mFragment;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest();
-    }
-
-    @After
-    public void tearDown() {
-        ShadowEntityHeaderController.reset();
-    }
-
-    @Test
-    public void bindAppHeader_allWorkApps_shouldNotShowAppInfoLink() {
-        ShadowEntityHeaderController.setUseMock(mHeaderController);
-        when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
-        when(mHeaderController.setUid(anyInt())).thenReturn(mHeaderController);
-
-        mFragment = spy(new AppDataUsageV2());
-
-        when(mFragment.getPreferenceManager())
-            .thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-        ReflectionHelpers.setField(mFragment, "mAppItem", mock(AppItem.class));
-
-        mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
-
-        verify(mHeaderController).setHasAppInfoLink(false);
-    }
-
-    @Test
-    public void bindAppHeader_workApp_shouldSetWorkAppUid() throws
-            PackageManager.NameNotFoundException {
-        final int fakeUserId = 100;
-
-        mFragment = spy(new AppDataUsageV2());
-        final ArraySet<String> packages = new ArraySet<>();
-        packages.add("pkg");
-        final AppItem appItem = new AppItem(123456789);
-
-        ReflectionHelpers.setField(mFragment, "mPackageManager", mPackageManager);
-        ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
-        ReflectionHelpers.setField(mFragment, "mPackages", packages);
-
-        when(mPackageManager.getPackageUidAsUser(anyString(), anyInt()))
-                .thenReturn(fakeUserId);
-
-        ShadowEntityHeaderController.setUseMock(mHeaderController);
-        when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
-        when(mHeaderController.setUid(fakeUserId)).thenReturn(mHeaderController);
-        when(mHeaderController.setHasAppInfoLink(anyBoolean())).thenReturn(mHeaderController);
-
-        when(mFragment.getPreferenceManager())
-            .thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-
-        mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
-
-        verify(mHeaderController).setHasAppInfoLink(true);
-        verify(mHeaderController).setUid(fakeUserId);
-    }
-
-    @Test
-    public void changePreference_backgroundData_shouldUpdateUI() {
-        mFragment = spy(new AppDataUsageV2());
-        final AppItem appItem = new AppItem(123456789);
-        final RestrictedSwitchPreference pref = mock(RestrictedSwitchPreference.class);
-        final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
-        ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
-        ReflectionHelpers.setField(mFragment, "mRestrictBackground", pref);
-        ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
-
-        doNothing().when(mFragment).updatePrefs();
-
-        mFragment.onPreferenceChange(pref, true /* value */);
-
-        verify(mFragment).updatePrefs();
-    }
-
-    @Test
-    public void updatePrefs_restrictedByAdmin_shouldDisablePreference() {
-        mFragment = spy(new AppDataUsageV2());
-        final int testUid = 123123;
-        final AppItem appItem = new AppItem(testUid);
-        final RestrictedSwitchPreference restrictBackgroundPref
-                = mock(RestrictedSwitchPreference.class);
-        final RestrictedSwitchPreference unrestrictedDataPref
-                = mock(RestrictedSwitchPreference.class);
-        final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
-        final NetworkPolicyManager networkPolicyManager = mock(NetworkPolicyManager.class);
-        ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
-        ReflectionHelpers.setField(mFragment, "mRestrictBackground", restrictBackgroundPref);
-        ReflectionHelpers.setField(mFragment, "mUnrestrictedData", unrestrictedDataPref);
-        ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
-        ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager);
-
-        ShadowRestrictedLockUtilsInternal.setRestricted(true);
-        doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager)
-                .getUidPolicy(testUid);
-
-        mFragment.updatePrefs();
-
-        verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
-        verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
-    }
-
-    @Test
-    public void bindData_noAppUsageData_shouldHideCycleSpinner() {
-        mFragment = spy(new AppDataUsageV2());
-        final SpinnerPreference cycle = mock(SpinnerPreference.class);
-        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
-        final Preference preference = mock(Preference.class);
-        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", preference);
-        ReflectionHelpers.setField(mFragment, "mForegroundUsage", preference);
-        ReflectionHelpers.setField(mFragment, "mTotalUsage", preference);
-        doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
-
-        mFragment.bindData(0 /* position */);
-
-        verify(cycle).setVisible(false);
-    }
-
-    @Test
-    public void bindData_hasAppUsageData_shouldShowCycleSpinnerAndUpdateUsageSummary() {
-        mFragment = spy(new AppDataUsageV2());
-        final Context context = RuntimeEnvironment.application;
-        doReturn(context).when(mFragment).getContext();
-        final long backgroundBytes = 1234L;
-        final long foregroundBytes = 5678L;
-        final List<NetworkCycleDataForUid> appUsage = new ArrayList<>();
-        appUsage.add(new NetworkCycleDataForUid.Builder()
-            .setBackgroundUsage(backgroundBytes).setForegroundUsage(foregroundBytes).build());
-        ReflectionHelpers.setField(mFragment, "mUsageData", appUsage);
-        final Preference backgroundPref = mock(Preference.class);
-        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref);
-        final Preference foregroundPref = mock(Preference.class);
-        ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref);
-        final Preference totalPref = mock(Preference.class);
-        ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref);
-        final SpinnerPreference cycle = mock(SpinnerPreference.class);
-        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
-
-        mFragment.bindData(0 /* position */);
-
-        verify(cycle).setVisible(true);
-        verify(totalPref).setSummary(
-            DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
-        verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
-        verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
index ce58ae2..0f9aed1 100644
--- a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
@@ -18,17 +18,15 @@
 import static com.google.common.truth.Truth.assertThat;
 
 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.net.NetworkStatsHistory;
-import android.net.NetworkStatsHistory.Entry;
 import android.util.SparseIntArray;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.widget.UsageView;
+import com.android.settingslib.net.NetworkCycleChartData;
+import com.android.settingslib.net.NetworkCycleData;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -37,14 +35,20 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ChartDataUsagePreferenceTest {
 
-    private static final long MILLIS_IN_ONE_HOUR = 60 * 60 * 1000;
-    private static final long MILLIS_IN_ONE_DAY = 24 * MILLIS_IN_ONE_HOUR;
-    private static final long TIMESTAMP_NOW = Integer.MAX_VALUE;
+    // Test cycle start date, 20 Mar 2018 22:00: GMT
+    private static final long TIMESTAMP_START = 1521583200000L;
+    // Test bucket end date, 22 Mar 2018 00:00:00
+    private static final long TIMESTAMP_END = 1521676800000L;
 
-    private NetworkStatsHistory mNetworkStatsHistory;
+    private List<NetworkCycleData> mNetworkCycleData;
+    private NetworkCycleChartData mNetworkCycleChartData;
     private Context mContext;
     private ChartDataUsagePreference mPreference;
 
@@ -54,79 +58,119 @@
 
         mContext = RuntimeEnvironment.application;
         mPreference = new ChartDataUsagePreference(mContext, null);
-        mNetworkStatsHistory = spy(new NetworkStatsHistory(MILLIS_IN_ONE_HOUR, 10));
-        addTestNetworkEntries();
-        mPreference.setNetworkStats(mNetworkStatsHistory);
     }
 
     @Test
-    public void calcPoints_notStartOfData_shouldAddDataPointsOnly() {
-        final long start = TIMESTAMP_NOW - 20 * MILLIS_IN_ONE_DAY;
-        final long end = TIMESTAMP_NOW - 5 * MILLIS_IN_ONE_DAY;
-        mPreference.setVisibleRange(start, end);
-        when(mNetworkStatsHistory.getIndexAfter(start)).thenReturn(2);
-        when(mNetworkStatsHistory.getIndexAfter(end)).thenReturn(7);
+    public void calcPoints_dataAvailableFromCycleStart_shouldAddDataPointsOnly() {
         final UsageView usageView = mock(UsageView.class);
         final ArgumentCaptor<SparseIntArray> pointsCaptor =
                 ArgumentCaptor.forClass(SparseIntArray.class);
+        createTestNetworkData();
+        mPreference.setNetworkCycleData(mNetworkCycleChartData);
 
-        mPreference.calcPoints(usageView);
+        mPreference.calcPoints(usageView, mNetworkCycleData.subList(0, 5));
 
         verify(usageView).addPath(pointsCaptor.capture());
-        SparseIntArray points = pointsCaptor.getValue();
+        final SparseIntArray points = pointsCaptor.getValue();
         // the point should be normal usage data
         assertThat(points.valueAt(1)).isNotEqualTo(-1);
     }
 
     @Test
-    public void calcPoints_startOfData_shouldIndicateStartOfData() {
-        final long start = TIMESTAMP_NOW - 20 * MILLIS_IN_ONE_DAY;
-        final long end = TIMESTAMP_NOW - 5 * MILLIS_IN_ONE_DAY;
-        mPreference.setVisibleRange(start, end);
-        when(mNetworkStatsHistory.getIndexAfter(start)).thenReturn(0);
-        when(mNetworkStatsHistory.getIndexAfter(end)).thenReturn(5);
+    public void calcPoints_dataNotAvailableAtCycleStart_shouldIndicateStartOfData() {
         final UsageView usageView = mock(UsageView.class);
         final ArgumentCaptor<SparseIntArray> pointsCaptor =
                 ArgumentCaptor.forClass(SparseIntArray.class);
+        createTestNetworkData();
+        mPreference.setNetworkCycleData(mNetworkCycleChartData);
 
-        mPreference.calcPoints(usageView);
+        mPreference.calcPoints(usageView, mNetworkCycleData.subList(2, 7));
 
         verify(usageView).addPath(pointsCaptor.capture());
-        SparseIntArray points = pointsCaptor.getValue();
+        final SparseIntArray points = pointsCaptor.getValue();
         // indicator that no data is available
         assertThat(points.keyAt(1)).isEqualTo(points.keyAt(2) - 1);
         assertThat(points.valueAt(1)).isEqualTo(-1);
     }
 
-    private void addTestNetworkEntries() {
-        // create 10 arbitary network data
-        mNetworkStatsHistory.setValues(0, createEntry(1521583200000L, 743823454L, 16574289L));
-        mNetworkStatsHistory.setValues(1, createEntry(1521586800000L, 64396L, 160364L));
-        mNetworkStatsHistory.setValues(2, createEntry(1521590400000L, 2832L, 5299L));
-        mNetworkStatsHistory.setValues(3, createEntry(1521655200000L, 83849690L, 3558238L));
-        mNetworkStatsHistory.setValues(4, createEntry(1521658800000L, 1883657L, 353330L));
-        mNetworkStatsHistory.setValues(5, createEntry(1521662400000L, 705259L, 279065L));
-        mNetworkStatsHistory.setValues(6, createEntry(1521666000000L, 216169L, 155302L));
-        mNetworkStatsHistory.setValues(7, createEntry(1521669600000L, 6069175L, 427581L));
-        mNetworkStatsHistory.setValues(8, createEntry(1521673200000L, 120389L, 110807L));
-        mNetworkStatsHistory.setValues(9, createEntry(1521676800000L, 29947L, 73257L));
+    @Test
+    public void calcPoints_shouldNotDrawPointForFutureDate() {
+        final UsageView usageView = mock(UsageView.class);
+        final ArgumentCaptor<SparseIntArray> pointsCaptor =
+            ArgumentCaptor.forClass(SparseIntArray.class);
+        final long tonight = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(12);
+        mNetworkCycleData = new ArrayList<>();
+        // add test usage data for last 5 days
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight - TimeUnit.DAYS.toMillis(5), tonight - TimeUnit.DAYS.toMillis(4), 743823454L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight - TimeUnit.DAYS.toMillis(4), tonight - TimeUnit.DAYS.toMillis(3), 64396L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight - TimeUnit.DAYS.toMillis(3), tonight - TimeUnit.DAYS.toMillis(2), 2832L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight - TimeUnit.DAYS.toMillis(2), tonight - TimeUnit.DAYS.toMillis(1), 83849690L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight - TimeUnit.DAYS.toMillis(1), tonight, 1883657L));
+        // add dummy usage data for next 5 days
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight, tonight + TimeUnit.DAYS.toMillis(1), 0L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight + TimeUnit.DAYS.toMillis(1), tonight + TimeUnit.DAYS.toMillis(2), 0L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight + TimeUnit.DAYS.toMillis(2), tonight + TimeUnit.DAYS.toMillis(3), 0L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight + TimeUnit.DAYS.toMillis(3), tonight + TimeUnit.DAYS.toMillis(4), 0L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight + TimeUnit.DAYS.toMillis(4), tonight + TimeUnit.DAYS.toMillis(5), 0L));
+        mNetworkCycleData.add(createNetworkCycleData(
+            tonight + TimeUnit.DAYS.toMillis(5), tonight + TimeUnit.DAYS.toMillis(6), 0L));
+
+        final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
+        builder.setUsageBuckets(mNetworkCycleData)
+            .setStartTime(tonight - TimeUnit.DAYS.toMillis(5))
+            .setEndTime(tonight + TimeUnit.DAYS.toMillis(6));
+        mNetworkCycleChartData = builder.build();
+        mPreference.setNetworkCycleData(mNetworkCycleChartData);
+
+        mPreference.calcPoints(usageView, mNetworkCycleData);
+
+        verify(usageView).addPath(pointsCaptor.capture());
+        final SparseIntArray points = pointsCaptor.getValue();
+        // should only have 7 points: 1 dummy point indicating the start of data, starting point 0,
+        // and 5 actual data point for each day
+        assertThat(points.size()).isEqualTo(7);
+        assertThat(points.keyAt(0)).isEqualTo(-1);
+        assertThat(points.keyAt(1)).isEqualTo(0);
+        assertThat(points.keyAt(2)).isEqualTo(TimeUnit.DAYS.toMinutes(1));
+        assertThat(points.keyAt(3)).isEqualTo(TimeUnit.DAYS.toMinutes(2));
+        assertThat(points.keyAt(4)).isEqualTo(TimeUnit.DAYS.toMinutes(3));
+        assertThat(points.keyAt(5)).isEqualTo(TimeUnit.DAYS.toMinutes(4));
+        assertThat(points.keyAt(6)).isEqualTo(TimeUnit.DAYS.toMinutes(5));
     }
 
-    /**
-     * Create a network entry to be used to calculate the usage chart. In the calculation, we only
-     * need bucketStart, total bytes (rx + tx), and bucketDuration (which is set when we create
-     * the NetworkStatsHistory object). Other fields are ignored, so we don't initialize here.
-     *
-     * @param start the timestamp when this entry begins
-     * @param rx    the total number of received bytes
-     * @param tx    the total number of transmitted bytes
-     * @return the network entry with the corresponding start time and data usage
-     */
-    private Entry createEntry(long start, long rx, long tx) {
-        Entry entry = new Entry();
-        entry.bucketStart = start;
-        entry.rxBytes = rx;
-        entry.txBytes = tx;
-        return entry;
+    private void createTestNetworkData() {
+        mNetworkCycleData = new ArrayList<>();
+        // create 10 arbitrary network data
+        mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 743823454L));
+        mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 64396L));
+        mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 2832L));
+        mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 83849690L));
+        mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 1883657L));
+        mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 705259L));
+        mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 216169L));
+        mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 6069175L));
+        mNetworkCycleData.add(createNetworkCycleData(1521673200000L, 1521676800000L, 120389L));
+        mNetworkCycleData.add(createNetworkCycleData(1521676800000L, 1521678800000L, 29947L));
+
+        final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
+        builder.setUsageBuckets(mNetworkCycleData)
+            .setStartTime(TIMESTAMP_START)
+            .setEndTime(TIMESTAMP_END);
+        mNetworkCycleChartData = builder.build();
+    }
+
+    private NetworkCycleData createNetworkCycleData(long start, long end, long usage) {
+        return new NetworkCycleData.Builder()
+            .setStartTime(start).setEndTime(end).setTotalUsage(usage).build();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
index acd00fd..7a10d70 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 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.
@@ -26,13 +26,11 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.net.ConnectivityManager;
 import android.net.NetworkTemplate;
 import android.os.Bundle;
 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;
@@ -45,6 +43,9 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.util.ReflectionHelpers;
 
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.PreferenceManager;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 public class DataUsageListTest {
 
@@ -98,6 +99,18 @@
     }
 
     @Test
+    public void processArgument_shouldGetNetworkTypeFromArgument() {
+        final Bundle args = new Bundle();
+        args.putInt(DataUsageList.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_WIFI);
+        args.putInt(DataUsageList.EXTRA_SUB_ID, 3);
+        mDataUsageList.setArguments(args);
+
+        mDataUsageList.processArgument();
+
+        assertThat(mDataUsageList.mNetworkType).isEqualTo(ConnectivityManager.TYPE_WIFI);
+    }
+
+    @Test
     public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
         final FragmentActivity activity = mock(FragmentActivity.class);
         final Intent intent = new Intent();
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java
deleted file mode 100644
index f561a05..0000000
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java
+++ /dev/null
@@ -1,127 +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.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.ConnectivityManager;
-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_shouldGetNetworkTypeFromArgument() {
-        final Bundle args = new Bundle();
-        args.putInt(DataUsageListV2.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_WIFI);
-        args.putInt(DataUsageListV2.EXTRA_SUB_ID, 3);
-        mDataUsageList.setArguments(args);
-
-        mDataUsageList.processArgument();
-
-        assertThat(mDataUsageList.mNetworkType).isEqualTo(ConnectivityManager.TYPE_WIFI);
-    }
-
-    @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/DataUsageUtilsTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
index 9a67df8..4bd584e 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
@@ -29,9 +29,7 @@
 import android.net.ConnectivityManager;
 import android.telephony.TelephonyManager;
 import android.util.DataUnit;
-import android.util.FeatureFlagUtils;
 
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -102,7 +100,6 @@
 
     @Test
     public void hasEthernet_shouldQueryEthernetSummaryForUser() throws Exception {
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, true);
         when(mManager.isNetworkSupported(anyInt())).thenReturn(true);
         final String subscriber = "TestSub";
         when(mTelephonyManager.getSubscriberId()).thenReturn(subscriber);
diff --git a/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java
deleted file mode 100644
index 03837c2..0000000
--- a/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java
+++ /dev/null
@@ -1,138 +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.development;
-
-import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_CODE_ANGLE_ENABLED_APP;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.provider.Settings;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-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;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class AngleEnabledAppPreferenceControllerTest {
-
-    @Mock
-    private Preference mPreference;
-    @Mock
-    private PreferenceScreen mPreferenceScreen;
-    @Mock
-    private DevelopmentSettingsDashboardFragment mFragment;
-    @Mock
-    private PackageManager mPackageManager;
-
-    private Context mContext;
-    private AngleEnabledAppPreferenceController mController;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mController = spy(new AngleEnabledAppPreferenceController(mContext, mFragment));
-        ReflectionHelpers
-            .setField(mController, "mPackageManager" /* field name */, mPackageManager);
-        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
-            .thenReturn(mPreference);
-        mController.displayPreference(mPreferenceScreen);
-    }
-
-    @Test
-    public void handlePreferenceTreeClick_preferenceClicked_launchActivity() {
-        final Intent activityStartIntent = new Intent(mContext, AppPicker.class);
-        final String preferenceKey = mController.getPreferenceKey();
-        doReturn(activityStartIntent).when(mController).getActivityStartIntent();
-        when(mPreference.getKey()).thenReturn(preferenceKey);
-        mController.handlePreferenceTreeClick(mPreference);
-
-        verify(mFragment).startActivityForResult(activityStartIntent,
-                REQUEST_CODE_ANGLE_ENABLED_APP);
-    }
-
-    @Test
-    public void updateState_foobarAppSelected_shouldUpdateSummaryWithAngleEnabledAppLabel() {
-        final String angleEnabledApp = "foobar";
-        final ContentResolver contentResolver = mContext.getContentResolver();
-        Settings.Global.putString(contentResolver, Settings.Global.ANGLE_ENABLED_APP,
-                angleEnabledApp);
-        mController.updateState(mPreference);
-
-        verify(mPreference).setSummary(
-                mContext.getString(R.string.angle_enabled_app_set, angleEnabledApp));
-    }
-
-    @Test
-    public void updateState_noAppSelected_shouldUpdateSummaryWithNoAppSelected() {
-        final String angleEnabledApp = null;
-        final ContentResolver contentResolver = mContext.getContentResolver();
-        Settings.Global.putString(contentResolver, Settings.Global.ANGLE_ENABLED_APP,
-                angleEnabledApp);
-        mController.updateState(mPreference);
-
-        verify(mPreference).setSummary(
-            mContext.getString(R.string.angle_enabled_app_not_set));
-    }
-
-    @Test
-    public void onActivityResult_foobarAppSelected_shouldUpdateSummaryWithAngleEnabledLabel() {
-        Intent activityResultIntent = new Intent(mContext, AppPicker.class);
-        final String appLabel = "foobar";
-        activityResultIntent.setAction(appLabel);
-        final boolean result = mController
-            .onActivityResult(REQUEST_CODE_ANGLE_ENABLED_APP, Activity.RESULT_OK,
-                    activityResultIntent);
-
-        assertThat(result).isTrue();
-        verify(mPreference).setSummary(
-                mContext.getString(R.string.angle_enabled_app_set, appLabel));
-    }
-
-    @Test
-    public void onActivityResult_badRequestCode_shouldReturnFalse() {
-        assertThat(mController.onActivityResult(
-                -1 /* requestCode */, -1 /* resultCode */, null /* intent */)).isFalse();
-    }
-
-    @Test
-    public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
-        mController.onDeveloperOptionsSwitchDisabled();
-
-        assertThat(mPreference.isEnabled()).isFalse();
-        verify(mPreference).setSummary(
-                mContext.getString(R.string.angle_enabled_app_not_set));
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
index d2c9b65..5eb21bd 100644
--- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
@@ -28,10 +28,15 @@
 import android.provider.SearchIndexableResource;
 import android.provider.Settings;
 
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 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.ShadowAlertDialogCompat;
 import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settings.widget.SwitchBar;
 import com.android.settings.widget.ToggleSwitch;
@@ -47,12 +52,14 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.androidx.fragment.FragmentController;
 import org.robolectric.util.ReflectionHelpers;
 
 import java.util.List;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = ShadowUserManager.class)
+@Config(shadows = {ShadowUserManager.class, ShadowAlertDialogCompat.class,
+        SettingsShadowResourcesImpl.class})
 public class DevelopmentSettingsDashboardFragmentTest {
 
     private ToggleSwitch mSwitch;
@@ -179,6 +186,29 @@
     }
 
     @Test
+    @Config(shadows = ShadowDisableDevSettingsDialogFragment.class)
+    public void onSwitchChanged_turnOff_andOffloadIsNotDefaultValue_shouldShowWarningDialog() {
+        final BluetoothA2dpHwOffloadPreferenceController controller =
+                mock(BluetoothA2dpHwOffloadPreferenceController.class);
+        when(mDashboard.getContext()).thenReturn(mContext);
+        when(mDashboard.getDevelopmentOptionsController(
+                BluetoothA2dpHwOffloadPreferenceController.class)).thenReturn(controller);
+        when(controller.isDefaultValue()).thenReturn(false);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+
+        mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
+
+        AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(dialog).isNotNull();
+        ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+        assertThat(shadowDialog.getTitle()).isEqualTo(
+                mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title));
+        assertThat(shadowDialog.getMessage()).isEqualTo(
+                mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message));
+    }
+
+    @Test
     public void onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed() {
         final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class);
         doReturn(controller).when(mDashboard)
@@ -264,6 +294,18 @@
         }
     }
 
+    @Implements(DisableDevSettingsDialogFragment.class)
+    public static class ShadowDisableDevSettingsDialogFragment {
+
+        @Implementation
+        public static void show(DevelopmentSettingsDashboardFragment host) {
+            DisableDevSettingsDialogFragment mFragment =
+                    spy(DisableDevSettingsDialogFragment.newInstance());
+            FragmentController.setupFragment(mFragment, FragmentActivity.class,
+                    0 /* containerViewId */, null /* bundle */);
+        }
+    }
+
     @Implements(PictureColorModePreferenceController.class)
     public static class ShadowPictureColorModePreferenceController {
         @Implementation
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
index 983621c..a966417 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
@@ -64,6 +64,7 @@
         MockitoAnnotations.initMocks(this);
 
         when(mVolumeInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
+        when(mVolumeInfo.isMountedWritable()).thenReturn(true);
         when(mPrimaryInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
         when(mMenu.findItem(anyInt())).thenReturn(mMigrateMenuItem);
         when(mMigrateMenuItem.getItemId()).thenReturn(100);
@@ -82,6 +83,7 @@
     @Test
     public void testMigrateDataIsNotVisibleNormally() {
         when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mPrimaryInfo);
+        when(mPrimaryInfo.isMountedWritable()).thenReturn(true);
 
         mController.onCreateOptionsMenu(mMenu, mMenuInflater);
         mController.onPrepareOptionsMenu(mMenu);
@@ -100,6 +102,17 @@
     }
 
     @Test
+    public void testMigrateDataIsNotVisibleWhenExternalVolumeIsNotMounted() {
+        when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mVolumeInfo);
+        when(mVolumeInfo.isMountedWritable()).thenReturn(false);
+
+        mController.onCreateOptionsMenu(mMenu, mMenuInflater);
+        mController.onPrepareOptionsMenu(mMenu);
+
+        verify(mMigrateMenuItem).setVisible(false);
+    }
+
+    @Test
     public void testMigrateDataGoesToMigrateWizard() {
         when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mVolumeInfo);
 
diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
index 859912a..57f0ebb 100644
--- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
@@ -209,6 +209,7 @@
 
     @Test
     public void onCreatePreferences_useNewTitle_shouldAddColorModePreferences() {
+        when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
         doNothing().when(mFragment).addPreferencesFromResource(anyInt());
         doNothing().when(mFragment).updateCandidates();
 
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
index f1d03c7..f7a61c8 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
@@ -28,6 +28,7 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.widget.PreferenceCategoryController;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.drawer.CategoryKey;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -59,7 +60,7 @@
         assertThat(mSettings.getMetricsCategory())
                 .isEqualTo(MetricsEvent.ENTERPRISE_PRIVACY_SETTINGS);
         assertThat(mSettings.getLogTag()).isEqualTo("EnterprisePrivacySettings");
-        assertThat(mSettings.getCategoryKey()).isNull();
+        assertThat(mSettings.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_ENTERPRISE_PRIVACY);
         assertThat(mSettings.getPreferenceScreenResId())
                 .isEqualTo(R.xml.enterprise_privacy_settings);
     }
diff --git a/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java b/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceTest.java
similarity index 94%
rename from tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java
rename to tests/robotests/src/com/android/settings/flashlight/FlashlightSliceTest.java
index 56a84bb..4af5754 100644
--- a/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java
+++ b/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceTest.java
@@ -42,7 +42,7 @@
 
 
 @RunWith(SettingsRobolectricTestRunner.class)
-public class FlashlightSliceBuilderTest {
+public class FlashlightSliceTest {
 
     private Context mContext;
 
@@ -58,7 +58,7 @@
     public void getFlashlightSlice_correctData() {
         Settings.Secure.putInt(
                 mContext.getContentResolver(), Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
-        final Slice slice = FlashlightSliceBuilder.getSlice(mContext);
+        final Slice slice = new FlashlightSlice(mContext).getSlice();
         final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
 
         final List<SliceAction> toggles = metadata.getToggles();
diff --git a/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
index d8f800d..e892eb2 100644
--- a/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.gestures;
 
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Matchers.any;
@@ -81,7 +83,7 @@
         });
         ReflectionHelpers.setField(mController, "mGestureControllers", mControllers);
 
-        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
index 08631f7..b3f9411 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
@@ -16,13 +16,20 @@
 
 package com.android.settings.homepage.contextualcards;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.content.Intent;
+import android.net.Uri;
+import android.os.UserHandle;
 
+import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -31,6 +38,9 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ContextualCardFeatureProviderImplTest {
 
@@ -48,7 +58,7 @@
         final Intent intent = new Intent();
         mImpl.sendBroadcast(mContext, intent);
 
-        verify(mContext, never()).sendBroadcast(intent);
+        verify(mContext, never()).sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     @Test
@@ -57,6 +67,37 @@
         final Intent intent = new Intent();
         mImpl.sendBroadcast(mContext, intent);
 
-        verify(mContext).sendBroadcast(intent);
+        verify(mContext).sendBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void logContextualCardDisplay_hasAction_sendBroadcast() {
+        mImpl.logContextualCardDisplay(mContext, new ArrayList<>(), new ArrayList<>());
+
+        verify(mContext).sendBroadcastAsUser(any(Intent.class), any());
+    }
+
+    @Test
+    public void serialize_hasSizeTwo_returnSizeTwo() {
+        final List<ContextualCard> cards = new ArrayList<>();
+        cards.add(new ContextualCard.Builder()
+                .setName("name1")
+                .setSliceUri(Uri.parse("uri1"))
+                .build());
+        cards.add(new ContextualCard.Builder()
+                .setName("name2")
+                .setSliceUri(Uri.parse("uri2"))
+                .build());
+
+
+        final byte[] data = mImpl.serialize(cards);
+
+        try {
+            assertThat(ContextualCardList
+                    .parseFrom(data).getCardCount()).isEqualTo(cards.size());
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
     }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index 4f50197..98943a0 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -162,7 +162,7 @@
         cards.add(new ContextualCard.Builder()
                 .setName("test_connected")
                 .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI)
+                .setSliceUri(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI)
                 .build());
         cards.add(new ContextualCard.Builder()
                 .setName("test_gesture")
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
index bb61c7d..25689e6 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
@@ -58,7 +58,7 @@
         final ActivityController<Activity> activityController = Robolectric.buildActivity(
                 Activity.class);
         mActivity = activityController.get();
-        mActivity.setTheme(R.style.Theme_AppCompat);
+        mActivity.setTheme(R.style.Theme_Settings_Home);
         activityController.create();
         mRenderer = new ConditionContextualCardRenderer(mActivity, mControllerRendererPool);
     }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
index d0b5a24..ee8a582 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
@@ -60,7 +60,7 @@
         final ActivityController<Activity> activityController = Robolectric.buildActivity(
                 Activity.class);
         mActivity = activityController.get();
-        mActivity.setTheme(R.style.Theme_AppCompat);
+        mActivity.setTheme(R.style.Theme_Settings_Home);
         activityController.create();
         mRenderer = new ConditionHeaderContextualCardRenderer(mActivity, mControllerRendererPool);
     }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
index 2618e1b..c337df1 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
@@ -59,7 +59,7 @@
         final ActivityController<Activity> activityController = Robolectric.buildActivity(
                 Activity.class);
         mActivity = activityController.get();
-        mActivity.setTheme(R.style.Theme_AppCompat);
+        mActivity.setTheme(R.style.Theme_Settings_Home);
         activityController.create();
 
         mRenderer = new LegacySuggestionContextualCardRenderer(mActivity, mControllerRendererPool);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
new file mode 100644
index 0000000..ac6557e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.contextualcards.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.SliceTester;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+import org.junit.After;
+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 java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class BluetoothDevicesSliceTest {
+
+    private static final String BLUETOOTH_MOCK_SUMMARY = "BluetoothSummary";
+    private static final String BLUETOOTH_MOCK_TITLE = "BluetoothTitle";
+
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+
+    private List<CachedBluetoothDevice> mBluetoothDeviceList;
+    private BluetoothDevicesSlice mBluetoothDevicesSlice;
+    private Context mContext;
+    private IconCompat mIcon;
+    private PendingIntent mDetailIntent;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+
+        mBluetoothDevicesSlice = spy(new BluetoothDevicesSlice(mContext));
+
+        // Mock the icon and detail intent of Bluetooth.
+        mIcon = IconCompat.createWithResource(mContext, R.drawable.ic_settings_bluetooth);
+        mDetailIntent = PendingIntent.getActivity(mContext, 0, new Intent("test action"), 0);
+        doReturn(mIcon).when(mBluetoothDevicesSlice).getBluetoothDeviceIcon(any());
+        doReturn(mDetailIntent).when(mBluetoothDevicesSlice).getBluetoothDetailIntent(any());
+
+        // Initial Bluetooth device list.
+        mBluetoothDeviceList = new ArrayList<>();
+    }
+
+    @After
+    public void tearDown() {
+        if (!mBluetoothDeviceList.isEmpty()) {
+            mBluetoothDeviceList.clear();
+        }
+    }
+
+    @Test
+    public void getSlice_hasBluetoothDevices_shouldHaveBluetoothDevicesTitle() {
+        mockBluetoothDeviceList();
+        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+        final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+        final List<SliceItem> sliceItems = slice.getItems();
+        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.bluetooth_devices));
+    }
+
+    @Test
+    public void getSlice_hasBluetoothDevices_shouldMatchBluetoothMockTitle() {
+        mockBluetoothDeviceList();
+        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+        final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+        final List<SliceItem> sliceItems = slice.getItems();
+        SliceTester.assertTitle(sliceItems, BLUETOOTH_MOCK_TITLE);
+    }
+
+    @Test
+    public void getSlice_hasBluetoothDevices_shouldHavePairNewDevice() {
+        mockBluetoothDeviceList();
+        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+        final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+        final List<SliceItem> sliceItems = slice.getItems();
+        SliceTester.assertTitle(sliceItems,
+                mContext.getString(R.string.bluetooth_pairing_pref_title));
+    }
+
+    @Test
+    public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() {
+        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+        final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+        final List<SliceItem> sliceItems = slice.getItems();
+        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_bluetooth_devices));
+    }
+
+    @Test
+    public void getSlice_noBluetoothDevices_shouldNotHavePairNewDevice() {
+        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+        final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+        final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+        assertThat(hasTitle(metadata,
+                mContext.getString(R.string.bluetooth_pairing_pref_title))).isFalse();
+    }
+
+    private void mockBluetoothDeviceList() {
+        doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName();
+        doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
+        mBluetoothDeviceList.add(mCachedBluetoothDevice);
+    }
+
+    private boolean hasTitle(SliceMetadata metadata, String title) {
+        final CharSequence sliceTitle = metadata.getTitle();
+        return TextUtils.equals(sliceTitle, title);
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
deleted file mode 100644
index 23da127..0000000
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
+++ /dev/null
@@ -1,99 +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.contextualcards.slices;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-
-import androidx.core.graphics.drawable.IconCompat;
-import androidx.slice.Slice;
-import androidx.slice.SliceItem;
-import androidx.slice.SliceProvider;
-import androidx.slice.widget.SliceLiveData;
-
-import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.SliceTester;
-import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-
-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 java.util.ArrayList;
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class ConnectedDeviceSliceTest {
-
-    @Mock
-    private CachedBluetoothDevice mCachedBluetoothDevice;
-
-    private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
-    private Context mContext;
-    private ConnectedDeviceSlice mConnectedDeviceSlice;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-
-        // Set-up specs for SliceMetadata.
-        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
-
-        mConnectedDeviceSlice = spy(new ConnectedDeviceSlice(mContext));
-    }
-
-    @Test
-    public void getSlice_hasConnectedDevices_shouldBeCorrectSliceContent() {
-        final String title = "BluetoothTitle";
-        final String summary = "BluetoothSummary";
-        final IconCompat icon = IconCompat.createWithResource(mContext,
-                R.drawable.ic_homepage_connected_device);
-        final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
-                new Intent("test action"), 0);
-        doReturn(title).when(mCachedBluetoothDevice).getName();
-        doReturn(summary).when(mCachedBluetoothDevice).getConnectionSummary();
-        mCachedDevices.add(mCachedBluetoothDevice);
-        doReturn(mCachedDevices).when(mConnectedDeviceSlice).getBluetoothConnectedDevices();
-        doReturn(icon).when(mConnectedDeviceSlice).getConnectedDeviceIcon(any());
-        doReturn(pendingIntent).when(mConnectedDeviceSlice).getBluetoothDetailIntent(any());
-        final Slice slice = mConnectedDeviceSlice.getSlice();
-
-        final List<SliceItem> sliceItems = slice.getItems();
-        SliceTester.assertTitle(sliceItems, title);
-    }
-
-    @Test
-    public void getSlice_hasNoConnectedDevices_shouldReturnCorrectHeader() {
-        final List<CachedBluetoothDevice> connectedBluetoothList = new ArrayList<>();
-        doReturn(connectedBluetoothList).when(mConnectedDeviceSlice).getBluetoothConnectedDevices();
-        final Slice slice = mConnectedDeviceSlice.getSlice();
-
-        final List<SliceItem> sliceItems = slice.getItems();
-        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_connected_devices));
-    }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
index 0be55d9..9787aee 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
+import static android.app.slice.Slice.HINT_ERROR;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
@@ -66,7 +68,7 @@
 
     @Test
     @Config(shadows = ShadowPrivateStorageInfo.class)
-    public void getSlice_hasLowStorage_shouldBeCorrectSliceContent() {
+    public void getSlice_lowStorage_shouldHaveStorageFreeTitle() {
         ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
 
         final Slice slice = mLowStorageSlice.getSlice();
@@ -77,12 +79,33 @@
 
     @Test
     @Config(shadows = ShadowPrivateStorageInfo.class)
-    public void getSlice_hasNoLowStorage_shouldBeNull() {
+    public void getSlice_lowStorage_shouldNotHaveErrorHint() {
+        ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
+
+        final Slice slice = mLowStorageSlice.getSlice();
+
+        assertThat(slice.hasHint(HINT_ERROR)).isFalse();
+    }
+
+    @Test
+    @Config(shadows = ShadowPrivateStorageInfo.class)
+    public void getSlice_storageFree_shouldHaveStorageSettingsTitle() {
         ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
 
         final Slice slice = mLowStorageSlice.getSlice();
 
-        assertThat(slice).isNull();
+        final List<SliceItem> sliceItems = slice.getItems();
+        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.storage_settings));
+    }
+
+    @Test
+    @Config(shadows = ShadowPrivateStorageInfo.class)
+    public void getSlice_storageFree_shouldHaveErrorHint() {
+        ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
+
+        final Slice slice = mLowStorageSlice.getSlice();
+
+        assertThat(slice.hasHint(HINT_ERROR)).isTrue();
     }
 
     @Implements(PrivateStorageInfo.class)
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index abfddbb..7d71302 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 
 import android.app.Activity;
@@ -51,10 +52,14 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 public class SliceContextualCardRendererTest {
 
+    private static final Uri TEST_SLICE_URI = Uri.parse("content://test/test");
+
     @Mock
     private LiveData<Slice> mSliceLiveData;
     @Mock
     private ControllerRendererPool mControllerRendererPool;
+    @Mock
+    private SliceContextualCardController mController;
 
     private Activity mActivity;
     private SliceContextualCardRenderer mRenderer;
@@ -66,7 +71,7 @@
         final ActivityController<Activity> activityController = Robolectric.buildActivity(
                 Activity.class);
         mActivity = activityController.get();
-        mActivity.setTheme(R.style.Theme_AppCompat);
+        mActivity.setTheme(R.style.Theme_Settings_Home);
         activityController.create();
         mLifecycleOwner = new ContextualCardsFragment();
         mRenderer = new SliceContextualCardRenderer(mActivity, mLifecycleOwner,
@@ -75,10 +80,9 @@
 
     @Test
     public void bindView_shouldSetScrollableToFalse() {
-        final String sliceUri = "content://com.android.settings.slices/action/flashlight";
         RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
 
-        mRenderer.bindView(viewHolder, buildContextualCard(sliceUri));
+        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
 
         assertThat(
                 ((SliceContextualCardRenderer.SliceViewHolder) viewHolder).sliceView.isScrollable
@@ -87,7 +91,7 @@
 
     @Test
     public void bindView_invalidScheme_sliceShouldBeNull() {
-        final String sliceUri = "contet://com.android.settings.slices/action/flashlight";
+        final Uri sliceUri = Uri.parse("contet://com.android.settings.slices/action/flashlight");
         RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
 
         mRenderer.bindView(viewHolder, buildContextualCard(sliceUri));
@@ -99,64 +103,124 @@
 
     @Test
     public void bindView_newSliceLiveData_shouldAddDataToMap() {
-        final String sliceUri = "content://com.android.settings.slices/action/flashlight";
-
-        mRenderer.bindView(getSliceViewHolder(), buildContextualCard(sliceUri));
+        mRenderer.bindView(getSliceViewHolder(), buildContextualCard(TEST_SLICE_URI));
 
         assertThat(mRenderer.mSliceLiveDataMap.size()).isEqualTo(1);
     }
 
     @Test
     public void bindView_sliceLiveDataShouldObserveSliceView() {
-        final String sliceUri = "content://com.android.settings.slices/action/flashlight";
+        mRenderer.bindView(getSliceViewHolder(), buildContextualCard(TEST_SLICE_URI));
 
-        mRenderer.bindView(getSliceViewHolder(), buildContextualCard(sliceUri));
-
-        assertThat(mRenderer.mSliceLiveDataMap.get(sliceUri).hasObservers()).isTrue();
+        assertThat(mRenderer.mSliceLiveDataMap.get(TEST_SLICE_URI).hasObservers()).isTrue();
     }
 
     @Test
     public void bindView_sliceLiveDataShouldRemoveObservers() {
-        final String sliceUri = "content://com.android.settings.slices/action/flashlight";
-        mRenderer.mSliceLiveDataMap.put(sliceUri, mSliceLiveData);
+        mRenderer.mSliceLiveDataMap.put(TEST_SLICE_URI, mSliceLiveData);
 
-        mRenderer.bindView(getSliceViewHolder(), buildContextualCard(sliceUri));
+        mRenderer.bindView(getSliceViewHolder(), buildContextualCard(TEST_SLICE_URI));
 
         verify(mSliceLiveData).removeObservers(mLifecycleOwner);
     }
 
     @Test
     public void longClick_shouldFlipCard() {
-        final String sliceUri = "content://com.android.settings.slices/action/flashlight";
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
         final View card = viewHolder.itemView.findViewById(R.id.slice_view);
         final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.viewFlipper);
         final View dismissalView = viewHolder.itemView.findViewById(R.id.dismissal_view);
-        mRenderer.bindView(viewHolder, buildContextualCard(sliceUri));
+        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
 
-        assertThat(card).isNotNull();
         card.performLongClick();
 
         assertThat(viewFlipper.getCurrentView()).isEqualTo(dismissalView);
     }
 
     @Test
+    public void longClick_shouldAddViewHolderToSet() {
+        final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
+        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
+        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+
+        card.performLongClick();
+
+        assertThat(mRenderer.mFlippedCardSet).contains(viewHolder);
+    }
+
+    @Test
     public void viewClick_keepCard_shouldFlipBackToSlice() {
-        final String sliceUri = "content://com.android.settings.slices/action/flashlight";
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
         final View card = viewHolder.itemView.findViewById(R.id.slice_view);
         final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
         final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.viewFlipper);
-        mRenderer.bindView(viewHolder, buildContextualCard(sliceUri));
+        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
 
-        assertThat(card).isNotNull();
         card.performLongClick();
-        assertThat(btnKeep).isNotNull();
         btnKeep.performClick();
 
         assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
     }
 
+    @Test
+    public void viewClick_keepCard_shouldRemoveViewHolderFromSet() {
+        final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
+        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
+        final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
+        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+
+        card.performLongClick();
+        btnKeep.performClick();
+
+        assertThat(mRenderer.mFlippedCardSet).doesNotContain(viewHolder);
+    }
+
+    @Test
+    public void viewClick_removeCard_shouldRemoveViewHolderFromSet() {
+        final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
+        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
+        final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
+        final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
+        mRenderer.bindView(viewHolder, contextualCard);
+        doReturn(mController).when(mControllerRendererPool).getController(mActivity,
+                ContextualCard.CardType.SLICE);
+
+        card.performLongClick();
+        btnRemove.performClick();
+
+        assertThat(mRenderer.mFlippedCardSet).doesNotContain(viewHolder);
+    }
+
+    @Test
+    public void viewClick_removeCard_sliceLiveDataShouldRemoveObservers() {
+        final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
+        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
+        final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
+        final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
+        mRenderer.mSliceLiveDataMap.put(TEST_SLICE_URI, mSliceLiveData);
+        mRenderer.bindView(viewHolder, contextualCard);
+        doReturn(mController).when(mControllerRendererPool).getController(mActivity,
+                ContextualCard.CardType.SLICE);
+
+        card.performLongClick();
+        btnRemove.performClick();
+
+        assertThat(mRenderer.mSliceLiveDataMap.get(TEST_SLICE_URI).hasObservers()).isFalse();
+    }
+
+    @Test
+    public void onStop_cardIsFlipped_shouldFlipBack() {
+        final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
+        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
+        final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.viewFlipper);
+        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+
+        card.performLongClick();
+        mRenderer.onStop();
+
+        assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
+    }
+
     private RecyclerView.ViewHolder getSliceViewHolder() {
         final int viewType = mRenderer.getViewType(false /* isHalfWidth */);
         final RecyclerView recyclerView = new RecyclerView(mActivity);
@@ -166,10 +230,11 @@
         return mRenderer.createViewHolder(view);
     }
 
-    private ContextualCard buildContextualCard(String sliceUri) {
+    private ContextualCard buildContextualCard(Uri sliceUri) {
         return new ContextualCard.Builder()
                 .setName("test_name")
-                .setSliceUri(Uri.parse(sliceUri))
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(sliceUri)
                 .build();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/location/LocationScanningPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationScanningPreferenceControllerTest.java
index e25b226..994a8fd 100644
--- a/tests/robotests/src/com/android/settings/location/LocationScanningPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationScanningPreferenceControllerTest.java
@@ -18,7 +18,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.content.Context;
+import android.provider.Settings;
+
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.R;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -28,22 +32,63 @@
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class LocationScanningPreferenceControllerTest {
+    private Context mContext;
+    private LocationScanningPreferenceController mController;
 
-  private LocationScanningPreferenceController mController;
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mController = new LocationScanningPreferenceController(mContext);
+    }
 
-  @Before
-  public void setUp() {
-    mController = new LocationScanningPreferenceController(RuntimeEnvironment.application);
-  }
+    @Test
+    public void testLocationScanning_byDefault_shouldBeShown() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
 
-  @Test
-  public void testLocationScanning_byDefault_shouldBeShown() {
-    assertThat(mController.isAvailable()).isTrue();
-  }
+    @Test
+    public void testLocationScanning_WifiOnBleOn() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 1);
+        assertThat(mController.getSummary()).isEqualTo(
+                mContext.getString(R.string.scanning_status_text_wifi_on_ble_on));
+    }
 
-  @Test
-  @Config(qualifiers = "mcc999")
-  public void testLocationScanning_ifDisabled_shouldNotBeShown() {
-    assertThat(mController.isAvailable()).isFalse();
-  }
+    @Test
+    public void testLocationScanning_WifiOnBleOff() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
+        assertThat(mController.getSummary()).isEqualTo(
+                mContext.getString(R.string.scanning_status_text_wifi_on_ble_off));
+    }
+
+    @Test
+    public void testLocationScanning_WifiOffBleOn() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 1);
+        assertThat(mController.getSummary()).isEqualTo(
+                mContext.getString(R.string.scanning_status_text_wifi_off_ble_on));
+    }
+
+    @Test
+    public void testLocationScanning_WifiOffBleOff() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
+        assertThat(mController.getSummary()).isEqualTo(
+                mContext.getString(R.string.scanning_status_text_wifi_off_ble_off));
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void testLocationScanning_ifDisabled_shouldNotBeShown() {
+        assertThat(mController.isAvailable()).isFalse();
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java b/tests/robotests/src/com/android/settings/location/LocationSliceTest.java
similarity index 93%
rename from tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java
rename to tests/robotests/src/com/android/settings/location/LocationSliceTest.java
index ecbf858..8f1045a 100644
--- a/tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationSliceTest.java
@@ -24,7 +24,7 @@
 import java.util.List;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-public class LocationSliceBuilderTest {
+public class LocationSliceTest {
 
     private Context mContext;
 
@@ -38,7 +38,7 @@
 
     @Test
     public void getLocationSlice_correctSliceContent() {
-        final Slice LocationSlice = LocationSliceBuilder.getSlice(mContext);
+        final Slice LocationSlice = new LocationSlice(mContext).getSlice();
         final SliceMetadata metadata = SliceMetadata.from(mContext, LocationSlice);
 
         final List<SliceAction> toggles = metadata.getToggles();
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java
new file mode 100644
index 0000000..02e4024
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SubscriptionUtilTest {
+    @Mock
+    private SubscriptionManager mManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void getAvailableSubscriptions_nullInfoFromSubscriptionManager_nonNullResult() {
+        when(mManager.getAvailableSubscriptionInfoList()).thenReturn(null);
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        assertThat(subs).isNotNull();
+        assertThat(subs).isEmpty();
+    }
+
+    @Test
+    public void getAvailableSubscriptions_oneSubscription_oneResult() {
+        final SubscriptionInfo info = mock(SubscriptionInfo.class);
+        when(info.getMncString()).thenReturn("fake1234");
+        when(mManager.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        assertThat(subs).isNotNull();
+        assertThat(subs).hasSize(1);
+    }
+
+    @Test
+    public void getAvailableSubscriptions_twoSubscriptions_twoResults() {
+        final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+        when(info1.getMncString()).thenReturn("fake1234");
+        when(info2.getMncString()).thenReturn("fake5678");
+        when(mManager.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info1, info2));
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        assertThat(subs).isNotNull();
+        assertThat(subs).hasSize(2);
+    }
+
+    @Test
+    public void getAvailableSubscriptions_oneSubWithHiddenNetworks_oneResult() {
+        final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info3 = mock(SubscriptionInfo.class);
+        when(info1.getSubscriptionId()).thenReturn(1);
+        when(info1.getMncString()).thenReturn("fake1234");
+        when(mManager.getAvailableSubscriptionInfoList()).thenReturn(
+                new ArrayList<>(Arrays.asList(info1, info2, info3)));
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        assertThat(subs).isNotNull();
+        assertThat(subs).hasSize(1);
+        assertThat(subs.get(0).getSubscriptionId()).isEqualTo(1);
+    }
+
+    @Test
+    public void getAvailableSubscriptions_twoSubsWithHiddenNetworks_twoResults() {
+        final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info3 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info4 = mock(SubscriptionInfo.class);
+        when(info1.getSubscriptionId()).thenReturn(1);
+        when(info1.getMncString()).thenReturn("fake1234");
+        when(info4.getSubscriptionId()).thenReturn(4);
+        when(info4.getMncString()).thenReturn("fake5678");
+        when(mManager.getAvailableSubscriptionInfoList()).thenReturn(new ArrayList<>(
+                Arrays.asList(info1, info2, info3, info4)));
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        assertThat(subs).isNotNull();
+        assertThat(subs).hasSize(2);
+        assertThat(subs.get(0).getSubscriptionId()).isEqualTo(1);
+        assertThat(subs.get(1).getSubscriptionId()).isEqualTo(4);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java
new file mode 100644
index 0000000..88ea2ea
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.AdditionalMatchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+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;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+
+import com.android.settings.network.SubscriptionsChangeListener.SubscriptionsChangeListenerClient;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SubscriptionsChangeListenerTest {
+
+    @Mock
+    private SubscriptionsChangeListenerClient mClient;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+
+    private Context mContext;
+    private SubscriptionsChangeListener mListener;
+    private Uri mAirplaneModeUri;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+
+        mAirplaneModeUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
+    }
+
+    private void initListener(boolean alsoStart) {
+        mListener = new SubscriptionsChangeListener(mContext, mClient);
+        if (alsoStart) {
+            mListener.start();
+        }
+    }
+
+    @Test
+    public void whenStartNotCalled_noListeningWasSetup() {
+        final ContentResolver contentResolver = mock(ContentResolver.class);
+        when(mContext.getContentResolver()).thenReturn(contentResolver);
+        initListener(false);
+        verify(contentResolver, never()).registerContentObserver(any(Uri.class), anyBoolean(),
+                any(ContentObserver.class));
+        verify(mSubscriptionManager, never()).addOnSubscriptionsChangedListener(any());
+        verify(mContext, never()).registerReceiver(any(), any());
+    }
+
+    @Test
+    public void onSubscriptionsChangedEvent_subscriptionManagerFires_eventDeliveredToUs() {
+        initListener(true);
+        final ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> captor =
+                ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
+        verify(mSubscriptionManager).addOnSubscriptionsChangedListener(captor.capture());
+        captor.getValue().onSubscriptionsChanged();
+        verify(mClient).onSubscriptionsChanged();
+    }
+
+    @Test
+    public void onSubscriptionsChangedEvent_radioTechnologyChangedBroadcast_eventDeliveredToUs() {
+        initListener(true);
+        final ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any());
+        broadcastReceiverCaptor.getValue().onReceive(mContext, null);
+        verify(mClient).onSubscriptionsChanged();
+    }
+
+    @Test
+    public void onAirplaneModeChangedEvent_becameTrue_eventFires() {
+        initListener(true);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
+        mListener.onChange(false, mAirplaneModeUri);
+        verify(mClient).onAirplaneModeChanged(true);
+        assertThat(mListener.isAirplaneModeOn()).isTrue();
+    }
+
+    @Test
+    public void onAirplaneModeChangedEvent_becameFalse_eventFires() {
+        initListener(true);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
+        mListener.onChange(false, mAirplaneModeUri);
+        verify(mClient).onAirplaneModeChanged(false);
+        assertThat(mListener.isAirplaneModeOn()).isFalse();
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
index 2fc3d98..e1ad93b 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
@@ -20,6 +20,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -104,9 +105,8 @@
     public void isDialogNeeded_enableNonDefaultSimInMultiSimMode_returnTrue() {
         doReturn(false).when(mTelephonyManager).isDataEnabled();
         doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
-        doReturn(null).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
+        doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(anyInt());
         doReturn(2).when(mTelephonyManager).getSimCount();
-        doReturn(1).when(mTelephonyManager).getNumberOfModemsWithSimultaneousDataConnections();
 
         assertThat(mController.isDialogNeeded()).isTrue();
         assertThat(mController.mDialogType).isEqualTo(
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
index ec50e2b..b431c0a 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
@@ -16,13 +16,17 @@
 
 package com.android.settings.notification;
 
-import static junit.framework.Assert.assertEquals;
-
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.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.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.AutomaticZenRule;
-import android.app.NotificationManager;
 import android.content.Context;
 import android.provider.Settings;
 
@@ -31,161 +35,122 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.internal.util.reflection.FieldSetter;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.ReflectionHelpers;
 
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ZenModeAutomaticRulesPreferenceControllerTest {
 
-    private static final String GENERIC_RULE_NAME = "test";
-    private static final String DEFAULT_ID_1 = "DEFAULT_1";
-    private static final String DEFAULT_ID_2 = "DEFAULT_2";
-
     private ZenModeAutomaticRulesPreferenceController mController;
-    private final List<String> mDefaultIds = Arrays.asList(DEFAULT_ID_1, DEFAULT_ID_2);
-
     @Mock
     private ZenModeBackend mBackend;
     @Mock
-    private NotificationManager mNotificationManager;
-    @Mock
     private PreferenceCategory mockPref;
     @Mock
-    private NotificationManager.Policy mPolicy;
-    @Mock
     private PreferenceScreen mPreferenceScreen;
-
+    @Mock
+    private ZenRulePreference mZenRulePreference;
     private Context mContext;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        ShadowApplication shadowApplication = ShadowApplication.getInstance();
-        shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
-
         mContext = RuntimeEnvironment.application;
-        when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
-        mController = new ZenModeAutomaticRulesPreferenceController(mContext, mock(Fragment.class),
-                mock(Lifecycle.class));
-
+        mController = spy(new ZenModeAutomaticRulesPreferenceController(mContext, mock(Fragment.class),
+                null));
         ReflectionHelpers.setField(mController, "mBackend", mBackend);
-        ReflectionHelpers.setField(mController, "mDefaultRuleIds", mDefaultIds);
-
         when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
                 mockPref);
         mController.displayPreference(mPreferenceScreen);
+        doReturn(mZenRulePreference).when(mController).createZenRulePreference(any());
     }
 
     @Test
-    public void updateState_checkRuleOrderingDescending() {
-        final int NUM_RULES = 4;
-        when(mNotificationManager.getAutomaticZenRules()).thenReturn(
-                mockAutoZenRulesDecreasingCreationTime(NUM_RULES));
+    public void testUpdateState_clearsPreferencesWhenAddingNewPreferences() {
+        final int NUM_RULES = 3;
+        Map<String, AutomaticZenRule> rMap = new HashMap<>();
 
-        Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
-        assertEquals(NUM_RULES, rules.length);
+        String ruleId1 = "test1_id";
+        String ruleId2 = "test2_id";
+        String ruleId3 = "test3_id";
 
-        // check ordering, most recent should be at the bottom/end (ie higher creation time)
-        for (int i = 0; i < NUM_RULES; i++) {
-            assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i].getKey());
-        }
+        AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+        AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
+        AutomaticZenRule autoRule3 = new AutomaticZenRule("test_rule_3", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 30);
+
+        rMap.put(ruleId1, autoRule1);
+        rMap.put(ruleId2, autoRule2);
+        rMap.put(ruleId3, autoRule3);
+
+        // should add 3 new preferences to mockPref
+        mockGetAutomaticZenRules(NUM_RULES, rMap);
+        mController.updateState(mockPref);
+        verify(mockPref, times(1)).removeAll();
+        verify(mockPref, times(NUM_RULES)).addPreference(any());
     }
 
     @Test
-    public void updateState_checkRuleOrderingAscending() {
-        final int NUM_RULES = 4;
-        when(mNotificationManager.getAutomaticZenRules()).thenReturn(
-                mockAutoZenRulesAscendingCreationTime(NUM_RULES));
+    public void testUpdateState_clearsPreferencesWhenRemovingPreferences(){
+        final int NUM_RULES = 2;
+        Map<String, AutomaticZenRule> rMap = new HashMap<>();
 
-        Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
-        assertEquals(NUM_RULES, rules.length);
+        String ruleId1 = "test1_id";
+        String ruleId2 = "test2_id";
 
-        // check ordering, most recent should be at the bottom/end (ie higher creation time)
-        for (int i = 0; i < NUM_RULES; i++) {
-            assertEquals(GENERIC_RULE_NAME + i, rules[i].getKey());
-        }
+        AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+        AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
+
+        rMap.put(ruleId1, autoRule1);
+        rMap.put(ruleId2, autoRule2);
+
+        // update state should re-add all preferences since a preference was deleted
+        when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES + 2);
+        mockGetAutomaticZenRules(NUM_RULES, rMap);
+        mController.updateState(mockPref);
+        verify(mockPref, times(1)).removeAll();
+        verify(mockPref, times(NUM_RULES)).addPreference(any());
     }
 
     @Test
-    public void updateState_checkRuleOrderingDescending_withDefaultRules() {
-        final int NUM_RULES = 4;
+    public void testUpdateState_updateEnableState() throws NoSuchFieldException {
+        final int NUM_RULES = 1;
+        Map<String, AutomaticZenRule> rMap = new HashMap<>();
+        String testId = "test1_id";
+        AutomaticZenRule rule = new AutomaticZenRule("rule_name", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+        rMap.put(testId, rule);
 
-        Map<String, AutomaticZenRule> ruleMap = mockAutoZenRulesDecreasingCreationTime(NUM_RULES);
-        ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_1_NAME", null,
-                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
-        ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
-                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
-        when(mNotificationManager.getAutomaticZenRules()).thenReturn(ruleMap);
+        when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES);
+        when(mockPref.getPreference(anyInt())).thenReturn(mZenRulePreference);
 
-        Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
-        assertEquals(NUM_RULES + 2, rules.length);
-
-        assertEquals(rules[0].getKey(), DEFAULT_ID_1);
-        assertEquals(rules[1].getKey(), DEFAULT_ID_2);
-        // NON-DEFAULT RULES check ordering, most recent at the bottom/end
-        for (int i = 0; i < NUM_RULES; i++) {
-            assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey());
-        }
+        // update state should NOT re-add all the preferences, should only update enable state
+        rule.setEnabled(false);
+        rMap.put(testId, rule);
+        mockGetAutomaticZenRules(NUM_RULES, rMap);
+        FieldSetter.setField(mZenRulePreference, ZenRulePreference.class.getDeclaredField("mId"), testId);
+        mController.updateState(mockPref);
+        verify(mZenRulePreference, times(1)).updatePreference(any());
+        verify(mController, never()).reloadAllRules(any());
     }
 
-    @Test
-    public void updateState_checkRuleOrderingMix() {
-        final int NUM_RULES = 4;
-        // map with creation times: 0, 2, 4, 6
-        Map<String,AutomaticZenRule> rMap = mockAutoZenRulesAscendingCreationTime(NUM_RULES);
-
-        final String insertedRule1 = "insertedRule1";
-        rMap.put(insertedRule1, new AutomaticZenRule(insertedRule1, null, null,
-                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 5));
-
-        final String insertedRule2 = "insertedRule2";
-        rMap.put(insertedRule2, new AutomaticZenRule(insertedRule2, null, null,
-                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 3));
-
-        // rule map with rule creation times, 0, 2, 4, 6, 5, 3
-        // sort should create ordering based on creation times: 0, 2, 3, 4, 5, 6
-        when(mNotificationManager.getAutomaticZenRules()).thenReturn(rMap);
-
-        Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
-        assertEquals(NUM_RULES + 2, rules.length); // inserted 2 rules
-
-        // check ordering of inserted rules
-        assertEquals(insertedRule1, rules[4].getKey());
-        assertEquals(insertedRule2, rules[2].getKey());
-    }
-
-    private Map<String, AutomaticZenRule> mockAutoZenRulesAscendingCreationTime(int numRules) {
-        Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
-
-        for (int i = 0; i < numRules; i++) {
-            ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
-                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2));
-        }
-
-        return ruleMap;
-    }
-
-    private Map<String, AutomaticZenRule> mockAutoZenRulesDecreasingCreationTime(int numRules) {
-        Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
-
-        for (int i = 0; i < numRules; i++) {
-            ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
-                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i));
-        }
-
-        return ruleMap;
+    private void mockGetAutomaticZenRules(int numRules, Map<String, AutomaticZenRule> rules) {
+        Map.Entry<String, AutomaticZenRule>[] arr = new Map.Entry[numRules];
+        rules.entrySet().toArray(arr);
+        when(mBackend.getAutomaticZenRules()).thenReturn(arr);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
new file mode 100644
index 0000000..94a3c01
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
@@ -0,0 +1,108 @@
+package com.android.settings.notification;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.app.AutomaticZenRule;
+import android.provider.Settings;
+import android.service.notification.ZenModeConfig;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ZenModeBackendTest {
+
+    private static final String GENERIC_RULE_NAME = "test";
+    private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
+    private static final String DEFAULT_ID_2 = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
+
+    @Test
+    public void updateState_checkRuleOrderingDescending() {
+        final int NUM_RULES = 4;
+        Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesDescendingCreationTime(
+                NUM_RULES, false);
+        Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+        // check ordering, most recent should be at the end
+        for (int i = 0; i < NUM_RULES; i++) {
+            assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i].getKey());
+        }
+    }
+
+    @Test
+    public void updateState_checkRuleOrderingAscending() {
+        final int NUM_RULES = 4;
+        Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesAscendingCreationTime(
+                NUM_RULES, false);
+        Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+        // check ordering, most recent should be at the end
+        for (int i = 0; i < NUM_RULES; i++) {
+            assertEquals(GENERIC_RULE_NAME + i, rules[i].getKey());
+        }
+    }
+
+    @Test
+    public void updateState_checkRuleOrderingDescending_withDefaultRules() {
+        final int NUM_RULES = 4;
+
+        Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesDescendingCreationTime(NUM_RULES,
+                true);
+        Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+        assertEquals(rules[0].getKey(), DEFAULT_ID_1);
+        assertEquals(rules[1].getKey(), DEFAULT_ID_2);
+        // NON-DEFAULT RULES check ordering, most recent at the bottom/end
+        for (int i = 0; i < NUM_RULES; i++) {
+            assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey());
+        }
+    }
+
+    private Map.Entry<String, AutomaticZenRule>[] populateAutoZenRulesAscendingCreationTime(
+            int numRules, boolean addDefaultRules) {
+        Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
+
+        for (int i = 0; i < numRules; i++) {
+            ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2));
+        }
+
+        if (addDefaultRules) {
+            ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
+            ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
+        }
+
+        Map.Entry<String, AutomaticZenRule>[] toReturn = new Map.Entry[ruleMap.size()];
+        ruleMap.entrySet().toArray(toReturn);
+        return toReturn;
+    }
+
+    private Map.Entry<String, AutomaticZenRule>[] populateAutoZenRulesDescendingCreationTime(
+            int numRules, boolean addDefaultRules) {
+        Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
+
+        for (int i = 0; i < numRules; i++) {
+            ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i));
+        }
+
+        if (addDefaultRules) {
+            ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
+            ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
+        }
+
+        Map.Entry<String, AutomaticZenRule>[] toReturn = new Map.Entry[ruleMap.size()];
+        ruleMap.entrySet().toArray(toReturn);
+        return toReturn;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModePriorityCallsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModePriorityCallsPreferenceControllerTest.java
index 36a1382..7131250 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModePriorityCallsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModePriorityCallsPreferenceControllerTest.java
@@ -30,6 +30,9 @@
 import android.content.Context;
 import android.provider.Settings;
 
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -43,9 +46,6 @@
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.ReflectionHelpers;
 
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceScreen;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ZenModePriorityCallsPreferenceControllerTest {
 
@@ -86,8 +86,8 @@
 
         when(mBackend.getPriorityCallSenders())
                 .thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_STARRED);
-        when(mBackend.getContactsSummary(ZenModeBackend.SOURCE_NONE))
-                .thenCallRealMethod();
+        when(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
+                NotificationManager.Policy.PRIORITY_CATEGORY_CALLS)).thenCallRealMethod();
         when(mBackend.getContactsSummary(NotificationManager.Policy.PRIORITY_CATEGORY_CALLS))
                 .thenCallRealMethod();
 
@@ -110,7 +110,7 @@
         mController.updateState(mockPref);
 
         verify(mockPref).setEnabled(false);
-        verify(mockPref).setSummary(R.string.zen_mode_from_none);
+        verify(mockPref).setSummary(R.string.zen_mode_from_none_calls);
     }
 
     @Test
@@ -121,7 +121,7 @@
         mController.updateState(mockPref);
 
         verify(mockPref).setEnabled(false);
-        verify(mockPref).setSummary(R.string.zen_mode_from_none);
+        verify(mockPref).setSummary(R.string.zen_mode_from_none_calls);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceControllerTest.java
index 75605a4..7b6698d 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceControllerTest.java
@@ -30,6 +30,9 @@
 import android.content.Context;
 import android.provider.Settings;
 
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -43,9 +46,6 @@
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.ReflectionHelpers;
 
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceScreen;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ZenModePriorityMessagesPreferenceControllerTest {
 
@@ -86,8 +86,8 @@
 
         when(mBackend.getPriorityMessageSenders())
             .thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_STARRED);
-        when(mBackend.getContactsSummary(ZenModeBackend.SOURCE_NONE))
-                .thenCallRealMethod();
+        when(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
+                NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)).thenCallRealMethod();
         when(mBackend.getContactsSummary(NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES))
                 .thenCallRealMethod();
 
@@ -110,7 +110,7 @@
         mController.updateState(mockPref);
 
         verify(mockPref).setEnabled(false);
-        verify(mockPref).setSummary(R.string.zen_mode_from_none);
+        verify(mockPref).setSummary(R.string.zen_mode_from_none_messages);
     }
 
     @Test
@@ -121,7 +121,7 @@
         mController.updateState(mockPref);
 
         verify(mockPref).setEnabled(false);
-        verify(mockPref).setSummary(R.string.zen_mode_from_none);
+        verify(mockPref).setSummary(R.string.zen_mode_from_none_messages);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
index c1634fb..ca9f942 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
@@ -126,7 +126,7 @@
     }
 
     @Test
-    public void app_manualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_app_manualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         injectManualRuleFromApp();
         mController.updateState(mockPref);
@@ -137,7 +137,7 @@
     }
 
     @Test
-    public void time_manualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_time_manualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         String placeholder = "placeholder";
         injectManualRuleWithTimeCountdown(1000, placeholder);
@@ -148,7 +148,7 @@
     }
 
     @Test
-    public void forever_manualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_forever_manualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         injectManualRuleWithIndefiniteEnd();
         mController.updateState(mockPref);
@@ -158,7 +158,7 @@
     }
 
     @Test
-    public void automaticRule_noManualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_automaticRule_noManualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         // no manual rule
         ReflectionHelpers.setField(mZenModeConfig, MANUAL_RULE_FIELD, null);
@@ -174,7 +174,7 @@
     }
 
     @Test
-    public void manualRuleEndsLast_hasAutomaticRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_manualRuleEndsLast_hasAutomaticRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         // manual rule that ends after automatic rule ends
         injectManualRuleWithIndefiniteEnd();
@@ -190,7 +190,7 @@
     }
 
     @Test
-    public void automaticRuleEndsLast_hasManualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_automaticRuleEndsLast_hasManualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         // manual rule that ends before automatic rule ends
         injectManualRuleWithTimeCountdown(1000, "");
@@ -208,14 +208,15 @@
     }
 
     @Test
-    public void multipleAutomaticRules_appAutoRuleautomaticRuleApp_setFooterTitle() {
+    public void testDefaultNotifPolicy_multipleAutomaticRules_autoRuleApp_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
 
         // automatic rule that ends after manual rule ends
         ZenRule rule1 = injectNewAutomaticRule(TEST_RULE_NAME + "1", false, false);
         when(mConfigWrapper.parseAutomaticRuleEndTime(rule1.conditionId)).thenReturn(10000L);
 
-        ZenRule rule2 = injectNewAutomaticRule(TEST_RULE_NAME + "2", true, true);
+        // automatic rule that is an app
+        injectNewAutomaticRule(TEST_RULE_NAME + "2", true, true);
 
         ZenRule rule3 = injectNewAutomaticRule(TEST_RULE_NAME + "3", true, false);
         when(mConfigWrapper.parseAutomaticRuleEndTime(rule3.conditionId)).thenReturn(9000L);
@@ -229,7 +230,7 @@
     }
 
     @Test
-    public void multipleAutomaticRules_setFooterTitle() {
+    public void testDefaultNotifPolicy_multipleAutomaticRules_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
 
         // automatic rule that ends after manual rule ends
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
index 4fc7d57..53032ac 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
@@ -71,20 +71,20 @@
     @Test
     public void testGetCallsSettingSummary_none() {
         Policy policy = new Policy(0, 0, 0, 0);
-        assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("None");
+        assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("Don\u2019t allow any calls");
     }
 
     @Test
     public void testGetCallsSettingSummary_contacts() {
         Policy policy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | Policy.PRIORITY_CATEGORY_CALLS,
                 Policy.PRIORITY_SENDERS_CONTACTS, 0, 0);
-        assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("From contacts");
+        assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("Allow from contacts");
     }
 
     @Test
     public void testGetCallsSettingSummary_repeatCallers() {
         Policy policy = new Policy(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0);
-        assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("From repeat callers");
+        assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("Allow from repeat callers");
     }
 
     @Test
@@ -93,7 +93,7 @@
                 Policy.PRIORITY_CATEGORY_REPEAT_CALLERS | Policy.PRIORITY_CATEGORY_CALLS,
                 Policy.PRIORITY_SENDERS_STARRED, 0, 0);
         assertThat(mBuilder.getCallsSettingSummary(policy))
-                .isEqualTo("From starred contacts and repeat callers");
+                .isEqualTo("Allow from starred contacts and repeat callers");
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
index 9b29d48..cf344d2 100644
--- a/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
@@ -61,7 +61,6 @@
         mFakePanelContent = new FakePanelContent();
         doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
 
-
         ActivityController<FakeSettingsPanelActivity> activityController =
                 Robolectric.buildActivity(FakeSettingsPanelActivity.class);
         activityController.setup();
diff --git a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
index bfd7863..02a7d0a 100644
--- a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
@@ -54,7 +54,13 @@
     public void setUp() {
         mContext = RuntimeEnvironment.application;
 
-        final ActivityController<FakeSettingsPanelActivity> activityController =
+        mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
+        mFakePanelContent = new FakePanelContent();
+        doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
+
+        ActivityController<FakeSettingsPanelActivity> activityController =
                 Robolectric.buildActivity(FakeSettingsPanelActivity.class);
         activityController.setup();
 
@@ -65,12 +71,6 @@
                                 .getSupportFragmentManager()
                                 .findFragmentById(R.id.main_content));
 
-        mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
-        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
-        mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
-        mFakePanelContent = new FakePanelContent();
-        doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
-
         mAdapter = new PanelSlicesAdapter(mPanelFragment, mFakePanelContent.getSlices());
     }
 
diff --git a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
new file mode 100644
index 0000000..21019d3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.panel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class VolumePanelTest {
+
+    private VolumePanel mPanel;
+
+    @Before
+    public void setUp() {
+        mPanel = VolumePanel.create(RuntimeEnvironment.application);
+    }
+
+    @Test
+    public void getSlices_containsNecessarySlices() {
+        final List<Uri> uris = mPanel.getSlices();
+
+        assertThat(uris).containsExactly(
+                CustomSliceRegistry.VOLUME_CALL_URI,
+                CustomSliceRegistry.VOLUME_MEDIA_URI,
+                CustomSliceRegistry.VOLUME_RINGER_URI,
+                CustomSliceRegistry.VOLUME_ALARM_URI);
+    }
+
+    @Test
+    public void getSeeMoreIntent_notNull() {
+        assertThat(mPanel.getSeeMoreIntent()).isNotNull();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 2e2104b..821d383 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -218,6 +218,19 @@
     }
 
     @Test
+    public void getDynamicSummary_allowDynamicSummary_nullSummary_returnsNull() {
+        final SliceData data = getDummyData(true /*isDynamicSummaryAllowed*/);
+        final FakePreferenceController controller = spy(
+                new FakePreferenceController(mContext, KEY));
+        final String controllerSummary = null;
+        doReturn(controllerSummary).when(controller).getSummary();
+
+        final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
+
+        assertThat(summary).isNull();
+    }
+
+    @Test
     public void getDynamicSummary_returnsScreenTitle() {
         final SliceData data = getDummyData();
         final FakePreferenceController controller = new FakePreferenceController(mContext, KEY);
@@ -492,6 +505,19 @@
         assertThat(actualIconResource).isEqualTo(settingsIcon);
     }
 
+    @Test
+    public void getSafeIcon_invalidResource_shouldFallbackToSettingsIcon() {
+        final int settingsIcon = R.drawable.ic_settings;
+        final int badIcon = 0x12345678;
+        final SliceData data = getDummyData(TOGGLE_CONTROLLER, SliceData.SliceType.SWITCH,
+                badIcon);
+
+        final IconCompat actualIcon = SliceBuilderUtils.getSafeIcon(mContext, data);
+
+        final int actualIconResource = actualIcon.toIcon().getResId();
+        assertThat(actualIconResource).isEqualTo(settingsIcon);
+    }
+
     private SliceData getDummyData() {
         return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE,
                 ICON, IS_DYNAMIC_SUMMARY_ALLOWED);
diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
index 9417e9c..74914f4 100644
--- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
+++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
@@ -84,6 +84,8 @@
             paths.add(new ResourcePath(null,
                     Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SearchWidget/res/")), null));
             paths.add(new ResourcePath(null,
+                    Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/ActionButtonsPreference/res")), null));
+            paths.add(new ResourcePath(null,
                     Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SettingsLayoutPreference/res")), null));
             paths.add(new ResourcePath(null,
                 Fs.fromURL(new URL("file:frameworks/base/core/res/res")), null));
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index be4199d..c0ffdcd 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -110,8 +110,6 @@
 
         final SliceAction mainToggleAction = toggles.get(0);
 
-        final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
-                sliceData.getIconResource());
         assertThat(mainToggleAction.getIcon()).isNull();
 
         // Check intent in Toggle Action
@@ -238,6 +236,7 @@
         assertKeywords(metadata, sliceData);
     }
 
+    // TODO(b/120592507): Clean up method of SliceTester
     public static void assertTitle(List<SliceItem> sliceItems, String title) {
         boolean hasTitle = false;
         for (SliceItem item : sliceItems) {
@@ -257,6 +256,7 @@
         assertThat(hasTitle).isTrue();
     }
 
+    // TODO(b/120592507): Clean up method of SliceTester
     private static void assertKeywords(SliceMetadata metadata, SliceData data) {
         final List<String> keywords = metadata.getSliceKeywords();
         final Set<String> expectedKeywords = Arrays.stream(data.getKeywords().split(","))
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
index f11d9e8..e0576b2 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
@@ -17,7 +17,7 @@
 package com.android.settings.testutils.shadow;
 
 import android.content.Context;
-import android.content.pm.permission.RuntimePermissionPresenter;
+import android.permission.RuntimePermissionPresenter;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
diff --git a/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java
deleted file mode 100644
index 34a9872..0000000
--- a/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.widget;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-import android.widget.Button;
-
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-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 ActionButtonPreferenceTest {
-
-    private Context mContext;
-    private View mRootView;
-    private ActionButtonPreference mPref;
-    private PreferenceViewHolder mHolder;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        mRootView = View.inflate(mContext, R.layout.settings_action_buttons, null /* parent */);
-        mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
-        mPref = new ActionButtonPreference(mContext);
-    }
-
-    @Test
-    public void onBindViewHolder_setTitle_shouldShowButtonByDefault() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton2Text(R.string.settings_label);
-        mPref.setButton3Text(R.string.settings_label);
-        mPref.setButton4Text(R.string.settings_label);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void onBindViewHolder_setIcon_shouldShowButtonByDefault() {
-        mPref.setButton1Icon(R.drawable.ic_settings);
-        mPref.setButton2Icon(R.drawable.ic_settings);
-        mPref.setButton3Icon(R.drawable.ic_settings);
-        mPref.setButton4Icon(R.drawable.ic_settings);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void onBindViewHolder_notSetTitleOrIcon_shouldNotShowButtonByDefault() {
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void onBindViewHolder_setVisibleIsGoneAndSetTitle_shouldNotShowButton() {
-        mPref.setButton1Text(R.string.settings_label).setButton1Visible(false);
-        mPref.setButton2Text(R.string.settings_label).setButton2Visible(false);
-        mPref.setButton3Text(R.string.settings_label).setButton3Visible(false);
-        mPref.setButton4Text(R.string.settings_label).setButton4Visible(false);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void onBindViewHolder_setVisibleIsGoneAndSetIcon_shouldNotShowButton() {
-        mPref.setButton1Icon(R.drawable.ic_settings).setButton1Visible(false);
-        mPref.setButton2Icon(R.drawable.ic_settings).setButton2Visible(false);
-        mPref.setButton3Icon(R.drawable.ic_settings).setButton3Visible(false);
-        mPref.setButton4Icon(R.drawable.ic_settings).setButton4Visible(false);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void onBindViewHolder_setVisibility_shouldUpdateButtonVisibility() {
-        mPref.setButton1Text(R.string.settings_label).setButton1Visible(false);
-        mPref.setButton2Text(R.string.settings_label).setButton2Visible(false);
-        mPref.setButton3Text(R.string.settings_label).setButton3Visible(false);
-        mPref.setButton4Text(R.string.settings_label).setButton4Visible(false);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.GONE);
-
-        mPref.setButton1Visible(true);
-        mPref.setButton2Visible(true);
-        mPref.setButton3Visible(true);
-        mPref.setButton4Visible(true);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void onBindViewHolder_setEnabled_shouldEnableButton() {
-        mPref.setButton1Enabled(true);
-        mPref.setButton2Enabled(false);
-        mPref.setButton3Enabled(true);
-        mPref.setButton4Enabled(false);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).isEnabled()).isTrue();
-        assertThat(mRootView.findViewById(R.id.button2).isEnabled()).isFalse();
-        assertThat(mRootView.findViewById(R.id.button3).isEnabled()).isTrue();
-        assertThat(mRootView.findViewById(R.id.button4).isEnabled()).isFalse();
-    }
-
-    @Test
-    public void onBindViewHolder_setText_shouldShowSameText() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton2Text(R.string.settings_label);
-        mPref.setButton3Text(R.string.settings_label);
-        mPref.setButton4Text(R.string.settings_label);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(((Button) mRootView.findViewById(R.id.button1)).getText())
-                .isEqualTo(mContext.getText(R.string.settings_label));
-        assertThat(((Button) mRootView.findViewById(R.id.button2)).getText())
-                .isEqualTo(mContext.getText(R.string.settings_label));
-        assertThat(((Button) mRootView.findViewById(R.id.button3)).getText())
-                .isEqualTo(mContext.getText(R.string.settings_label));
-        assertThat(((Button) mRootView.findViewById(R.id.button4)).getText())
-                .isEqualTo(mContext.getText(R.string.settings_label));
-    }
-
-    @Test
-    public void onBindViewHolder_setButtonIcon_iconMustDisplayAboveText() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton1Icon(R.drawable.ic_settings);
-
-        mPref.onBindViewHolder(mHolder);
-        final Drawable[] drawablesAroundText =
-                ((Button) mRootView.findViewById(R.id.button1))
-                        .getCompoundDrawables();
-
-        assertThat(drawablesAroundText[1 /* top */]).isNotNull();
-    }
-
-    @Test
-    public void setButtonIcon_iconResourceIdIsZero_shouldNotDisplayIcon() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton1Icon(0);
-
-        mPref.onBindViewHolder(mHolder);
-        final Drawable[] drawablesAroundText =
-                ((Button) mRootView.findViewById(R.id.button1))
-                        .getCompoundDrawables();
-
-        assertThat(drawablesAroundText[1 /* top */]).isNull();
-    }
-
-    @Test
-    public void setButtonIcon_iconResourceIdNotExisting_shouldNotDisplayIconAndCrash() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton1Icon(999999999 /* not existing id */);
-        // Should not crash here
-        mPref.onBindViewHolder(mHolder);
-        final Drawable[] drawablesAroundText =
-                ((Button) mRootView.findViewById(R.id.button1))
-                        .getCompoundDrawables();
-
-        assertThat(drawablesAroundText[1 /* top */]).isNull();
-    }
-
-    public static ActionButtonPreference createMock() {
-        final ActionButtonPreference pref = mock(ActionButtonPreference.class);
-        when(pref.setButton1Text(anyInt())).thenReturn(pref);
-        when(pref.setButton1Icon(anyInt())).thenReturn(pref);
-        when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
-        when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
-        when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
-        when(pref.setButton2Text(anyInt())).thenReturn(pref);
-        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
-        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
-        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
-        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
-        when(pref.setButton3Text(anyInt())).thenReturn(pref);
-        when(pref.setButton3Icon(anyInt())).thenReturn(pref);
-        when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
-        when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
-        when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
-        when(pref.setButton4Text(anyInt())).thenReturn(pref);
-        when(pref.setButton4Icon(anyInt())).thenReturn(pref);
-        when(pref.setButton4Enabled(anyBoolean())).thenReturn(pref);
-        when(pref.setButton4Visible(anyBoolean())).thenReturn(pref);
-        when(pref.setButton4OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-        return pref;
-    }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/widget/FloatingAppBarScrollingViewBehaviorTest.java b/tests/robotests/src/com/android/settings/widget/FloatingAppBarScrollingViewBehaviorTest.java
new file mode 100644
index 0000000..6acc4d9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/FloatingAppBarScrollingViewBehaviorTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import com.google.android.material.appbar.AppBarLayout;
+
+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 FloatingAppBarScrollingViewBehaviorTest {
+
+    private FloatingAppBarScrollingViewBehavior mScrollingViewBehavior;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mScrollingViewBehavior = new FloatingAppBarScrollingViewBehavior(mContext,
+                Robolectric.buildAttributeSet().build());
+    }
+
+    @Test
+    public void shouldHeaderOverlapScrollingChild_returnTrue() {
+        assertThat(mScrollingViewBehavior.shouldHeaderOverlapScrollingChild()).isTrue();
+    }
+
+    @Test
+    public void setAppBarLayoutTransparent_backgroundDefaultAsWhite_shouldBeTransparent() {
+        mContext.setTheme(R.style.Theme_Settings_Home);
+        final AppBarLayout appBarLayout = new AppBarLayout(mContext);
+        appBarLayout.setBackgroundColor(Color.WHITE);
+        mScrollingViewBehavior.setAppBarLayoutTransparent(appBarLayout);
+        assertThat(((ColorDrawable) appBarLayout.getBackground()).getColor()).isEqualTo(
+                Color.TRANSPARENT);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/RadioButtonPickerFragmentTest.java b/tests/robotests/src/com/android/settings/widget/RadioButtonPickerFragmentTest.java
index 64352d9..55d212f 100644
--- a/tests/robotests/src/com/android/settings/widget/RadioButtonPickerFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/widget/RadioButtonPickerFragmentTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -37,7 +38,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
+import org.mockito.InOrder;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 
@@ -99,6 +102,26 @@
     }
 
     @Test
+    public void staticPreferencesPrepended_addedFirst() {
+        mFragment.mAppendStaticPreferences = false;
+        mFragment.updateCandidates();
+
+        InOrder inOrder = Mockito.inOrder(mFragment);
+        inOrder.verify(mFragment).addStaticPreferences(any());
+        inOrder.verify(mFragment).getRadioButtonPreferenceCustomLayoutResId();
+    }
+
+    @Test
+    public void staticPreferencesAppended_addedLast() {
+        mFragment.mAppendStaticPreferences = true;
+        mFragment.updateCandidates();
+
+        InOrder inOrder = Mockito.inOrder(mFragment);
+        inOrder.verify(mFragment).mayCheckOnlyRadioButton();
+        inOrder.verify(mFragment).addStaticPreferences(any());
+    }
+
+    @Test
     public void shouldHaveNoCustomPreferenceLayout() {
         assertThat(mFragment.getRadioButtonPreferenceCustomLayoutResId()).isEqualTo(0);
     }
diff --git a/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
index e12053c..91598c0 100644
--- a/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
@@ -33,6 +33,7 @@
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class CellularFallbackPreferenceControllerTest {
+    private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
@@ -42,7 +43,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mController = new CellularFallbackPreferenceController(mContext);
+        mController = new CellularFallbackPreferenceController(mContext, KEY_CELLULAR_FALLBACK);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
index 2e806dd..8cf02b8 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.wifi;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -32,213 +33,220 @@
 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
 import android.os.Bundle;
 import android.widget.Button;
+
 import androidx.appcompat.app.AlertDialog;
 import androidx.fragment.app.FragmentActivity;
+
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
 import com.android.settingslib.wifi.AccessPoint;
+
 import java.util.ArrayList;
 import java.util.List;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+
 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+
 import org.robolectric.shadows.ShadowLooper;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
 public class NetworkRequestDialogFragmentTest {
 
-  final String KEY_SSID = "key_ssid";
+    final String KEY_SSID = "key_ssid";
 
-  private FragmentActivity mActivity;
-  private NetworkRequestDialogFragment networkRequestDialogFragment;
-  private Context mContext;
+    private FragmentActivity mActivity;
+    private NetworkRequestDialogFragment networkRequestDialogFragment;
+    private Context mContext;
 
-  @Before
-  public void setUp() {
-    mActivity = Robolectric.setupActivity(FragmentActivity.class);
-    networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
-    mContext = spy(RuntimeEnvironment.application);
-  }
-
-  @Test
-  public void display_shouldShowTheDialog() {
-    networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-    assertThat(alertDialog).isNotNull();
-    assertThat(alertDialog.isShowing()).isTrue();
-  }
-
-  @Test
-  public void clickPositiveButton_shouldCloseTheDialog() {
-    networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-    assertThat(alertDialog.isShowing()).isTrue();
-
-    Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
-    assertThat(positiveButton).isNotNull();
-
-    positiveButton.performClick();
-    assertThat(alertDialog.isShowing()).isFalse();
-  }
-
-  @Test
-  public void onResumeAndWaitTimeout_shouldCallTimeoutDialog() {
-    FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
-    FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
-    spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
-
-    assertThat(fakeFragment.bCalledStopAndPop).isFalse();
-
-    ShadowLooper.getShadowMainLooper().runToEndOfTasks();
-
-    assertThat(fakeFragment.bCalledStopAndPop).isTrue();
-  }
-
-  class FakeNetworkRequestDialogFragment extends NetworkRequestDialogFragment {
-    boolean bCalledStopAndPop = false;
-
-    @Override
-    public void stopScanningAndPopTimeoutDialog() {
-      bCalledStopAndPop = true;
+    @Before
+    public void setUp() {
+        mActivity = Robolectric.setupActivity(FragmentActivity.class);
+        networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
+        mContext = spy(RuntimeEnvironment.application);
     }
-  }
 
-  @Test
-  public void onResume_shouldRegisterCallback() {
-    when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
-    Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
-    when(mContext.getApplicationContext()).thenReturn(applicationContext);
-    WifiManager wifiManager = mock(WifiManager.class);
-    when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+    @Test
+    public void display_shouldShowTheDialog() {
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog).isNotNull();
+        assertThat(alertDialog.isShowing()).isTrue();
+    }
 
-    networkRequestDialogFragment.onResume();
+    @Test
+    public void clickPositiveButton_shouldCloseTheDialog() {
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog.isShowing()).isTrue();
 
-    verify(wifiManager).registerNetworkRequestMatchCallback(any(), any());
-  }
+        Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        assertThat(positiveButton).isNotNull();
 
-  @Test
-  public void onPause_shouldUnRegisterCallback() {
-    when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
-    Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
-    when(mContext.getApplicationContext()).thenReturn(applicationContext);
-    WifiManager wifiManager = mock(WifiManager.class);
-    when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+        positiveButton.performClick();
+        assertThat(alertDialog.isShowing()).isFalse();
+    }
 
-    networkRequestDialogFragment.onPause();
+    @Test
+    public void onResumeAndWaitTimeout_shouldCallTimeoutDialog() {
+        FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
+        FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
+        spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
 
-    verify(wifiManager).unregisterNetworkRequestMatchCallback(networkRequestDialogFragment);
-  }
+        assertThat(fakeFragment.bCalledStopAndPop).isFalse();
 
-  @Test
-  public void updateAccessPointList_onUserSelectionConnectSuccess_updateCorrectly() {
-    List<AccessPoint> accessPointList = spy(new ArrayList<>());
-    Bundle bundle = new Bundle();
-    bundle.putString(KEY_SSID, "Test AP 1");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 2");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 3");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 4");
-    accessPointList.add(new AccessPoint(mContext, bundle));
+        ShadowLooper.getShadowMainLooper().runToEndOfTasks();
 
-    when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
-    networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        assertThat(fakeFragment.bCalledStopAndPop).isTrue();
+    }
 
-    // Test if config would update list.
-    WifiConfiguration config = new WifiConfiguration();
-    config.SSID = "Test AP 3";
-    networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
+    class FakeNetworkRequestDialogFragment extends NetworkRequestDialogFragment {
+        boolean bCalledStopAndPop = false;
 
-    AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
-    verify(accessPointList, times(1)).set(2, verifyAccessPoint);
-  }
+        @Override
+        public void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
+            bCalledStopAndPop = true;
+        }
+    }
 
-  @Test
-  public void updateAccessPointList_onUserSelectionConnectFailure_updateCorrectly() {
-    List<AccessPoint> accessPointList = spy(new ArrayList<>());
-    Bundle bundle = new Bundle();
-    bundle.putString(KEY_SSID, "Test AP 1");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 2");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 3");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 4");
-    accessPointList.add(new AccessPoint(mContext, bundle));
+    @Test
+    public void onResume_shouldRegisterCallback() {
+        when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
+        Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        when(mContext.getApplicationContext()).thenReturn(applicationContext);
+        WifiManager wifiManager = mock(WifiManager.class);
+        when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
 
-    when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
-    networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        networkRequestDialogFragment.onResume();
 
-    // Test if config would update list.
-    WifiConfiguration config = new WifiConfiguration();
-    config.SSID = "Test AP 3";
-    networkRequestDialogFragment.onUserSelectionConnectFailure(config);
+        verify(wifiManager).registerNetworkRequestMatchCallback(any(), any());
+    }
 
-    AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
-    verify(accessPointList, times(1)).set(2, verifyAccessPoint);
-  }
+    @Test
+    public void onPause_shouldUnRegisterCallback() {
+        when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
+        Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        when(mContext.getApplicationContext()).thenReturn(applicationContext);
+        WifiManager wifiManager = mock(WifiManager.class);
+        when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
 
-  @Test
-  public void onUserSelectionCallbackRegistration_shouldCallSelect() {
-    List<AccessPoint> accessPointList = spy(new ArrayList<>());
-    Bundle bundle = new Bundle();
-    bundle.putString(KEY_SSID, "Test AP 1");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 2");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 3");
-    AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
-    accessPointList.add(clickedAccessPoint);
-    bundle.putString(KEY_SSID, "Test AP 4");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
+        networkRequestDialogFragment.onPause();
 
-    NetworkRequestUserSelectionCallback selectionCallback = mock(
-        NetworkRequestUserSelectionCallback.class);
-    AlertDialog dialog = mock(AlertDialog.class);
-    networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
+        verify(wifiManager).unregisterNetworkRequestMatchCallback(networkRequestDialogFragment);
+    }
 
-    networkRequestDialogFragment.onClick(dialog, 2);
+    @Test
+    public void updateAccessPointList_onUserSelectionConnectSuccess_updateCorrectly() {
+        List<AccessPoint> accessPointList = spy(new ArrayList<>());
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_SSID, "Test AP 1");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 2");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 3");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 4");
+        accessPointList.add(new AccessPoint(mContext, bundle));
 
-    verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
-  }
+        when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
 
-  @Test
-  public void onMatch_shouldUpdatedList() {
-    // Prepares WifiManager.
-    when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
-    Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
-    when(mContext.getApplicationContext()).thenReturn(applicationContext);
-    WifiManager wifiManager = mock(WifiManager.class);
-    when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+        // Test if config would update list.
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "Test AP 3";
+        networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
 
-    List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
-    WifiConfiguration config = new WifiConfiguration();
-    final String SSID_AP1 = "Test AP 1";
-    config.SSID = SSID_AP1;
-    wifiConfigurationList.add(config);
-    config = new WifiConfiguration();
-    final String SSID_AP2 = "Test AP 2";
-    config.SSID = SSID_AP2;
-    wifiConfigurationList.add(config);
+        AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
+        verify(accessPointList, times(1)).set(2, verifyAccessPoint);
+    }
 
-    // Prepares callback converted data.
-    List<ScanResult> scanResults = new ArrayList<>();
-    when(wifiManager.getAllMatchingWifiConfigs(scanResults)).thenReturn(wifiConfigurationList);
+    @Test
+    public void updateAccessPointList_onUserSelectionConnectFailure_updateCorrectly() {
+        List<AccessPoint> accessPointList = spy(new ArrayList<>());
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_SSID, "Test AP 1");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 2");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 3");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 4");
+        accessPointList.add(new AccessPoint(mContext, bundle));
 
-    networkRequestDialogFragment.onMatch(scanResults);
+        when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
 
-    List<AccessPoint> accessPointList = networkRequestDialogFragment.getAccessPointList();
-    assertThat(accessPointList).isNotEmpty();
-    assertThat(accessPointList.size()).isEqualTo(2);
-    assertThat(accessPointList.get(0).getSsid()).isEqualTo(SSID_AP1);
-    assertThat(accessPointList.get(1).getSsid()).isEqualTo(SSID_AP2);
-  }
+        // Test if config would update list.
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "Test AP 3";
+        networkRequestDialogFragment.onUserSelectionConnectFailure(config);
+
+        AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
+        verify(accessPointList, times(1)).set(2, verifyAccessPoint);
+    }
+
+    @Test
+    public void onUserSelectionCallbackRegistration_shouldCallSelect() {
+        List<AccessPoint> accessPointList = spy(new ArrayList<>());
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_SSID, "Test AP 1");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 2");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 3");
+        AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
+        accessPointList.add(clickedAccessPoint);
+        bundle.putString(KEY_SSID, "Test AP 4");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
+
+        NetworkRequestUserSelectionCallback selectionCallback = mock(
+                NetworkRequestUserSelectionCallback.class);
+        AlertDialog dialog = mock(AlertDialog.class);
+        networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
+
+        networkRequestDialogFragment.onClick(dialog, 2);
+
+        verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
+    }
+
+    @Test
+    public void onMatch_shouldUpdatedList() {
+        // Prepares WifiManager.
+        when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
+        Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        when(mContext.getApplicationContext()).thenReturn(applicationContext);
+        WifiManager wifiManager = mock(WifiManager.class);
+        when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+
+        List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
+        WifiConfiguration config = new WifiConfiguration();
+        final String SSID_AP1 = "Test AP 1";
+        config.SSID = SSID_AP1;
+        wifiConfigurationList.add(config);
+        config = new WifiConfiguration();
+        final String SSID_AP2 = "Test AP 2";
+        config.SSID = SSID_AP2;
+        wifiConfigurationList.add(config);
+
+        // Prepares callback converted data.
+        List<ScanResult> scanResults = new ArrayList<>();
+        when(wifiManager.getAllMatchingWifiConfigs(scanResults)).thenReturn(wifiConfigurationList);
+
+        networkRequestDialogFragment.onMatch(scanResults);
+
+        List<AccessPoint> accessPointList = networkRequestDialogFragment.getAccessPointList();
+        assertThat(accessPointList).isNotEmpty();
+        assertThat(accessPointList.size()).isEqualTo(2);
+        assertThat(accessPointList.get(0).getSsid()).isEqualTo(SSID_AP1);
+        assertThat(accessPointList.get(1).getSsid()).isEqualTo(SSID_AP2);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestErrorDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestErrorDialogFragmentTest.java
new file mode 100644
index 0000000..c6659a5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestErrorDialogFragmentTest.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.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.internal.verification.VerificationModeFactory.times;
+
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.widget.Button;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
+public class NetworkRequestErrorDialogFragmentTest {
+
+    private FragmentActivity mActivity;
+    private NetworkRequestErrorDialogFragment mFragment;
+
+    @Before
+    public void setUp() {
+        mActivity = Robolectric.setupActivity(FragmentActivity.class);
+        mFragment = spy(NetworkRequestErrorDialogFragment.newInstance());
+        mFragment.show(mActivity.getSupportFragmentManager(), null);
+    }
+
+    @Test
+    public void display_shouldShowTimeoutDialog() {
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+
+        assertThat(alertDialog).isNotNull();
+        assertThat(alertDialog.isShowing()).isTrue();
+
+        ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
+        assertThat(RuntimeEnvironment.application
+                .getString(R.string.network_connection_timeout_dialog_message))
+                .isEqualTo(shadowAlertDialog.getMessage());
+    }
+
+    @Test
+    public void display_shouldShowAbortDialog() {
+        mFragment = spy(NetworkRequestErrorDialogFragment.newInstance());
+        Bundle bundle = new Bundle();
+        bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE,
+                ERROR_DIALOG_TYPE.ABORT);
+        mFragment.setArguments(bundle);
+        mFragment.show(mActivity.getSupportFragmentManager(), null);
+
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+
+        assertThat(alertDialog).isNotNull();
+        assertThat(alertDialog.isShowing()).isTrue();
+
+        ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
+        assertThat(RuntimeEnvironment.application
+                .getString(R.string.network_connection_errorstate_dialog_message))
+                .isEqualTo(shadowAlertDialog.getMessage());
+    }
+
+    @Test
+    public void clickPositiveButton_shouldCallStartScanningDialog() {
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog.isShowing()).isTrue();
+
+        Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        assertThat(positiveButton).isNotNull();
+
+        positiveButton.performClick();
+        verify(mFragment, times(1)).startScanningDialog();
+    }
+
+    @Test
+    public void clickNegativeButton_shouldCloseTheDialog() {
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog.isShowing()).isTrue();
+
+        Button negativeButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
+        assertThat(negativeButton).isNotNull();
+
+        negativeButton.performClick();
+        assertThat(alertDialog.isShowing()).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragmentTest.java
deleted file mode 100644
index ed28e60..0000000
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragmentTest.java
+++ /dev/null
@@ -1,90 +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.wifi;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.internal.verification.VerificationModeFactory.times;
-
-import android.content.DialogInterface;
-import android.widget.Button;
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.FragmentActivity;
-import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
-import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
-public class NetworkRequestTimeoutDialogFragmentTest {
-
-  private FragmentActivity mActivity;
-  private NetworkRequestTimeoutDialogFragment mFragment;
-
-  @Before
-  public void setUp() {
-    mActivity = Robolectric.setupActivity(FragmentActivity.class);
-    mFragment = spy(NetworkRequestTimeoutDialogFragment.newInstance());
-    mFragment.show(mActivity.getSupportFragmentManager(), null);
-  }
-
-  @Test
-  public void display_shouldShowTheDialog() {
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-
-    assertThat(alertDialog).isNotNull();
-    assertThat(alertDialog.isShowing()).isTrue();
-
-    ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
-    assertThat(RuntimeEnvironment.application
-        .getString(R.string.network_connection_timeout_dialog_message))
-        .isEqualTo(shadowAlertDialog.getMessage());
-  }
-
-  @Test
-  public void clickPositiveButton_shouldCallStartScanningDialog() {
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-    assertThat(alertDialog.isShowing()).isTrue();
-
-    Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
-    assertThat(positiveButton).isNotNull();
-
-    positiveButton.performClick();
-    verify(mFragment, times(1)).startScanningDialog();
-  }
-
-  @Test
-  public void clickNegativeButton_shouldCloseTheDialog() {
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-    assertThat(alertDialog.isShowing()).isTrue();
-
-    Button negativeButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
-    assertThat(negativeButton).isNotNull();
-
-    negativeButton.performClick();
-    assertThat(alertDialog.isShowing()).isFalse();
-  }
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
index 5ac25ed..cdd1664 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
@@ -53,14 +53,17 @@
 
     private Context mContext;
 
+    private WifiManager mWifiManager;
     private WifiSlice mWifiSlice;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
+        mWifiManager = mContext.getSystemService(WifiManager.class);
 
         // Set-up specs for SliceMetadata.
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+        mWifiManager.setWifiEnabled(true);
 
         mWifiSlice = new WifiSlice(mContext);
     }
@@ -83,13 +86,30 @@
     }
 
     @Test
-    public void getWifiSlice_noAp_shouldReturnPlaceholder() {
+    public void getWifiSlice_wifiOff_shouldReturnSingleRow() {
+        mWifiManager.setWifiEnabled(false);
+
         final Slice wifiSlice = mWifiSlice.getSlice();
 
-        int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
+        final int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
                 null /* nonHints */).size();
+
+        // Title row
+        assertThat(rows).isEqualTo(1);
+    }
+
+    @Test
+    public void getWifiSlice_noAp_shouldReturnLoadingRow() {
+        final Slice wifiSlice = mWifiSlice.getSlice();
+
+        final int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
+                null /* nonHints */).size();
+        final List<SliceItem> sliceItems = wifiSlice.getItems();
+
         // All AP rows + title row
         assertThat(rows).isEqualTo(DEFAULT_EXPANDED_ROW_COUNT + 1);
+        // Has scanning text
+        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.wifi_empty_list_wifi_on));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index d39b55f..eab9e51 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -17,12 +17,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
@@ -67,11 +69,10 @@
 import com.android.settings.testutils.shadow.ShadowBidiFormatter;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.AccessPoint;
 
@@ -142,7 +143,7 @@
     private ImageView mockHeaderIcon;
 
     @Mock
-    private ActionButtonPreference mockButtonsPref;
+    private ActionButtonsPreference mockButtonsPref;
     @Mock
     private Preference mockSignalStrengthPref;
     @Mock
@@ -247,7 +248,7 @@
                 .thenReturn(mockNetworkInfo);
         doNothing().when(mockConnectivityManager).registerNetworkCallback(
                 nullable(NetworkRequest.class), mCallbackCaptor.capture(), nullable(Handler.class));
-        mockButtonsPref = ActionButtonPreferenceTest.createMock();
+        mockButtonsPref = createMock();
         when(mockButtonsPref.setButton1OnClickListener(mForgetClickListener.capture()))
                 .thenReturn(mockButtonsPref);
 
@@ -849,4 +850,27 @@
         verify(mockAccessPoint, times(2)).getLevel();
         verify(mockIconInjector, times(2)).getIcon(anyInt());
     }
+
+    private ActionButtonsPreference createMock() {
+        final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+        when(pref.setButton1Text(anyInt())).thenReturn(pref);
+        when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton2Text(anyInt())).thenReturn(pref);
+        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton3Text(anyInt())).thenReturn(pref);
+        when(pref.setButton3Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        return pref;
+    }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
index 208c344..70e9587 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -35,43 +35,42 @@
             new ActivityTestRule<>(WifiDppConfiguratorActivity.class);
 
     @Test
-    public void launchActivity_modeQrCodeScanner_shouldNotAutoFinish() {
-        Intent intent = new Intent();
-        intent.putExtra(WifiDppConfiguratorActivity.EXTRA_LAUNCH_MODE,
-                WifiDppConfiguratorActivity.LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode());
+    public void launchActivity_qrCodeScanner_shouldNotAutoFinish() {
+        Intent intent = new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+
         mActivityRule.launchActivity(intent);
 
         assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
     }
 
     @Test
-    public void launchActivity_modeQrCodeGenerator_shouldNotAutoFinish() {
-        Intent intent = new Intent();
-        intent.putExtra(WifiDppConfiguratorActivity.EXTRA_LAUNCH_MODE,
-                WifiDppConfiguratorActivity.LaunchMode.LAUNCH_MODE_QR_CODE_GENERATOR.getMode());
+    public void launchActivity_qrCodeGenerator_shouldNotAutoFinish() {
+        Intent intent = new Intent(
+                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+
         mActivityRule.launchActivity(intent);
 
         assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
     }
 
     @Test
-    public void launchActivity_modeChooseSavedWifiNetwork_shouldNotAutoFinish() {
-        Intent intent = new Intent();
-        intent.putExtra(WifiDppConfiguratorActivity.EXTRA_LAUNCH_MODE,
-                WifiDppConfiguratorActivity.LaunchMode
-                .LAUNCH_MODE_CHOOSE_SAVED_WIFI_NETWORK.getMode());
+    public void launchActivity_chooseSavedWifiNetwork_shouldNotAutoFinish() {
+        Intent intent = new Intent(
+                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK);
+
         mActivityRule.launchActivity(intent);
 
         assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
     }
 
     @Test
-    public void launchActivity_noLaunchMode_shouldFinishActivityWithResultCodeCanceled() {
-        // If we do not specify launch mode, the activity will finish itself right away
-        Intent intent = new Intent();
-        mActivityRule.launchActivity(intent);
+    public void testActivity_shouldImplementsWifiNetworkConfigRetriever() {
+        WifiDppConfiguratorActivity activity = mActivityRule.getActivity();
 
-        assertThat(mActivityRule.getActivityResult().getResultCode()).
-                isEqualTo(Activity.RESULT_CANCELED);
+        assertThat(activity instanceof WifiNetworkConfig.Retriever).isEqualTo(true);
     }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
index c46db2c..98742ed 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
@@ -28,6 +28,8 @@
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.settings.R;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -41,21 +43,13 @@
 
     @Before
     public void setUp() {
-        Intent intent = new Intent();
-        intent.putExtra(WifiDppConfiguratorActivity.EXTRA_LAUNCH_MODE,
-                WifiDppConfiguratorActivity.LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode());
+        Intent intent = new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
         mActivityRule.launchActivity(intent);
     }
 
     @Test
-    public void leftButton_shouldFinishActivityWithResultCodeCanceled() {
-        onView(withText("Cancel")).perform(click());
-
-        assertThat(mActivityRule.getActivityResult().getResultCode()).
-                isEqualTo(Activity.RESULT_CANCELED);
-    }
-
-    @Test
     public void rotateScreen_shouldNotCrash() {
         mActivityRule.getActivity().setRequestedOrientation(
                 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);