Merge "Move Panel to public API"
diff --git a/Android.mk b/Android.mk
index 7eb9b6a..c99e30c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -14,7 +14,9 @@
 LOCAL_PACKAGE_NAME := Settings
 LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
+LOCAL_PRODUCT_MODULE := true
 LOCAL_PRIVILEGED_MODULE := true
+LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.settings
 LOCAL_MODULE_TAGS := optional
 LOCAL_USE_AAPT2 := true
 
@@ -70,4 +72,4 @@
 # Use the following include to make our test apk.
 ifeq (,$(ONE_SHOT_MAKEFILE))
 include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
\ No newline at end of file
+endif
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index cbe4f6d..871f609 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -717,8 +717,7 @@
             android:name="Settings$ZenModeSettingsActivity"
             android:label="@string/zen_mode_settings_title"
             android:icon="@drawable/ic_notifications"
-            android:exported="true"
-            android:parentActivityName="Settings">
+            android:exported="true">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.ZEN_MODE_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -875,8 +874,7 @@
             android:name="Settings$NightDisplaySettingsActivity"
             android:label="@string/night_display_title"
             android:enabled="@*android:bool/config_nightDisplayAvailable"
-            android:icon="@drawable/ic_settings_night_display"
-            android:parentActivityName="Settings">
+            android:icon="@drawable/ic_settings_night_display">
             <intent-filter android:priority="32">
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.SHORTCUT" />
@@ -1626,7 +1624,7 @@
             android:icon="@drawable/ic_settings_security">
             <intent-filter android:priority="1">
                 <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.LOCK_SCREEN" />
+                <category android:name="com.android.settings.suggested.category.DEFAULT" />
             </intent-filter>
             <meta-data android:name="com.android.settings.title"
                        android:resource="@string/suggested_lock_settings_title" />
@@ -2821,10 +2819,8 @@
             android:name=".Settings$AppAndNotificationDashboardActivity"
             android:label="@string/app_and_notification_dashboard_title"
             android:icon="@drawable/ic_homepage_apps"
-            android:parentActivityName="Settings">
-            <intent-filter>
-                <action android:name="com.android.settings.action.SETTINGS"/>
-            </intent-filter>
+            android:parentActivityName="Settings"
+            android:exported="true">
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                        android:value="com.android.settings.applications.AppAndNotificationDashboardFragment"/>
         </activity>
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 6ead46e..93445f9 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -46,6 +46,7 @@
 
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Settings_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Settings_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/Settings)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/OWNERS b/OWNERS
index d2bc1ff..37124b2 100644
--- a/OWNERS
+++ b/OWNERS
@@ -7,8 +7,11 @@
 dehboxturtle@google.com
 dhnishi@google.com
 dling@google.com
+edgarwang@google.com
 jackqdyulei@google.com
 mfritze@google.com
+rafftsai@google.com
+tmfang@google.com
 zhfan@google.com
 
 # Emergency approvers in case the above are not available
diff --git a/res/drawable/ic_battery_saver_accent_24dp.xml b/res/drawable/ic_battery_saver_accent_24dp.xml
deleted file mode 100644
index c8def54..0000000
--- a/res/drawable/ic_battery_saver_accent_24dp.xml
+++ /dev/null
@@ -1,29 +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.
-  -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorAccent">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M15,14l-2,0l0,2l-2,0l0,-2l-2,0l0,-2l2,0l0,-2l2,0l0,2l2,0z"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M16.2,22.5H7.8c-1.3,0 -2.3,-1 -2.3,-2.3V5.8c0,-1.3 1,-2.3 2.3,-2.3h0.7v-2h7v2h0.7c1.3,0 2.3,1.1 2.3,2.3v14.3C18.5,21.5 17.5,22.5 16.2,22.5zM7.8,5.5c-0.2,0 -0.3,0.2 -0.3,0.3v14.3c0,0.2 0.2,0.3 0.3,0.3h8.3c0.2,0 0.3,-0.1 0.3,-0.3V5.8c0,-0.2 -0.1,-0.3 -0.3,-0.3h-2.7v-2h-3v2H7.8z"/>
-</vector>
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
index 0c938f8..4217867 100644
--- a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -24,28 +24,24 @@
 
     <include layout="@layout/wifi_dpp_fragment_header"/>
 
-    <FrameLayout
+    <com.android.settings.wifi.qrcode.QrPreviewLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-        <SurfaceView
+        android:layout_height="match_parent"
+        android:layout_gravity="center">
+        <TextureView
             android:id="@+id/preview_view"
-            android:layout_width="426dp"
-            android:layout_height="320dp"
-            android:layout_gravity="center"/>
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"/>
         <com.android.settings.wifi.qrcode.QrDecorateView
             android:id="@+id/decorate_view"
-            android:layout_width="426dp"
-            android:layout_height="320dp"
-            android:layout_gravity="center"/>
-    </FrameLayout>
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"/>
+    </com.android.settings.wifi.qrcode.QrPreviewLayout>
 
     <TextView android:id="@+id/error_message"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"/>
 
-    <include layout="@layout/wifi_dpp_fragment_footer"
-        android:gravity="center|bottom"/>
-
 </LinearLayout>
 
diff --git a/res/layout/face_enroll_accessibility_toggle.xml b/res/layout/face_enroll_accessibility_toggle.xml
new file mode 100644
index 0000000..4dda2a7
--- /dev/null
+++ b/res/layout/face_enroll_accessibility_toggle.xml
@@ -0,0 +1,46 @@
+<?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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingEnd="16dp"
+    android:paddingStart="16dp">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/title"/>
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+    <View
+        android:layout_width="1dp"
+        android:layout_height="match_parent"
+        android:background="?android:attr/listDivider" />
+
+    <Switch
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/toggle"
+        android:checked="true"/>
+
+</LinearLayout>
diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml
index 7a5c172..025c239 100644
--- a/res/layout/face_enroll_introduction.xml
+++ b/res/layout/face_enroll_introduction.xml
@@ -18,6 +18,7 @@
 <com.google.android.setupdesign.GlifLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:FaceEnrollAccessibilitySwitch="http://schemas.android.com/apk/res/com.android.settings"
     style="?attr/face_layout_theme"
     android:id="@+id/setup_wizard_layout"
     android:layout_width="match_parent"
@@ -59,6 +60,41 @@
 
         </com.google.android.setupdesign.view.FillContentLayout>
 
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center">
+            <Button
+                android:id="@+id/accessibility_button"
+                style="@style/SuwGlifButton.Secondary"
+                android:layout_gravity="center"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/security_settings_face_enroll_introduction_accessibility" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:id="@+id/accessibility_layout"
+                android:orientation="vertical"
+                android:visibility="invisible">
+
+                <com.android.settings.biometrics.face.FaceEnrollAccessibilityToggle
+                    android:id="@+id/toggle_diversity"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    FaceEnrollAccessibilitySwitch:messageText="@string/security_settings_face_enroll_introduction_accessibility_diversity"/>
+
+                <com.android.settings.biometrics.face.FaceEnrollAccessibilityToggle
+                    android:id="@+id/toggle_vision"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    FaceEnrollAccessibilitySwitch:messageText="@string/security_settings_face_enroll_introduction_accessibility_vision"/>
+
+            </LinearLayout>
+        </FrameLayout>
+
     </LinearLayout>
 
 </com.google.android.setupdesign.GlifLayout>
diff --git a/res/layout/face_enroll_introduction_footer.xml b/res/layout/face_enroll_introduction_footer.xml
index d73a8ed..15993f0 100644
--- a/res/layout/face_enroll_introduction_footer.xml
+++ b/res/layout/face_enroll_introduction_footer.xml
@@ -39,6 +39,6 @@
         style="@style/SuwGlifButton.Primary"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="@string/suw_next_button_label" />
+        android:text="@string/wizard_next" />
 
 </com.google.android.setupdesign.view.ButtonBarLayout>
diff --git a/res/layout/fingerprint_enroll_introduction_footer.xml b/res/layout/fingerprint_enroll_introduction_footer.xml
index 1298d82..47d7657 100644
--- a/res/layout/fingerprint_enroll_introduction_footer.xml
+++ b/res/layout/fingerprint_enroll_introduction_footer.xml
@@ -39,6 +39,6 @@
         style="@style/SuwGlifButton.Primary"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="@string/suw_next_button_label" />
+        android:text="@string/wizard_next" />
 
 </com.google.android.setupdesign.view.ButtonBarLayout>
diff --git a/res/layout/homepage_condition_half_tile.xml b/res/layout/homepage_condition_half_tile.xml
index eff167a..895183f 100644
--- a/res/layout/homepage_condition_half_tile.xml
+++ b/res/layout/homepage_condition_half_tile.xml
@@ -25,38 +25,44 @@
         android:id="@+id/content"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingStart="@dimen/homepage_card_padding_start"
-        android:paddingEnd="@dimen/homepage_card_padding_end"
         android:paddingTop="@dimen/homepage_condition_half_card_padding_top"
         android:orientation="vertical">
 
-        <ImageView
-            android:id="@android:id/icon"
-            android:layout_width="@dimen/homepage_card_icon_size"
-            android:layout_height="@dimen/homepage_card_icon_size"
-            android:tint="?android:attr/colorAccent"/>
-
-        <TextView
-            android:id="@android:id/title"
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:maxLines="1"
-            android:ellipsize="end"
-            android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
-            android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
-            style="@style/TextAppearance.ConditionCardTitle"/>
+            android:paddingStart="@dimen/homepage_card_padding_start"
+            android:paddingEnd="@dimen/homepage_card_padding_end"
+            android:orientation="vertical">
 
-        <TextView
-            android:id="@android:id/summary"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:maxLines="1"
-            android:ellipsize="end"
-            android:layout_marginBottom="@dimen/homepage_condition_half_card_summary_margin_bottom"
-            style="@style/TextAppearance.ConditionCardSummary"/>
+            <ImageView
+                android:id="@android:id/icon"
+                android:layout_width="@dimen/homepage_card_icon_size"
+                android:layout_height="@dimen/homepage_card_icon_size"
+                android:tint="?android:attr/colorAccent"/>
 
-        <include layout="@layout/horizontal_divider"/>
+            <TextView
+                android:id="@android:id/title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:maxLines="1"
+                android:ellipsize="end"
+                android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
+                android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
+                style="@style/TextAppearance.ConditionCardTitle"/>
 
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:maxLines="1"
+                android:ellipsize="end"
+                android:layout_marginBottom="@dimen/homepage_condition_half_card_summary_margin_bottom"
+                style="@style/TextAppearance.ConditionCardSummary"/>
+
+            <include layout="@layout/horizontal_divider"/>
+
+        </LinearLayout>
         <Button
             android:id="@+id/first_action"
             android:layout_width="match_parent"
diff --git a/res/layout/preference_app_restrictions.xml b/res/layout/preference_app_restrictions.xml
index 4bb6fe2..65fd06c 100644
--- a/res/layout/preference_app_restrictions.xml
+++ b/res/layout/preference_app_restrictions.xml
@@ -39,11 +39,11 @@
             android:orientation="horizontal">
             <ImageView
                 android:id="@android:id/icon"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
+                android:layout_width="@dimen/secondary_app_icon_size"
+                android:layout_height="@dimen/secondary_app_icon_size"
                 android:layout_gravity="center"
-                android:minWidth="48dp"
-                android:scaleType="centerInside"
+                android:minWidth="@dimen/secondary_app_icon_size"
+                android:scaleType="fitCenter"
                 android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"
                  />
         </LinearLayout>
diff --git a/res/layout/search_bar.xml b/res/layout/search_bar.xml
index be8aa3b..fe2f270 100644
--- a/res/layout/search_bar.xml
+++ b/res/layout/search_bar.xml
@@ -43,5 +43,6 @@
         android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
         android:layout_width="@dimen/search_bar_avatar_size"
         android:layout_height="@dimen/search_bar_avatar_size"
-        android:layout_gravity="end|center_vertical"/>
+        android:layout_gravity="end|center_vertical"
+        android:contentDescription="@string/search_bar_account_avatar_content_description"/>
 </com.google.android.material.card.MaterialCardView>
diff --git a/res/layout/slice_preference_layout.xml b/res/layout/slice_preference_layout.xml
new file mode 100644
index 0000000..4cea9c0
--- /dev/null
+++ b/res/layout/slice_preference_layout.xml
@@ -0,0 +1,29 @@
+<?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.
+  -->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+    <androidx.slice.widget.SliceView
+        android:id="@+id/slice_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+</FrameLayout>
diff --git a/res/layout/storage_wizard_footer.xml b/res/layout/storage_wizard_footer.xml
index 0ff40aa..a4cda18 100644
--- a/res/layout/storage_wizard_footer.xml
+++ b/res/layout/storage_wizard_footer.xml
@@ -27,7 +27,7 @@
         android:layout_height="wrap_content"
         android:onClick="onNavigateBack"
         android:visibility="gone"
-        android:text="@string/suw_back_button_label" />
+        android:text="@string/wizard_back" />
 
     <Space
         android:layout_width="0dp"
@@ -41,6 +41,6 @@
         android:layout_height="wrap_content"
         android:onClick="onNavigateNext"
         android:visibility="gone"
-        android:text="@string/suw_next_button_label" />
+        android:text="@string/wizard_next" />
 
 </LinearLayout>
diff --git a/res/layout/wifi_dpp_activity.xml b/res/layout/wifi_dpp_activity.xml
index a833dcc..cb82f66 100644
--- a/res/layout/wifi_dpp_activity.xml
+++ b/res/layout/wifi_dpp_activity.xml
@@ -22,12 +22,6 @@
     android:layout_height="match_parent"
     android:orientation="vertical">
 
-    <ImageView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:src="@drawable/ic_wifi_signal_4"
-        android:layout_gravity="center"/>
-
     <LinearLayout
         android:id="@+id/fragment_container"
         android:layout_width="match_parent"
diff --git a/res/layout/wifi_dpp_fragment_header.xml b/res/layout/wifi_dpp_fragment_header.xml
index 99b246f..266a3e8 100644
--- a/res/layout/wifi_dpp_fragment_header.xml
+++ b/res/layout/wifi_dpp_fragment_header.xml
@@ -17,18 +17,42 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/EntityHeader"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical">
+    android:layout_centerHorizontal="true"
+    android:gravity="center_horizontal"
+    android:orientation="vertical"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp">
 
-    <TextView android:id="@+id/title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"/>
+    <ImageView
+        android:id="@+id/header_icon"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:scaleType="fitCenter"/>
 
-    <TextView android:id="@+id/description"
-        android:layout_width="wrap_content"
+    <TextView
+        android:id="@+id/title"
+        style="@style/TextAppearance.EntityHeaderTitle"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center"/>
+        android:gravity="center_horizontal"
+        android:textAlignment="center"
+        android:layout_marginTop="8dp"
+        android:paddingStart="32dp"
+        android:paddingEnd="32dp"/>
+
+    <TextView
+        android:id="@+id/description"
+        style="@style/TextAppearance.EntityHeaderSummary"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="false"
+        android:gravity="center_horizontal"
+        android:textAlignment="center"
+        android:layout_marginTop="2dp"
+        android:paddingStart="32dp"
+        android:paddingEnd="32dp"/>
 
 </LinearLayout>
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 0beacff..913998f 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -24,20 +24,20 @@
 
     <include layout="@layout/wifi_dpp_fragment_header"/>
 
-    <FrameLayout
+    <com.android.settings.wifi.qrcode.QrPreviewLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-        <SurfaceView
+        android:layout_height="match_parent">
+        <TextureView
             android:id="@+id/preview_view"
-            android:layout_width="320dp"
-            android:layout_height="426dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
             android:layout_gravity="center"/>
         <com.android.settings.wifi.qrcode.QrDecorateView
             android:id="@+id/decorate_view"
-            android:layout_width="320dp"
-            android:layout_height="426dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
             android:layout_gravity="center"/>
-    </FrameLayout>
+    </com.android.settings.wifi.qrcode.QrPreviewLayout>
 
     <TextView android:id="@+id/error_message"
         android:layout_width="wrap_content"
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 86763b7..806e148 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -52,6 +52,8 @@
 
     <attr name="apnPreferenceStyle" format="reference" />
 
+    <attr name="slicePreferenceStyle" format="reference" />
+
     <attr name="footerPreferenceStyle" format="reference" />
 
     <declare-styleable name="FixedLineSummaryPreference">
@@ -144,6 +146,11 @@
         <attr name="thickness" format="dimension" />
     </declare-styleable>
 
+    <!-- For Face enroll accessibility toggle -->
+    <declare-styleable name="FaceEnrollAccessibilityToggle">
+        <attr name="messageText" format="reference" />
+    </declare-styleable>
+
     <!-- For TwoStatesButtonPreference -->
     <declare-styleable name="TwoStateButtonPreference">
         <attr name="textOn" format="reference" />
diff --git a/res/values/bools.xml b/res/values/bools.xml
index 8bd11c7..a5043a2 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -168,6 +168,15 @@
     <!-- Whether device_model should be shown or not. -->
     <bool name="config_show_device_model">true</bool>
 
+    <!-- Whether top_level_battery should be shown or not. -->
+    <bool name="config_show_top_level_battery">true</bool>
+
+    <!-- Whether top_level_connected_devices should be shown or not. -->
+    <bool name="config_show_top_level_connected_devices">true</bool>
+
+    <!-- Whether top_level_display should be shown or not. -->
+    <bool name="config_show_top_level_display">true</bool>
+
     <!-- Whether wifi_ip_address should be shown or not. -->
     <bool name="config_show_wifi_ip_address">true</bool>
 
diff --git a/res/values/config.xml b/res/values/config.xml
index edd948f7..7108cbd 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -165,4 +165,7 @@
 
     <!-- Email address for the homepage contextual cards feedback -->
     <string name="config_contextual_card_feedback_email" translatable="false"></string>
+
+    <!-- Uri that represents extra bluetooth settings -->
+    <string name="config_bluetooth_device_settings_uri" translatable="false">content://com.google.android.gms.nearby.fastpair/settings_slice?addr=<xliff:g id="mac_address">%1$s</xliff:g></string>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6aacb0a..da05a41 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -798,6 +798,17 @@
     <string name="lockdown_settings_title">Show lockdown option</string>
     <!-- Text shown for the description of the lockdown option -->
     <string name="lockdown_settings_summary">Display power button option that turns off Smart Lock, fingerprint unlocking, and notifications on the lock screen</string>
+
+    <!-- Text shown for the title of the extend unlock mode option for trust agents [CHAR LIMIT=40] -->
+    <string name="trust_agents_extend_unlock_title">SmartLock only extends unlock</string>
+    <!-- Text shown for the description of the extend unlock mode option [CHAR LIMIT=NONE] -->
+    <string name="trust_agents_extend_unlock_summary">If enabled, SmartLock will keep your device unlocked for longer, but can no longer unlock a locked device.</string>
+
+    <!-- Text shown for the title of the lock when trust lost option [CHAR LIMIT=40] -->
+    <string name="trust_lost_locks_screen_title">Lock screen when trust is lost</string>
+    <!-- Text shown for the description of the lock when trust lost option [CHAR LIMIT=NONE -->
+    <string name="trust_lost_locks_screen_summary">If enabled, the device will lock when the last trust agent loses trust</string>
+
     <!-- Text shown for summary of owner info setting (if none set) [CHAR LIMIT=40]-->
     <string name="owner_info_settings_summary">None</string>
     <!-- Description of how many characters are used in owner info [CHAR LIMIT=40]-->
@@ -816,8 +827,15 @@
     <string name="location_settings_title">Location</string>
     <!-- Used in the location settings to control turning on/off the feature entirely -->
     <string name="location_settings_master_switch_title">Use location</string>
-    <!-- Summary for Location settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
-    <string name="location_settings_summary">Scanning, location history</string>
+    <!-- Summary for Location settings when location is off [CHAR LIMIT=NONE] -->
+    <string name="location_settings_summary_location_off">Off</string>
+    <!-- Summary for Location settings when location is on, explaining how many apps have location permission [CHAR LIMIT=NONE]-->
+    <plurals name="location_settings_summary_location_on">
+        <item quantity="one">On - <xliff:g id="count">%1$d</xliff:g> app can access location</item>
+        <item quantity="other">On - <xliff:g id="count">%1$d</xliff:g> apps can access location</item>
+    </plurals>
+    <!-- Location settings, loading the number of apps which have location permission [CHAR LIMIT=30] -->
+    <string name="location_settings_loading_app_permission_stats">Loading\u2026</string>
 
     <!-- Main Settings screen setting option title for the item to take you to the accounts screen [CHAR LIMIT=22] -->
     <string name="account_settings_title">Accounts</string>
@@ -859,6 +877,12 @@
     <string name="security_settings_face_preference_summary_none">Tap to set up face authentication</string>
     <!-- Title shown for menu item that launches face settings or enrollment. [CHAR LIMIT=32] -->
     <string name="security_settings_face_preference_title">Face authentication</string>
+    <!-- Button shown which shows accessibility toggles for face enrollment when clicked. [CHAR LIMIT=32] -->
+    <string name="security_settings_face_enroll_introduction_accessibility">Use accessibility setup</string>
+    <!-- Message shown for a toggle which when disabled, allows the user to enroll using a simpler flow for accessibility [CHAR LIMIT=NONE] -->
+    <string name="security_settings_face_enroll_introduction_accessibility_diversity"></string>
+    <!-- Message shown for a toggle which when disabled, allows the user to enroll using a simpler flow for accessibility [CHAR LIMIT=NONE] -->
+    <string name="security_settings_face_enroll_introduction_accessibility_vision"></string>
     <!-- Button text to cancel enrollment from the introduction [CHAR LIMIT=22] -->
     <string name="security_settings_face_enroll_introduction_cancel">Cancel</string>
     <!-- Introduction title shown in face enrollment to introduce the face unlock feature [CHAR LIMIT=40] -->
@@ -2060,6 +2084,8 @@
     <string name="wifi_dpp_scan_qr_code">Scan QR code</string>
     <!-- Hint for the user to center another device's QR code in the below camera window [CHAR LIMIT=NONE] -->
     <string name="wifi_dpp_scan_qr_code_join_network">Join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d by scanning a QR code</string>
+    <!-- Hint for the user to center another device's QR code in the below camera window [CHAR LIMIT=NONE] -->
+    <string name="wifi_dpp_scan_qr_code_join_unknown_network">Join Wi\u2011Fi by scanning a QR code</string>
     <!-- Title for the fragment to share Wi-Fi [CHAR LIMIT=50]  -->
     <string name="wifi_dpp_share_wifi">Share Wi\u2011Fi</string>
     <!-- Hint for the user to use another device to scan QR code on screen to join Wi-Fi [CHAR LIMIT=NONE] -->
@@ -3617,15 +3643,28 @@
     <string name="managed_profile_location_switch_title">Location for work profile</string>
     <!-- [CHAR LIMIT=30] Location settings screen. It's a link that directs the user to a page that
       shows the location permission setting for each installed app -->
-    <string name="location_app_level_permissions">App-level permissions</string>
-    <!-- [CHAR LIMIT=42] Location settings screen, sub category for recent location requests -->
-    <string name="location_category_recent_location_requests">Recent location requests</string>
-    <!-- Location settings screen, displayed when there're more than three recent location requests -->
-    <string name="location_recent_location_requests_see_all">See all</string>
+    <string name="location_app_level_permissions">App permission</string>
+    <!-- Summary for app permission on Location settings page when location is off [CHAR LIMIT=NONE] -->
+    <string name="location_app_permission_summary_location_off">Location is off</string>
+    <!-- Summary for Location settings when location is on, explaining how many apps have location permission [CHAR LIMIT=NONE]-->
+    <plurals name="location_app_permission_summary_location_on">
+        <item quantity="one">
+            <xliff:g id="background_location_app_count">%1$d</xliff:g>
+            of
+            <xliff:g id="total_location_app_count">%2$d</xliff:g>
+            app has unlimited access</item>
+        <item quantity="other">
+            <xliff:g id="background_location_app_count">%1$d</xliff:g>
+            of
+            <xliff:g id="total_location_app_count">%2$d</xliff:g>
+            apps have unlimited access</item>
+    </plurals>
+    <!-- [CHAR LIMIT=50] Location settings screen, sub category for recent location access -->
+    <string name="location_category_recent_location_access">Recent location access</string>
+    <!-- [CHAR LIMIT=30] Location settings screen, button to bring the user to view the details of recent location access -->
+    <string name="location_recent_location_access_view_details">View details</string>
     <!-- Location settings screen, displayed when there's no recent app accessing location -->
     <string name="location_no_recent_apps">No apps have requested location recently</string>
-    <!-- [CHAR LIMIT=30] Location settings screen, sub category for location services -->
-    <string name="location_category_location_services">Location services</string>
     <!-- [CHAR LIMIT=30] Location settings screen, recent location requests high battery use-->
     <string name="location_high_battery_use">High battery use</string>
     <!-- [CHAR LIMIT=30] Location settings screen, recent location requests low battery use-->
@@ -6733,7 +6772,7 @@
     <string name="wizard_back">Back</string>
     <!-- Wizard next button label [CHAR LIMIT=25] -->
     <string name="wizard_next">Next</string>
-    <!-- Wizard next button label [CHAR LIMIT=25] -->
+    <!-- Wizard finish button label [CHAR LIMIT=25] -->
     <string name="wizard_finish">Finish</string>
 
     <!-- An option in a photo selection dialog, if there is no photo yet [CHAR LIMIT=50] -->
@@ -6930,6 +6969,8 @@
     <string name="keywords_sim_status">network, mobile network state, service state, signal strength, mobile network type, roaming, iccid</string>
     <string name="keywords_model_and_hardware">serial number, hardware version</string>
     <string name="keywords_android_version">android security patch level, baseband version, kernel version</string>
+    <!--Search keywords for financial apps sms access settings -->
+    <string name="keywords_financial_apps_sms_access">financial app, sms, permission</string>
 
     <!-- Search keyword for Device Theme Settings [CHAR LIMIT=NONE] -->
     <string name="keywords_systemui_theme">dark theme</string>
@@ -8820,6 +8861,10 @@
     <!-- Summary of number of apps currently can write system settings [CHAR LIMIT=60] -->
     <string name="write_settings_summary"><xliff:g id="count" example="10">%1$d</xliff:g> of <xliff:g id="count" example="10">%2$d</xliff:g> apps allowed to modify system settings</string>
 
+    <!-- Settings title in main settings screen for financial apps sms access [CHAR LIMIT=60] -->
+    <string name="financial_apps_sms_access_title">Financial Apps Sms Access</string>
+    <!-- Preference key for financial apps sms access screen -->
+    <string name="financial_sms_root_screen_key" translatable="false">financial_sms_root_screen_key</string>
     <!-- Label for showing apps that can install other apps [CHAR LIMIT=45] -->
     <string name="filter_install_sources_apps">Can install other apps</string>
     <!-- Label for showing apps that can write system settings [CHAR LIMIT=45] -->
@@ -9008,12 +9053,6 @@
     <!-- Summary of condition that do not disturb is on [CHAR LIMIT=36] -->
     <string name="condition_zen_summary">Impacts what you hear and see</string>
 
-    <!-- Title of condition that battery saver is on [CHAR LIMIT=30] -->
-    <string name="condition_battery_title">Battery Saver is on</string>
-
-    <!-- Summary of condition that battery saver is on [CHAR LIMIT=NONE] -->
-    <string name="condition_battery_summary">Features restricted</string>
-
     <!-- Title of condition that cellular data is off [CHAR LIMIT=50] -->
     <string name="condition_cellular_title">Mobile data is off</string>
 
@@ -10332,4 +10371,11 @@
     <string name="contextual_card_feedback_send">Send feedback</string>
     <!-- String for contextual card feedback dialog [CHAR LIMIT=NONE] -->
     <string name="contextual_card_feedback_confirm_message">Would you like to give us feedback on this suggestion?</string>
+
+    <!-- Toast message for copy action of Copyable Slice [CHAR LIMIT=NONE] -->
+    <string name="copyable_slice_toast"><xliff:g id="copy_content" example="Phone number">%1$s</xliff:g> copied to clipboard.</string>
+
+    <!-- String for talkback on the account avatar of the search bar.  [CHAR LIMIT=NONE] -->
+    <string name="search_bar_account_avatar_content_description"></string>
+
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 19ce333..15ec46d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -476,6 +476,7 @@
     <style name="ConditionHalfCardBorderlessButton"
            parent="@style/ConditionCardBorderlessButton">
         <item name="android:textAlignment">viewStart</item>
+        <item name="android:layout_marginStart">4dp</item>
     </style>
 
     <style name="ConditionFullCardBorderlessButton"
@@ -488,4 +489,8 @@
         <item name="android:textAllCaps">false</item>
     </style>
 
+    <style name="Widget.SliceView.Settings">
+        <item name="titleSize">@*android:dimen/text_size_subhead_material</item>
+    </style>
+
 </resources>
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index 0f7ecab..f25289d 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -21,6 +21,7 @@
 
     <style name="PreferenceTheme" parent="@style/PreferenceThemeOverlay.SettingsBase">
         <item name="apnPreferenceStyle">@style/ApnPreference</item>
+        <item name="slicePreferenceStyle">@style/SlicePreference</item>
         <item name="seekBarPreferenceStyle">@style/SettingsSeekBarPreference</item>
         <item name="twoStateButtonPreferenceStyle">@style/TwoStateButtonPreference</item>
     </style>
@@ -34,6 +35,10 @@
         <item name="android:layout">@layout/apn_preference_layout</item>
     </style>
 
+    <style name="SlicePreference" parent="@style/Preference.Material">
+        <item name="android:layout">@layout/slice_preference_layout</item>
+    </style>
+
     <style name="SettingsSeekBarPreference" parent="@style/Preference.Material">
         <item name="android:layout">@layout/preference_widget_seekbar_settings</item>
     </style>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 9a05bfc..f22d111 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -32,9 +32,13 @@
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
         <item name="face_layout_theme">@style/FaceLayoutTheme</item>
         <item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_holo_dark</item>
+
+        <!-- For wifi icon -->
         <item name="wifi_signal">@drawable/wifi_signal</item>
         <item name="wifi_signal_color">?android:attr/colorAccent</item>
         <item name="wifi_friction">@drawable/wifi_friction</item>
+        <item name="frictionIconColor">?android:colorControlNormal</item>
+
         <item name="side_margin">@dimen/settings_side_margin</item>
         <item name="suwListItemIconColor">?android:attr/colorAccent</item>
 
@@ -58,6 +62,9 @@
         <!-- TODO(118444000): Remove colorPrimary and colorPrimaryVariant -->
         <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
         <item name="colorPrimaryVariant">@android:color/white</item>
+
+        <!-- For slice view in settings -->
+        <item name="sliceViewStyle">@style/Widget.SliceView.Settings</item>
     </style>
 
     <!-- Variant of the settings theme with no action bar. -->
@@ -71,9 +78,6 @@
         <item name="android:actionBarStyle">@style/Widget.ActionBar.SubSettings</item>
 
         <item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.Settings</item>
-
-        <!-- Friction icon color for wifi preferences -->
-        <item name="frictionIconColor">?android:colorControlNormal</item>
     </style>
 
     <style name="Theme.SubSettings" parent="Theme.SubSettings.Base"/>
@@ -202,10 +206,12 @@
         <item name="android:windowLightNavigationBar">true</item>
     </style>
 
+    <!-- Note that Dialog themes do not set list dividers -->
     <style name="Theme.BottomDialog" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog">
         <item name="android:windowBackground">@drawable/settings_panel_background</item>
         <item name="android:dividerHorizontal">@*android:drawable/list_divider_material</item>
         <item name="android:windowNoTitle">true</item>
+        <item name="android:listDivider">@*android:drawable/list_divider_material</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
     </style>
 
diff --git a/res/xml/battery_saver_settings.xml b/res/xml/battery_saver_settings.xml
index a086018..89f7eab 100644
--- a/res/xml/battery_saver_settings.xml
+++ b/res/xml/battery_saver_settings.xml
@@ -26,18 +26,6 @@
         android:title="@string/battery_saver_schedule_settings_title"
         settings:controller="com.android.settings.fuelgauge.batterysaver.BatterySaverSchedulePreferenceController"/>
 
-    <!-- Turn on automatically -->
-    <SwitchPreference
-        android:key="auto_battery_saver"
-        android:title="@string/battery_saver_auto_title"
-        settings:controller="com.android.settings.fuelgauge.batterysaver.AutoBatterySaverPreferenceController" />
-
-    <com.android.settings.widget.SeekBarPreference
-        android:key="battery_saver_seek_bar"
-        android:title="@string/battery_saver_seekbar_title_placeholder"
-        android:max="15"
-        android:min="1" />
-
     <com.android.settings.widget.TwoStateButtonPreference
         android:key="battery_saver"
         android:title="@string/battery_saver"
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index 40ce93d..90895f2 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -26,7 +26,14 @@
         settings:allowDividerBelow="true"/>
 
     <com.android.settingslib.widget.ActionButtonsPreference
-        android:key="action_buttons" />
+        android:key="action_buttons"
+        settings:allowDividerBelow="true"/>
+
+    <com.android.settings.slices.SlicePreference
+        android:key="bt_device_slice"
+        settings:controller="com.android.settings.slices.SlicePreferenceController"
+        settings:allowDividerBelow="true"
+        settings:allowDividerAbove="true"/>
 
     <PreferenceCategory
         android:key="bluetooth_profiles"/>
diff --git a/res/xml/location_recent_requests_see_all.xml b/res/xml/financial_app_sms_access.xml
similarity index 64%
rename from res/xml/location_recent_requests_see_all.xml
rename to res/xml/financial_app_sms_access.xml
index 38db142..6f7ba50 100644
--- a/res/xml/location_recent_requests_see_all.xml
+++ b/res/xml/financial_app_sms_access.xml
@@ -9,16 +9,14 @@
 
      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"
-        android:title="@string/location_category_recent_location_requests"
-        android:key="recent_location_requests_see_all">
-
-        <PreferenceCategory
-            android:key="all_recent_location_requests"/>
-</PreferenceScreen>
\ No newline at end of file
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="@string/financial_sms_root_screen_key"
+    android:title="@string/financial_apps_sms_access_title"
+    settings:controller="com.android.settings.applications.specialaccess.financialapps.FinancialAppsController" />
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index b53e986..f1c13cf 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -20,21 +20,14 @@
         android:title="@string/location_settings_title"
         settings:keywords="@string/keywords_location">
 
-        <PreferenceCategory
-            android:key="recent_location_requests"
-            android:title="@string/location_category_recent_location_requests"/>
-
-        <Preference
-            android:key="recent_location_requests_see_all_button"
-            android:title="@string/location_recent_location_requests_see_all"
-            android:icon="@drawable/ic_chevron_right_24dp"
-            android:selectable="true"
-            android:fragment="com.android.settings.location.RecentLocationRequestSeeAllFragment"
-            settings:searchable="false"/>
+        <com.android.settingslib.widget.LayoutPreference
+            android:key="apps_dashboard"
+            android:layout="@layout/app_entities_header"
+            settings:allowDividerBelow="true" />
 
         <PreferenceCategory
             android:key="location_advanced_settings"
-            settings:initialExpandedChildrenCount="1">
+            settings:initialExpandedChildrenCount="0">
 
             <!-- This preference category gets removed if new_recent_location_ui is disabled -->
             <Preference
@@ -60,8 +53,7 @@
                 android:selectable="true" />
 
             <PreferenceCategory
-                android:key="location_services"
-                android:title="@string/location_category_location_services"/>
+                android:key="location_services" />
         </PreferenceCategory>
 
         <PreferenceCategory
diff --git a/res/xml/network_and_internet_v2.xml b/res/xml/network_and_internet_v2.xml
index 974739d..8e0b426 100644
--- a/res/xml/network_and_internet_v2.xml
+++ b/res/xml/network_and_internet_v2.xml
@@ -18,8 +18,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="network_and_internet_screen"
-    android:title="@string/network_dashboard_title"
-    settings:initialExpandedChildrenCount="5">
+    android:title="@string/network_dashboard_title">
 
     <PreferenceCategory
         android:key="multi_network_header"
diff --git a/res/xml/screen_lock_settings.xml b/res/xml/screen_lock_settings.xml
index 43f96e9..29c8de9 100644
--- a/res/xml/screen_lock_settings.xml
+++ b/res/xml/screen_lock_settings.xml
@@ -40,4 +40,17 @@
         android:key="power_button_instantly_locks"
         android:title="@string/lockpattern_settings_enable_power_button_instantly_locks" />
 
-</PreferenceScreen>
\ No newline at end of file
+    <!-- Temporarily available to evaluate extend unlock mode for SmartLock -->
+    <SwitchPreference
+        android:key="security_setting_trust_agents_extend_unlock"
+        android:title="@string/trust_agents_extend_unlock_title"
+        android:summary="@string/trust_agents_extend_unlock_summary"
+        settings:controller="com.android.settings.security.trustagent.TrustAgentsExtendUnlockPreferenceController" />
+
+    <SwitchPreference
+        android:key="security_setting_trust_lost_locks_screen"
+        android:title="@string/trust_lost_locks_screen_title"
+        android:summary="@string/trust_lost_locks_screen_summary"
+        settings:controller="com.android.settings.security.trustagent.TrustLostLocksScreenPreferenceController" />
+
+</PreferenceScreen>
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 57e673f..cb76693 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -130,4 +130,9 @@
             android:value="com.android.settings.Settings$ChangeWifiStateActivity" />
     </Preference>
 
+    <Preference
+        android:key="financial_apps_sms_access"
+        android:title="@string/financial_apps_sms_access_title"
+        android:fragment="com.android.settings.applications.specialaccess.financialapps.FinancialAppsSmsAccess"
+        settings:keywords="@string/keywords_financial_apps_sms_access" />
 </PreferenceScreen>
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index 03e32dc..9f4f902 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -93,10 +93,11 @@
     <Preference
         android:key="top_level_location"
         android:title="@string/location_settings_title"
-        android:summary="@string/location_settings_summary"
+        android:summary="@string/location_settings_loading_app_permission_stats"
         android:icon="@drawable/ic_homepage_location"
         android:order="-50"
-        android:fragment="com.android.settings.location.LocationSettings"/>
+        android:fragment="com.android.settings.location.LocationSettings"
+        settings:controller="com.android.settings.location.TopLevelLocationPreferenceController"/>
 
     <Preference
         android:key="top_level_security"
@@ -149,4 +150,4 @@
         android:order="100"
         settings:controller="com.android.settings.support.SupportPreferenceController"/>
 
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java
index 149deb1..05dd265 100644
--- a/src/com/android/settings/DateTimeSettings.java
+++ b/src/com/android/settings/DateTimeSettings.java
@@ -20,7 +20,6 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.Intent;
-import android.os.UserManager;
 import android.provider.SearchIndexableResource;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 6557aee..fdd7f2e 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -32,7 +32,6 @@
 import com.android.settings.display.ThemePreferenceController;
 import com.android.settings.display.TimeoutPreferenceController;
 import com.android.settings.display.VrDisplayPreferenceController;
-import com.android.settings.display.WallpaperPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settingslib.core.AbstractPreferenceController;
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 8e745a3..61a247d 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -66,7 +66,9 @@
 import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import com.google.android.setupcompat.TemplateLayout;
-import com.google.android.setupdesign.template.ButtonFooterMixin;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.item.FooterButton.ButtonType;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
 
 import java.util.List;
 
@@ -96,7 +98,7 @@
 
     private View mContentView;
     @VisibleForTesting
-    Button mInitiateButton;
+    FooterButton mInitiateButton;
     private View mExternalStorageContainer;
     @VisibleForTesting
     CheckBox mExternalStorage;
@@ -416,12 +418,15 @@
 
         final TemplateLayout layout = mContentView.findViewById(R.id.setup_wizard_layout);
         final ButtonFooterMixin buttonFooterMixin = layout.getMixin(ButtonFooterMixin.class);
-        buttonFooterMixin.removeAllViews();
-        buttonFooterMixin.addSpace();
-        buttonFooterMixin.addSpace();
-        mInitiateButton = buttonFooterMixin.addButton(R.string.master_clear_button_text,
-                R.style.SuwGlifButton_Primary);
-        mInitiateButton.setOnClickListener(mInitiateListener);
+        buttonFooterMixin.setPrimaryButton(
+                new FooterButton(
+                        getActivity(),
+                        R.string.master_clear_button_text,
+                        mInitiateListener,
+                        ButtonType.OTHER,
+                        R.style.SuwGlifButton_Primary)
+        );
+        mInitiateButton = buttonFooterMixin.getPrimaryButton();
     }
 
     private void getContentDescription(View v, StringBuffer description) {
diff --git a/src/com/android/settings/MasterClearConfirm.java b/src/com/android/settings/MasterClearConfirm.java
index ffbb2aa..b2bf838 100644
--- a/src/com/android/settings/MasterClearConfirm.java
+++ b/src/com/android/settings/MasterClearConfirm.java
@@ -45,7 +45,9 @@
 import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import com.google.android.setupcompat.TemplateLayout;
-import com.google.android.setupdesign.template.ButtonFooterMixin;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.item.FooterButton.ButtonType;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
 
 /**
  * Confirm and execute a reset of the device to a clean "just out of the box"
@@ -153,11 +155,14 @@
         final TemplateLayout layout = mContentView.findViewById(R.id.setup_wizard_layout);
 
         final ButtonFooterMixin buttonFooterMixin = layout.getMixin(ButtonFooterMixin.class);
-        buttonFooterMixin.removeAllViews();
-        buttonFooterMixin.addSpace();
-        buttonFooterMixin.addSpace();
-        buttonFooterMixin.addButton(R.string.master_clear_button_text,
-                R.style.SuwGlifButton_Primary).setOnClickListener(mFinalClickListener);
+        buttonFooterMixin.setPrimaryButton(
+                new FooterButton(
+                        getActivity(),
+                        R.string.master_clear_button_text,
+                        mFinalClickListener,
+                        ButtonType.OTHER,
+                        R.style.SuwGlifButton_Primary)
+        );
     }
 
     private void setUpActionBarAndTitle() {
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 18c83f4..2791efa 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -1194,12 +1194,10 @@
             int state = mTelephonyManager.getDataState();
             switch (state) {
                 case TelephonyManager.DATA_CONNECTED:
-                    //FIXME: Replace with a TelephonyManager call
-                    phone.setUserDataEnabled(false);
+                    mTelephonyManager.setDataEnabled(false);
                     break;
                 case TelephonyManager.DATA_DISCONNECTED:
-                    //FIXME: Replace with a TelephonyManager call
-                    phone.setUserDataEnabled(true);
+                    mTelephonyManager.setDataEnabled(true);
                     break;
                 default:
                     // do nothing
diff --git a/src/com/android/settings/applications/AppLaunchSettings.java b/src/com/android/settings/applications/AppLaunchSettings.java
index 0e2e3c7..3ccc36f 100644
--- a/src/com/android/settings/applications/AppLaunchSettings.java
+++ b/src/com/android/settings/applications/AppLaunchSettings.java
@@ -124,6 +124,8 @@
             // * always
             // * ask
             // * never
+            //
+            // Make sure to update linkStateToIndex() if this presentation order is changed.
             mAppLinkState.setEntries(new CharSequence[] {
                     getString(R.string.app_link_open_always),
                     getString(R.string.app_link_open_ask),
@@ -141,10 +143,7 @@
                 // purposes of the UI (and does the right thing around pending domain
                 // verifications that might arrive after the user chooses 'ask' in this UI).
                 final int state = mPm.getIntentVerificationStatusAsUser(mPackageName, UserHandle.myUserId());
-                mAppLinkState.setValue(
-                        Integer.toString((state == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED)
-                                ? INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK
-                                        : state));
+                mAppLinkState.setValueIndex(linkStateToIndex(state));
 
                 // Set the callback only after setting the initial selected item
                 mAppLinkState.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@@ -157,6 +156,17 @@
         }
     }
 
+    private int linkStateToIndex(final int state) {
+        switch (state) {
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
+                return 0; // Always
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER:
+                return 2; // Never
+            default:
+                return 1; // Ask
+        }
+    }
+
     private boolean updateAppLinkState(final int newState) {
         if (mIsBrowser) {
             // We shouldn't get into this state, but if we do make sure
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index c246c58..4bda99e 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -25,6 +25,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.location.LocationManager;
 import android.os.RemoteException;
 import android.os.UserManager;
 import android.telecom.DefaultDialerManager;
@@ -142,6 +143,12 @@
         // Keep Settings intelligence enabled, otherwise search feature will be disabled.
         keepEnabledPackages.add(
                 mContext.getString(R.string.config_settingsintelligence_package_name));
+        final LocationManager locationManager =
+                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        final String locationHistoryPackage = locationManager.getLocationControllerExtraPackage();
+        if (locationHistoryPackage != null) {
+            keepEnabledPackages.add(locationHistoryPackage);
+        }
         return keepEnabledPackages;
     }
 
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index c2db019..5669b4c 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -817,13 +817,12 @@
                 mManageApplications.onItemSelected(null, null, 0, 0);
             }
             if (mFilterOptions.size() > 1) {
-                if (filterType == mManageApplications.mFilterType) {
-                    int index = mFilterOptions.indexOf(filter);
-                    if (index != -1) {
-                        mManageApplications.mFilterSpinner.setSelection(index);
-                        mManageApplications.onItemSelected(null, null, index, 0);
-                        mManageApplications.mFilterType = AppFilterRegistry.FILTER_APPS_ALL;
-                    }
+                final AppFilterItem previousFilter = AppFilterRegistry.getInstance().get(
+                        mManageApplications.mFilterType);
+                final int index = mFilterOptions.indexOf(previousFilter);
+                if (index != -1) {
+                    mManageApplications.mFilterSpinner.setSelection(index);
+                    mManageApplications.onItemSelected(null, null, index, 0);
                 }
             }
         }
diff --git a/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsController.java b/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsController.java
new file mode 100644
index 0000000..492e4fd
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsController.java
@@ -0,0 +1,158 @@
+/*
+ * 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.specialaccess.financialapps;
+
+import static android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS;
+import static android.Manifest.permission.READ_SMS;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.SwitchPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FinancialAppsController extends BasePreferenceController
+        implements ApplicationsState.Callbacks {
+    private final static String TAG = FinancialAppsController.class.getSimpleName();
+
+    @VisibleForTesting
+    PreferenceScreen mRoot;
+
+    public FinancialAppsController(Context context, String key) {
+        super(context, key);
+    }
+
+    @AvailabilityStatus
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mRoot = screen;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        updateList();
+    }
+
+    private void updateList() {
+        mRoot.removeAll();
+
+        final PackageManager packageManager = mContext.getPackageManager();
+        final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+
+        final List<PackageInfo> installedPackages =
+                packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
+        final int numPackages = installedPackages.size();
+        for (int i = 0; i < numPackages; i++) {
+            final PackageInfo installedPackage = installedPackages.get(i);
+
+            if (installedPackage.requestedPermissions == null) {
+                continue;
+            }
+            final int targetSdk = installedPackage.applicationInfo.targetSdkVersion;
+            final String pkgName = installedPackage.packageName;
+
+            if ((targetSdk >= Build.VERSION_CODES.Q
+                    && ArrayUtils.contains(installedPackage.requestedPermissions,
+                            SMS_FINANCIAL_TRANSACTIONS))
+                    || (targetSdk < Build.VERSION_CODES.Q
+                    && ArrayUtils.contains(installedPackage.requestedPermissions,
+                            READ_SMS))) {
+                final SwitchPreference pref = new SwitchPreference(mRoot.getContext());
+                pref.setTitle(installedPackage.applicationInfo.loadLabel(packageManager));
+                pref.setKey(pkgName);
+
+                pref.setChecked(
+                        appOpsManager.checkOp(
+                                targetSdk >= Build.VERSION_CODES.Q
+                                        ? AppOpsManager.OP_SMS_FINANCIAL_TRANSACTIONS
+                                        : AppOpsManager.OP_READ_SMS,
+                                installedPackage.applicationInfo.uid,
+                                pkgName) == AppOpsManager.MODE_ALLOWED);
+
+                pref.setOnPreferenceChangeListener((preference, newValue) -> {
+                    final int uid;
+                    try {
+                        uid = packageManager.getPackageInfo(preference.getKey(), 0)
+                                .applicationInfo.uid;
+                    } catch (NameNotFoundException e) {
+                        Log.e(TAG, "onPreferenceChange: Failed to get uid for "
+                                + preference.getKey());
+                        return false;
+                    }
+
+                    appOpsManager.setMode(
+                            targetSdk >= Build.VERSION_CODES.Q
+                                    ? AppOpsManager.OP_SMS_FINANCIAL_TRANSACTIONS
+                                    : AppOpsManager.OP_READ_SMS,
+                            uid,
+                            pkgName,
+                            (Boolean) newValue ? AppOpsManager.MODE_ALLOWED
+                                    : AppOpsManager.MODE_IGNORED);
+                    return true;
+                });
+                mRoot.addPreference(pref);
+            }
+        }
+    }
+
+    @Override
+    public void onRunningStateChanged(boolean running) {}
+
+    @Override
+    public void onPackageListChanged() {
+        updateList();
+    }
+
+    @Override
+    public void onRebuildComplete(ArrayList<AppEntry> apps) {}
+
+    @Override
+    public void onPackageIconChanged() {}
+
+    @Override
+    public void onPackageSizeChanged(String packageName) {}
+
+    @Override
+    public void onAllSizesComputed() {}
+
+    @Override
+    public void onLauncherInfoChanged() {}
+
+    @Override
+    public void onLoadEntriesCompleted() {}
+}
diff --git a/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsSmsAccess.java b/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsSmsAccess.java
new file mode 100644
index 0000000..92f4e28
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsSmsAccess.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.applications.specialaccess.financialapps;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+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;
+
+@SearchIndexable
+public class FinancialAppsSmsAccess extends DashboardFragment {
+    private final static String TAG = FinancialAppsSmsAccess.class.getSimpleName();
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.financial_app_sms_access;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+      return SettingsEnums.SETTINGS_FINANCIAL_APPS_SMS_ACCESS;
+    }
+
+    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.financial_app_sms_access;
+                    result.add(sir);
+                    return result;
+                }
+            };
+}
diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java
index 0aa8936..7a06671 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollBase.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java
@@ -40,8 +40,10 @@
  */
 public abstract class BiometricEnrollBase extends InstrumentedActivity
         implements View.OnClickListener {
-    public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
 
+    public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
+    public static final String EXTRA_KEY_REQUIRE_VISION = "accessibility_vision";
+    public static final String EXTRA_KEY_REQUIRE_DIVERSITY = "accessibility_diversity";
 
     /**
      * Used by the choose fingerprint wizard to indicate the wizard is
@@ -67,8 +69,11 @@
      */
     public static final int RESULT_TIMEOUT = RESULT_FIRST_USER + 2;
 
-    public static final int CONFIRM_REQUEST = 1;
-    public static final int ENROLLING = 2;
+    public static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
+    public static final int BIOMETRIC_FIND_SENSOR_REQUEST = 2;
+    public static final int LEARN_MORE_REQUEST = 3;
+    public static final int CONFIRM_REQUEST = 4;
+    public static final int ENROLLING = 5;
 
     protected boolean mLaunchedConfirmLock;
     protected byte[] mToken;
@@ -105,10 +110,6 @@
         initViews();
     }
 
-    protected boolean shouldLaunchConfirmLock() {
-        return mToken == null && !mLaunchedConfirmLock;
-    }
-
     protected void initViews() {
         getWindow().setStatusBarColor(Color.TRANSPARENT);
         Button nextButton = getNextButton();
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 2424eb1..8a2a8ec 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -37,10 +37,6 @@
 public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
         implements LinkSpan.OnClickListener {
 
-    public static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
-    public static final int BIOMETRIC_FIND_SENSOR_REQUEST = 2;
-    public static final int LEARN_MORE_REQUEST = 3;
-
     private UserManager mUserManager;
     private boolean mHasPassword;
     private boolean mBiometricUnlockDisabledByAdmin;
@@ -110,6 +106,11 @@
     protected abstract Intent getEnrollingIntent();
 
     /**
+     * @return the title to be shown on the ConfirmLock screen.
+     */
+    protected abstract int getConfirmLockTitleResId();
+
+    /**
      * @param span
      */
     public abstract void onClick(LinkSpan span);
@@ -133,6 +134,13 @@
 
         mUserManager = UserManager.get(this);
         updatePasswordQuality();
+
+        if (!mHasPassword) {
+            // No password registered, launch into enrollment wizard.
+            launchChooseLock();
+        } else {
+            launchConfirmLock(getConfirmLockTitleResId(), getChallenge());
+        }
     }
 
     @Override
@@ -157,13 +165,8 @@
 
     @Override
     protected void onNextButtonClick() {
-        if (!mHasPassword) {
-            // No biometrics registered, launch into enrollment wizard.
-            launchChooseLock();
-        } else {
-            // Lock thingy is already set up, launch directly into find sensor step from wizard.
-            launchFindSensor(null);
-        }
+        // Lock thingy is already set up, launch directly to the next page
+        launchNextEnrollingActivity(mToken);
     }
 
     private void launchChooseLock() {
@@ -181,7 +184,7 @@
         startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
     }
 
-    private void launchFindSensor(byte[] token) {
+    private void launchNextEnrollingActivity(byte[] token) {
         Intent intent = getEnrollingIntent();
         if (token != null) {
             intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
@@ -199,9 +202,9 @@
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         final boolean isResultFinished = resultCode == RESULT_FINISHED;
+        final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
         if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
             if (isResultFinished || resultCode == RESULT_SKIP) {
-                final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
                 setResult(result, data);
                 finish();
                 return;
@@ -209,10 +212,21 @@
         } else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
             if (isResultFinished) {
                 updatePasswordQuality();
-                byte[] token = data.getByteArrayExtra(
+                mToken = data.getByteArrayExtra(
                         ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
-                launchFindSensor(token);
+                overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
                 return;
+            } else {
+                setResult(result, data);
+                finish();
+            }
+        } else if (requestCode == CONFIRM_REQUEST) {
+            if (resultCode == RESULT_OK && data != null) {
+                mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
+                overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
+            } else {
+                setResult(result, data);
+                finish();
             }
         } else if (requestCode == LEARN_MORE_REQUEST) {
             overridePendingTransition(R.anim.suw_slide_back_in, R.anim.suw_slide_back_out);
diff --git a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
index f101038..033fb4b 100644
--- a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
@@ -48,13 +48,6 @@
      */
     protected abstract boolean shouldStartAutomatically();
 
-    /**
-     * @return true if enrollment should finish when onStop is called.
-     */
-    protected boolean shouldFinishOnStop() {
-        return true;
-    }
-
     @Override
     protected void onStart() {
         super.onStart();
@@ -70,7 +63,7 @@
             mSidecar.setListener(null);
         }
 
-        if (shouldFinishOnStop() && !isChangingConfigurations()) {
+        if (!isChangingConfigurations()) {
             if (mSidecar != null) {
                 mSidecar.cancelEnrollment();
                 getSupportFragmentManager()
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
new file mode 100644
index 0000000..49f4f7f
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
@@ -0,0 +1,66 @@
+/*
+ * 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.biometrics.face;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+/**
+ * A layout that contains a start-justified title, and an end-justified switch.
+ */
+public class FaceEnrollAccessibilityToggle extends LinearLayout {
+
+    private Switch mSwitch;
+
+    public FaceEnrollAccessibilityToggle(Context context) {
+        this(context, null /* attrs */);
+    }
+
+    public FaceEnrollAccessibilityToggle(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public FaceEnrollAccessibilityToggle(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        LayoutInflater.from(context).inflate(R.layout.face_enroll_accessibility_toggle,
+                this, true /* attachToRoot */);
+
+        final TypedArray a =
+                context.obtainStyledAttributes(attrs, R.styleable.FaceEnrollAccessibilityToggle);
+        try {
+            final CharSequence title =
+                    a.getText(R.styleable.FaceEnrollAccessibilityToggle_messageText);
+            final TextView titleTextView = findViewById(R.id.title);
+            titleTextView.setText(title);
+        } finally {
+            a.recycle();
+        }
+        mSwitch = findViewById(R.id.toggle);
+    }
+
+    public boolean isChecked() {
+        return mSwitch.isChecked();
+    }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java b/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java
index 5be7c53..b6ad565 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java
@@ -29,6 +29,7 @@
 import android.graphics.drawable.Drawable;
 
 import com.android.settings.biometrics.BiometricEnrollSidecar;
+import com.android.settings.overlay.FeatureFactory;
 
 /**
  * A drawable containing the circle cutout as well as the animations.
@@ -41,17 +42,17 @@
     private static final int BORDER_BOUNDS = 20;
 
     private final Context mContext;
-    private final ParticleCollection.Listener mListener;
+    private final FaceFeatureProvider.Listener mListener;
     private Rect mBounds;
     private final Paint mSquarePaint;
     private final Paint mCircleCutoutPaint;
 
-    private ParticleCollection mParticleCollection;
+    private FaceFeatureProvider.EnrollingAnimation mEnrollingAnimation;
 
     private TimeAnimator mTimeAnimator;
 
-    private final ParticleCollection.Listener mAnimationListener
-            = new ParticleCollection.Listener() {
+    private final FaceFeatureProvider.Listener mAnimationListener
+            = new FaceFeatureProvider.Listener() {
         @Override
         public void onEnrolled() {
             if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
@@ -61,7 +62,7 @@
         }
     };
 
-    public FaceEnrollAnimationDrawable(Context context, ParticleCollection.Listener listener) {
+    public FaceEnrollAnimationDrawable(Context context, FaceFeatureProvider.Listener listener) {
         mContext = context;
         mListener = listener;
 
@@ -77,29 +78,29 @@
 
     @Override
     public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
-        mParticleCollection.onEnrollmentHelp(helpMsgId, helpString);
+        mEnrollingAnimation.onEnrollmentHelp(helpMsgId, helpString);
     }
 
     @Override
     public void onEnrollmentError(int errMsgId, CharSequence errString) {
-        mParticleCollection.onEnrollmentError(errMsgId, errString);
+        mEnrollingAnimation.onEnrollmentError(errMsgId, errString);
     }
 
     @Override
     public void onEnrollmentProgressChange(int steps, int remaining) {
-        mParticleCollection.onEnrollmentProgressChange(steps, remaining);
+        mEnrollingAnimation.onEnrollmentProgressChange(steps, remaining);
     }
 
     @Override
     protected void onBoundsChange(Rect bounds) {
         mBounds = bounds;
-        mParticleCollection =
-                new ParticleCollection(mContext, mAnimationListener, bounds, BORDER_BOUNDS);
+        mEnrollingAnimation = FeatureFactory.getFactory(mContext).getFaceFeatureProvider()
+                .getEnrollingAnimation(mContext, mAnimationListener, bounds, BORDER_BOUNDS);
 
         if (mTimeAnimator == null) {
             mTimeAnimator = new TimeAnimator();
             mTimeAnimator.setTimeListener((animation, totalTimeMs, deltaTimeMs) -> {
-                mParticleCollection.update(totalTimeMs, deltaTimeMs);
+                mEnrollingAnimation.update(totalTimeMs, deltaTimeMs);
                 FaceEnrollAnimationDrawable.this.invalidateSelf();
             });
             mTimeAnimator.start();
@@ -121,7 +122,7 @@
                 mBounds.height() / 2 - BORDER_BOUNDS, mCircleCutoutPaint);
 
         // Draw the animation
-        mParticleCollection.draw(canvas);
+        mEnrollingAnimation.draw(canvas);
 
         canvas.restore();
     }
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
index 37b949c..990eef4 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
@@ -29,11 +29,12 @@
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
-import com.android.settings.Utils;
+import com.android.settings.biometrics.BiometricEnrollBase;
 import com.android.settings.biometrics.BiometricEnrollSidecar;
 import com.android.settings.biometrics.BiometricErrorDialog;
 import com.android.settings.biometrics.BiometricsEnrollEnrolling;
-import com.android.settings.password.ChooseLockSettingsHelper;
+
+import java.util.ArrayList;
 
 
 public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
@@ -44,10 +45,11 @@
 
     private TextView mErrorText;
     private Interpolator mLinearOutSlowInInterpolator;
-    private boolean mShouldFinishOnStop = true;
     private FaceEnrollPreviewFragment mPreviewFragment;
 
-    private ParticleCollection.Listener mListener = new ParticleCollection.Listener() {
+    private ArrayList<Integer> mDisabledFeatures = new ArrayList<>();
+
+    private FaceFeatureProvider.Listener mListener = new FaceFeatureProvider.Listener() {
         @Override
         public void onEnrolled() {
             FaceEnrollEnrolling.this.launchFinish(mToken);
@@ -92,13 +94,14 @@
         Button skipButton = findViewById(R.id.skip_button);
         skipButton.setOnClickListener(this);
 
-        if (shouldLaunchConfirmLock()) {
-            launchConfirmLock(R.string.security_settings_face_preference_title,
-                    Utils.getFaceManagerOrNull(this).generateChallenge());
-            mShouldFinishOnStop = false;
-        } else {
-            startEnrollment();
+        if (!getIntent().getBooleanExtra(BiometricEnrollBase.EXTRA_KEY_REQUIRE_DIVERSITY, true)) {
+            mDisabledFeatures.add(FaceManager.FEATURE_REQUIRE_REQUIRE_DIVERSITY);
         }
+        if (!getIntent().getBooleanExtra(BiometricEnrollBase.EXTRA_KEY_REQUIRE_VISION, true)) {
+            mDisabledFeatures.add(FaceManager.FEATURE_REQUIRE_ATTENTION);
+        }
+
+        startEnrollment();
     }
 
     @Override
@@ -121,7 +124,12 @@
 
     @Override
     protected BiometricEnrollSidecar getSidecar() {
-        return new FaceEnrollSidecar();
+        final int[] disabledFeatures = new int[mDisabledFeatures.size()];
+        for (int i = 0; i < mDisabledFeatures.size(); i++) {
+            disabledFeatures[i] = mDisabledFeatures.get(i);
+        }
+
+        return new FaceEnrollSidecar(disabledFeatures);
     }
 
     @Override
@@ -130,11 +138,6 @@
     }
 
     @Override
-    protected boolean shouldFinishOnStop() {
-        return mShouldFinishOnStop;
-    }
-
-    @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.FACE_ENROLL_ENROLLING;
     }
@@ -178,23 +181,6 @@
         }
     }
 
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (requestCode == CONFIRM_REQUEST) {
-            if (resultCode == RESULT_OK && data != null) {
-                mShouldFinishOnStop = true;
-                mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
-                overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
-                getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
-                startEnrollment();
-            } else {
-                finish();
-            }
-        } else {
-            super.onActivityResult(requestCode, resultCode, data);
-        }
-    }
-
     private void showErrorDialog(CharSequence msg, int msgId) {
         BiometricErrorDialog dialog = FaceErrorDialog.newInstance(msg, msgId);
         dialog.show(getSupportFragmentManager(), FaceErrorDialog.class.getName());
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index c4a9c4f..e221c96 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -20,7 +20,9 @@
 import android.content.Intent;
 import android.hardware.face.FaceManager;
 import android.os.Bundle;
+import android.view.View;
 import android.widget.Button;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto;
@@ -37,11 +39,22 @@
     private static final String TAG = "FaceIntro";
 
     private FaceManager mFaceManager;
+    private FaceEnrollAccessibilityToggle mSwitchVision;
+    private FaceEnrollAccessibilityToggle mSwitchDiversity;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mFaceManager = Utils.getFaceManagerOrNull(this);
+        final LinearLayout accessibilityLayout = findViewById(R.id.accessibility_layout);
+        final Button accessibilityButton = findViewById(R.id.accessibility_button);
+        accessibilityButton.setOnClickListener(view -> {
+            accessibilityButton.setVisibility(View.INVISIBLE);
+            accessibilityLayout.setVisibility(View.VISIBLE);
+        });
+
+        mSwitchVision = findViewById(R.id.toggle_vision);
+        mSwitchDiversity = findViewById(R.id.toggle_diversity);
     }
 
     @Override
@@ -102,6 +115,7 @@
 
     @Override
     protected long getChallenge() {
+        mFaceManager = Utils.getFaceManagerOrNull(this);
         if (mFaceManager == null) {
             return 0;
         }
@@ -115,7 +129,15 @@
 
     @Override
     protected Intent getEnrollingIntent() {
-        return new Intent(this, FaceEnrollEnrolling.class);
+        final Intent intent = new Intent(this, FaceEnrollEnrolling.class);
+        intent.putExtra(EXTRA_KEY_REQUIRE_VISION, mSwitchVision.isChecked());
+        intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, mSwitchDiversity.isChecked());
+        return intent;
+    }
+
+    @Override
+    protected int getConfirmLockTitleResId() {
+        return R.string.security_settings_face_preference_title;
     }
 
     @Override
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
index a543584..a370875 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
@@ -63,7 +63,7 @@
     private CameraCaptureSession mCaptureSession;
     private CaptureRequest mPreviewRequest;
     private Size mPreviewSize;
-    private ParticleCollection.Listener mListener;
+    private FaceFeatureProvider.Listener mListener;
 
     // View used to contain the circular cutout and enrollment animation drawable
     private ImageView mCircleView;
@@ -75,8 +75,8 @@
     private FaceSquareTextureView mTextureView;
 
     // Listener sent to the animation drawable
-    private final ParticleCollection.Listener mAnimationListener
-            = new ParticleCollection.Listener() {
+    private final FaceFeatureProvider.Listener mAnimationListener
+            = new FaceFeatureProvider.Listener() {
         @Override
         public void onEnrolled() {
             mListener.onEnrolled();
@@ -234,7 +234,7 @@
         mAnimationDrawable.onEnrollmentProgressChange(steps, remaining);
     }
 
-    public void setListener(ParticleCollection.Listener listener) {
+    public void setListener(FaceFeatureProvider.Listener listener) {
         mListener = listener;
     }
 
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
index 2433fcb..7519530 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
@@ -24,13 +24,22 @@
 import com.android.settings.Utils;
 import com.android.settings.biometrics.BiometricEnrollSidecar;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+
 /**
  * Sidecar fragment to handle the state around face enrollment
  */
 public class FaceEnrollSidecar extends BiometricEnrollSidecar {
 
+    private final int[] mDisabledFeatures;
+
     private FaceManager mFaceManager;
 
+    public FaceEnrollSidecar(int[] disabledFeatures) {
+        mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
+    }
+
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
@@ -43,9 +52,9 @@
         if (mUserId != UserHandle.USER_NULL) {
             mFaceManager.setActiveUser(mUserId);
         }
-        // TODO: Send the list of disabled features
+
         mFaceManager.enroll(mToken, mEnrollmentCancel,
-                mEnrollmentCallback, new int[0] /* disabledFeatures */);
+                mEnrollmentCallback, mDisabledFeatures);
     }
 
     private FaceManager.EnrollmentCallback mEnrollmentCallback
diff --git a/src/com/android/settings/biometrics/face/FaceFeatureProvider.java b/src/com/android/settings/biometrics/face/FaceFeatureProvider.java
new file mode 100644
index 0000000..e2f62d3
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceFeatureProvider.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.biometrics.face;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+
+/**
+ * Feature provider for face authentication.
+ */
+public interface FaceFeatureProvider {
+
+    interface EnrollingAnimation {
+        void onEnrollmentHelp(int helpMsgId, CharSequence helpString);
+        void onEnrollmentError(int errMsgId, CharSequence errString);
+        void onEnrollmentProgressChange(int steps, int remaining);
+        void draw(Canvas canvas);
+        void update(long t, long dt);
+    }
+
+    interface Listener {
+        void onEnrolled();
+    }
+
+    EnrollingAnimation getEnrollingAnimation(Context context, Listener listener, Rect bounds,
+            int borderWidth);
+}
diff --git a/src/com/android/settings/biometrics/face/FaceFeatureProviderImpl.java b/src/com/android/settings/biometrics/face/FaceFeatureProviderImpl.java
new file mode 100644
index 0000000..3f65669
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceFeatureProviderImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.biometrics.face;
+
+import android.content.Context;
+import android.graphics.Rect;
+
+public class FaceFeatureProviderImpl implements FaceFeatureProvider {
+    @Override
+    public EnrollingAnimation getEnrollingAnimation(Context context, Listener listener, Rect bounds,
+            int borderWidth) {
+        return new ParticleCollection(context, listener, bounds, borderWidth);
+    }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index d7dc9f8..8eabf00 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -59,6 +59,10 @@
     private byte[] mToken;
     private FaceSettingsAttentionPreferenceController mAttentionController;
 
+    private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
+        getActivity().finish();
+    };
+
     public static boolean isAvailable(Context context) {
         FaceManager manager = Utils.getFaceManagerOrNull(context);
         return manager != null && manager.isHardwareDetected();
@@ -146,10 +150,13 @@
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         final List<AbstractPreferenceController> controllers =
                 buildPreferenceControllers(context, getSettingsLifecycle());
+        // There's no great way of doing this right now :/
         for (AbstractPreferenceController controller : controllers) {
             if (controller instanceof FaceSettingsAttentionPreferenceController) {
                 mAttentionController = (FaceSettingsAttentionPreferenceController) controller;
-                break;
+            } else if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
+                ((FaceSettingsRemoveButtonPreferenceController) controller)
+                        .setListener(mRemovalListener);
             }
         }
 
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
index 8e41eff..baab391 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
@@ -17,8 +17,13 @@
 package com.android.settings.biometrics.face;
 
 import android.content.Context;
+import android.hardware.face.Face;
+import android.hardware.face.FaceManager;
+import android.os.UserHandle;
+import android.util.Log;
 import android.view.View;
 import android.widget.Button;
+import android.widget.Toast;
 
 import androidx.preference.Preference;
 
@@ -26,18 +31,61 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.widget.LayoutPreference;
 
+import java.util.List;
+
 /**
- * Controller for the remove button.
+ * Controller for the remove button. This assumes that there is only a single face enrolled. The UI
+ * will likely change if multiple enrollments are allowed/supported.
  */
 public class FaceSettingsRemoveButtonPreferenceController extends BasePreferenceController
         implements View.OnClickListener {
 
+    private static final String TAG = "FaceSettings/Remove";
     private static final String KEY = "security_settings_face_delete_faces_container";
 
+    interface Listener {
+        void onRemoved();
+    }
+
     private Button mButton;
+    private List<Face> mFaces;
+    private Listener mListener;
+
+    private final Context mContext;
+    private final int mUserId;
+    private final FaceManager mFaceManager;
+    private final FaceManager.RemovalCallback mRemovalCallback = new FaceManager.RemovalCallback() {
+        @Override
+        public void onRemovalError(Face face, int errMsgId, CharSequence errString) {
+            Log.e(TAG, "Unable to remove face: " + face.getBiometricId()
+                    + " error: " + errMsgId + " " + errString);
+            Toast.makeText(mContext, errString, Toast.LENGTH_SHORT).show();
+        }
+
+        @Override
+        public void onRemovalSucceeded(Face face, int remaining) {
+            if (remaining == 0) {
+                mFaces = mFaceManager.getEnrolledFaces(mUserId);
+                if (!mFaces.isEmpty()) {
+                    mButton.setEnabled(true);
+                } else {
+                    mListener.onRemoved();
+                }
+            } else {
+                Log.v(TAG, "Remaining: " + remaining);
+            }
+        }
+    };
 
     public FaceSettingsRemoveButtonPreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
+        mContext = context;
+        mFaceManager = context.getSystemService(FaceManager.class);
+        // TODO: Use the profile-specific userId instead
+        mUserId = UserHandle.myUserId();
+        if (mFaceManager != null) {
+            mFaces = mFaceManager.getEnrolledFaces(mUserId);
+        }
     }
 
     public FaceSettingsRemoveButtonPreferenceController(Context context) {
@@ -66,7 +114,21 @@
     @Override
     public void onClick(View v) {
         if (v == mButton) {
+            mButton.setEnabled(false);
+            if (mFaces.isEmpty()) {
+                Log.e(TAG, "No faces");
+                return;
+            }
+            if (mFaces.size() > 1) {
+                Log.e(TAG, "Multiple enrollments: " + mFaces.size());
+            }
 
+            // Remove the first/only face
+            mFaceManager.remove(mFaces.get(0), mUserId, mRemovalCallback);
         }
     }
+
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
 }
diff --git a/src/com/android/settings/biometrics/face/ParticleCollection.java b/src/com/android/settings/biometrics/face/ParticleCollection.java
index 399beec..b345ab5 100644
--- a/src/com/android/settings/biometrics/face/ParticleCollection.java
+++ b/src/com/android/settings/biometrics/face/ParticleCollection.java
@@ -35,7 +35,7 @@
  * are updated/drawn in a special order so that the overlap is correct during the final completion
  * effect.
  */
-public class ParticleCollection implements BiometricEnrollSidecar.Listener {
+public class ParticleCollection implements FaceFeatureProviderImpl.EnrollingAnimation {
 
     private static final String TAG = "AnimationController";
 
@@ -49,11 +49,7 @@
     private final List<AnimationParticle> mParticleList;
     private final List<Integer> mPrimariesInProgress; // primary particles not done animating yet
     private int mState;
-    private Listener mListener;
-
-    public interface Listener {
-        void onEnrolled();
-    }
+    private FaceFeatureProvider.Listener mListener;
 
     private final AnimationParticle.Listener mParticleListener = new AnimationParticle.Listener() {
         @Override
@@ -72,7 +68,8 @@
         }
     };
 
-    public ParticleCollection(Context context, Listener listener, Rect bounds, int borderWidth) {
+    public ParticleCollection(Context context, FaceFeatureProvider.Listener listener, Rect bounds,
+            int borderWidth) {
         mParticleList = new ArrayList<>();
         mListener = listener;
 
@@ -103,12 +100,14 @@
         updateState(STATE_STARTED);
     }
 
+    @Override
     public void update(long t, long dt) {
         for (int i = 0; i < mParticleList.size(); i++) {
             mParticleList.get(i).update(t, dt);
         }
     }
 
+    @Override
     public void draw(Canvas canvas) {
         for (int i = 0; i < mParticleList.size(); i++) {
             mParticleList.get(i).draw(canvas);
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
index 4b4f65a..0772c66 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
@@ -51,12 +51,9 @@
 
         setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
 
-        if (shouldLaunchConfirmLock()) {
-            launchConfirmLock(R.string.security_settings_fingerprint_preference_title,
-                    Utils.getFingerprintManagerOrNull(this).preEnroll());
-        } else if (mToken != null) {
-            startLookingForFingerprint(); // already confirmed, so start looking for fingerprint
-        }
+
+        startLookingForFingerprint(); // already confirmed, so start looking for fingerprint
+
         View animationView = findViewById(R.id.fingerprint_sensor_location_animation);
         if (animationView instanceof FingerprintFindSensorAnimation) {
             mAnimation = (FingerprintFindSensorAnimation) animationView;
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 8821ce5..61c67a5 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -106,6 +106,7 @@
 
     @Override
     protected long getChallenge() {
+        mFingerprintManager = Utils.getFingerprintManagerOrNull(this);
         if (mFingerprintManager == null) {
             return 0;
         }
@@ -123,6 +124,11 @@
     }
 
     @Override
+    protected int getConfirmLockTitleResId() {
+        return R.string.security_settings_fingerprint_preference_title;
+    }
+
+    @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.FINGERPRINT_ENROLL_INTRO;
     }
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index df32111..6ec419b 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -21,12 +21,16 @@
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
 import android.os.Bundle;
+import android.util.FeatureFlagUtils;
 
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
+import com.android.settings.core.FeatureFlags;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.slices.SlicePreferenceController;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -98,6 +102,13 @@
         mManager = getLocalBluetoothManager(context);
         mCachedDevice = getCachedDevice(mDeviceAddress);
         super.onAttach(context);
+
+        if (FeatureFlagUtils.isEnabled(context, FeatureFlags.SLICE_INJECTION)) {
+            final BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(context)
+                    .getBluetoothFeatureProvider(context);
+            use(SlicePreferenceController.class).setSliceUri(
+                    featureProvider.getBluetoothDeviceSettingsUri(mDeviceAddress));
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/slices/CopyableSlice.java b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
similarity index 61%
copy from src/com/android/settings/slices/CopyableSlice.java
copy to src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
index 31fc151..2bca038 100644
--- a/src/com/android/settings/slices/CopyableSlice.java
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
@@ -14,15 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.settings.slices;
+package com.android.settings.bluetooth;
+
+import android.net.Uri;
 
 /**
- * Provide the copy ability for preference controller to copy the data to the clipboard.
+ * Provider for bluetooth related feature
  */
-public interface CopyableSlice {
+public interface BluetoothFeatureProvider {
+
     /**
-     * Copy the key slice information to the clipboard.
-     * It is highly recommended to show the toast to notify users when implemented this function.
+     * Get the {@link Uri} that represents extra settings for a specific bluetooth device
+     * @param macAddress Bluetooth mac address
+     * @return {@link Uri} for extra settings
      */
-    void copy();
+    Uri getBluetoothDeviceSettingsUri(String macAddress);
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
new file mode 100644
index 0000000..dcdc2fd7
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
@@ -0,0 +1,41 @@
+/*
+ * 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.bluetooth;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.settings.R;
+
+/**
+ * Impl of {@link BluetoothFeatureProvider}
+ */
+public class BluetoothFeatureProviderImpl implements BluetoothFeatureProvider {
+
+    private Context mContext;
+
+    public BluetoothFeatureProviderImpl(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public Uri getBluetoothDeviceSettingsUri(String macAddress) {
+        final String uriString = mContext.getString(R.string.config_bluetooth_device_settings_uri,
+                macAddress);
+        return Uri.parse(uriString);
+    }
+}
diff --git a/src/com/android/settings/connecteddevice/TopLevelConnectedDevicesPreferenceController.java b/src/com/android/settings/connecteddevice/TopLevelConnectedDevicesPreferenceController.java
index 6f16db6..4b2bdc0 100644
--- a/src/com/android/settings/connecteddevice/TopLevelConnectedDevicesPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/TopLevelConnectedDevicesPreferenceController.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.R;
 
 public class TopLevelConnectedDevicesPreferenceController extends BasePreferenceController {
 
@@ -29,7 +30,9 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return AVAILABLE_UNSEARCHABLE;
+        return mContext.getResources().getBoolean(R.bool.config_show_top_level_connected_devices)
+        ? AVAILABLE_UNSEARCHABLE
+        : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
diff --git a/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java b/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
index befdf29..0be1438 100644
--- a/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
+++ b/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
@@ -15,9 +15,12 @@
  */
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+
 import android.content.Context;
 import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -43,7 +46,7 @@
     UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener =
             (connected, functions, powerRole, dataRole) -> {
                 if (connected) {
-                    mUsbPreference.setSummary(getSummary(dataRole == UsbPort.DATA_ROLE_DEVICE
+                    mUsbPreference.setSummary(getSummary(dataRole == DATA_ROLE_DEVICE
                                     ? functions : UsbManager.FUNCTION_NONE, powerRole));
                     mDevicePreferenceCallback.onDeviceAdded(mUsbPreference);
                 } else {
@@ -100,7 +103,7 @@
 
     public static int getSummary(long functions, int power) {
         switch (power) {
-            case UsbPort.POWER_ROLE_SINK:
+            case POWER_ROLE_SINK:
                 if (functions == UsbManager.FUNCTION_MTP) {
                     return R.string.usb_summary_file_transfers;
                 } else if (functions == UsbManager.FUNCTION_RNDIS) {
@@ -112,7 +115,7 @@
                 } else {
                     return R.string.usb_summary_charging_only;
                 }
-            case UsbPort.POWER_ROLE_SOURCE:
+            case POWER_ROLE_SOURCE:
                 if (functions == UsbManager.FUNCTION_MTP) {
                     return R.string.usb_summary_file_transfers_power;
                 } else if (functions == UsbManager.FUNCTION_RNDIS) {
diff --git a/src/com/android/settings/connecteddevice/usb/UsbBackend.java b/src/com/android/settings/connecteddevice/usb/UsbBackend.java
index f68a4a0..556f76d 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbBackend.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbBackend.java
@@ -15,6 +15,13 @@
  */
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+import static android.service.usb.UsbPortStatusProto.DATA_ROLE_HOST;
+import static android.service.usb.UsbPortStatusProto.DATA_ROLE_NONE;
+import static android.service.usb.UsbPortStatusProto.POWER_ROLE_SINK;
+
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -27,6 +34,8 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import java.util.List;
+
 /**
  * Provides access to underlying system USB functionality.
  */
@@ -96,30 +105,30 @@
 
     public int getPowerRole() {
         updatePorts();
-        return mPortStatus == null ? UsbPort.POWER_ROLE_NONE : mPortStatus.getCurrentPowerRole();
+        return mPortStatus == null ? POWER_ROLE_NONE : mPortStatus.getCurrentPowerRole();
     }
 
     public int getDataRole() {
         updatePorts();
-        return mPortStatus == null ? UsbPort.DATA_ROLE_NONE : mPortStatus.getCurrentDataRole();
+        return mPortStatus == null ? DATA_ROLE_NONE : mPortStatus.getCurrentDataRole();
     }
 
     public void setPowerRole(int role) {
         int newDataRole = getDataRole();
         if (!areAllRolesSupported()) {
             switch (role) {
-                case UsbPort.POWER_ROLE_SINK:
-                    newDataRole = UsbPort.DATA_ROLE_DEVICE;
+                case POWER_ROLE_SINK:
+                    newDataRole = DATA_ROLE_DEVICE;
                     break;
-                case UsbPort.POWER_ROLE_SOURCE:
-                    newDataRole = UsbPort.DATA_ROLE_HOST;
+                case POWER_ROLE_SOURCE:
+                    newDataRole = DATA_ROLE_HOST;
                     break;
                 default:
-                    newDataRole = UsbPort.DATA_ROLE_NONE;
+                    newDataRole = DATA_ROLE_NONE;
             }
         }
         if (mPort != null) {
-            mUsbManager.setPortRoles(mPort, role, newDataRole);
+            mPort.setRoles(role, newDataRole);
         }
     }
 
@@ -127,31 +136,27 @@
         int newPowerRole = getPowerRole();
         if (!areAllRolesSupported()) {
             switch (role) {
-                case UsbPort.DATA_ROLE_DEVICE:
-                    newPowerRole = UsbPort.POWER_ROLE_SINK;
+                case DATA_ROLE_DEVICE:
+                    newPowerRole = POWER_ROLE_SINK;
                     break;
-                case UsbPort.DATA_ROLE_HOST:
-                    newPowerRole = UsbPort.POWER_ROLE_SOURCE;
+                case DATA_ROLE_HOST:
+                    newPowerRole = POWER_ROLE_SOURCE;
                     break;
                 default:
-                    newPowerRole = UsbPort.POWER_ROLE_NONE;
+                    newPowerRole = POWER_ROLE_NONE;
             }
         }
         if (mPort != null) {
-            mUsbManager.setPortRoles(mPort, newPowerRole, role);
+            mPort.setRoles(newPowerRole, role);
         }
     }
 
     public boolean areAllRolesSupported() {
         return mPort != null && mPortStatus != null
-                && mPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE)
-                && mPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST)
-                && mPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE)
-                && mPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+                && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE)
+                && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST)
+                && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE)
+                && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST);
     }
 
     public static String usbFunctionsToString(long functions) {
@@ -205,17 +210,14 @@
     private void updatePorts() {
         mPort = null;
         mPortStatus = null;
-        UsbPort[] ports = mUsbManager.getPorts();
-        if (ports == null) {
-            return;
-        }
+        List<UsbPort> ports = mUsbManager.getPorts();
         // For now look for a connected port, in the future we should identify port in the
         // notification and pick based on that.
-        final int N = ports.length;
+        final int N = ports.size();
         for (int i = 0; i < N; i++) {
-            UsbPortStatus status = mUsbManager.getPortStatus(ports[i]);
+            UsbPortStatus status = ports.get(i).getStatus();
             if (status.isConnected()) {
-                mPort = ports[i];
+                mPort = ports.get(i);
                 mPortStatus = status;
                 break;
             }
diff --git a/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java b/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
index 1d43371..beb2375 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
@@ -49,8 +49,8 @@
         mUsbBackend = backend;
 
         mFunctions = UsbManager.FUNCTION_NONE;
-        mDataRole = UsbPort.DATA_ROLE_NONE;
-        mPowerRole = UsbPort.POWER_ROLE_NONE;
+        mDataRole = UsbPortStatus.DATA_ROLE_NONE;
+        mPowerRole = UsbPortStatus.POWER_ROLE_NONE;
     }
 
     @Override
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java
index 84576b1..a584c11 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java
@@ -16,6 +16,10 @@
 
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+
 import android.content.Context;
 import android.hardware.usb.UsbPort;
 
@@ -55,23 +59,23 @@
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         mPreferenceCategory = (PreferenceCategory) screen.findPreference(getPreferenceKey());
-        mHostPref = makeRadioPreference(UsbBackend.dataRoleToString(UsbPort.DATA_ROLE_HOST),
+        mHostPref = makeRadioPreference(UsbBackend.dataRoleToString(DATA_ROLE_HOST),
                 R.string.usb_control_host);
-        mDevicePref = makeRadioPreference(UsbBackend.dataRoleToString(UsbPort.DATA_ROLE_DEVICE),
+        mDevicePref = makeRadioPreference(UsbBackend.dataRoleToString(DATA_ROLE_DEVICE),
                 R.string.usb_control_device);
     }
 
     @Override
     protected void refresh(boolean connected, long functions, int powerRole, int dataRole) {
-        if (dataRole == UsbPort.DATA_ROLE_DEVICE) {
+        if (dataRole == DATA_ROLE_DEVICE) {
             mDevicePref.setChecked(true);
             mHostPref.setChecked(false);
             mPreferenceCategory.setEnabled(true);
-        } else if (dataRole == UsbPort.DATA_ROLE_HOST) {
+        } else if (dataRole == DATA_ROLE_HOST) {
             mDevicePref.setChecked(false);
             mHostPref.setChecked(true);
             mPreferenceCategory.setEnabled(true);
-        } else if (!connected || dataRole == UsbPort.DATA_ROLE_NONE){
+        } else if (!connected || dataRole == DATA_ROLE_NONE){
             mPreferenceCategory.setEnabled(false);
             if (mNextRolePref == null) {
                 // Disconnected with no operation pending, so clear subtexts
@@ -80,7 +84,7 @@
             }
         }
 
-        if (mNextRolePref != null && dataRole != UsbPort.DATA_ROLE_NONE) {
+        if (mNextRolePref != null && dataRole != DATA_ROLE_NONE) {
             if (UsbBackend.dataRoleFromString(mNextRolePref.getKey()) == dataRole) {
                 // Clear switching text if switch succeeded
                 mNextRolePref.setSummary("");
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
index f74dc0f..283e56b 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
 import static android.net.ConnectivityManager.TETHERING_USB;
 
 import android.content.Context;
@@ -88,7 +89,7 @@
 
     @Override
     protected void refresh(boolean connected, long functions, int powerRole, int dataRole) {
-        if (!connected || dataRole != UsbPort.DATA_ROLE_DEVICE) {
+        if (!connected || dataRole != DATA_ROLE_DEVICE) {
             mProfilesContainer.setEnabled(false);
         } else {
             // Functions are only available in device mode
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
index 30314f6..b59890a 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
@@ -16,8 +16,13 @@
 
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+
 import android.content.Context;
 import android.hardware.usb.UsbPort;
+import android.hardware.usb.UsbPortStatus;
 
 import androidx.preference.Preference;
 import androidx.preference.Preference.OnPreferenceClickListener;
@@ -40,16 +45,16 @@
     private int mNextPowerRole;
 
     private final Runnable mFailureCallback = () -> {
-        if (mNextPowerRole != UsbPort.POWER_ROLE_NONE) {
+        if (mNextPowerRole != POWER_ROLE_NONE) {
             mSwitchPreference.setSummary(R.string.usb_switching_failed);
-            mNextPowerRole = UsbPort.POWER_ROLE_NONE;
+            mNextPowerRole = POWER_ROLE_NONE;
         }
     };
 
     public UsbDetailsPowerRoleController(Context context, UsbDetailsFragment fragment,
             UsbBackend backend) {
         super(context, fragment, backend);
-        mNextPowerRole = UsbPort.POWER_ROLE_NONE;
+        mNextPowerRole = POWER_ROLE_NONE;
     }
 
     @Override
@@ -70,20 +75,21 @@
         } else if (connected && mUsbBackend.areAllRolesSupported()){
             mFragment.getPreferenceScreen().addPreference(mPreferenceCategory);
         }
-        if (powerRole == UsbPort.POWER_ROLE_SOURCE) {
+        if (powerRole == POWER_ROLE_SOURCE) {
             mSwitchPreference.setChecked(true);
             mPreferenceCategory.setEnabled(true);
-        } else if (powerRole == UsbPort.POWER_ROLE_SINK) {
+        } else if (powerRole == POWER_ROLE_SINK) {
             mSwitchPreference.setChecked(false);
             mPreferenceCategory.setEnabled(true);
-        } else if (!connected || powerRole == UsbPort.POWER_ROLE_NONE){
+        } else if (!connected || powerRole == POWER_ROLE_NONE){
             mPreferenceCategory.setEnabled(false);
-            if (mNextPowerRole == UsbPort.POWER_ROLE_NONE) {
+            if (mNextPowerRole == POWER_ROLE_NONE) {
                 mSwitchPreference.setSummary("");
             }
         }
 
-        if (mNextPowerRole != UsbPort.POWER_ROLE_NONE && powerRole != UsbPort.POWER_ROLE_NONE) {
+        if (mNextPowerRole != POWER_ROLE_NONE
+                && powerRole != POWER_ROLE_NONE) {
             if (mNextPowerRole == powerRole) {
                 // Clear switching text if switch succeeded
                 mSwitchPreference.setSummary("");
@@ -91,16 +97,16 @@
                 // Set failure text if switch failed
                 mSwitchPreference.setSummary(R.string.usb_switching_failed);
             }
-            mNextPowerRole = UsbPort.POWER_ROLE_NONE;
+            mNextPowerRole = POWER_ROLE_NONE;
             mHandler.removeCallbacks(mFailureCallback);
         }
     }
 
     @Override
     public boolean onPreferenceClick(Preference preference) {
-        int newRole = mSwitchPreference.isChecked() ? UsbPort.POWER_ROLE_SOURCE
-                : UsbPort.POWER_ROLE_SINK;
-        if (mUsbBackend.getPowerRole() != newRole && mNextPowerRole == UsbPort.POWER_ROLE_NONE
+        int newRole = mSwitchPreference.isChecked() ? POWER_ROLE_SOURCE
+                : POWER_ROLE_SINK;
+        if (mUsbBackend.getPowerRole() != newRole && mNextPowerRole == POWER_ROLE_NONE
                 && !Utils.isMonkeyRunning()) {
             mUsbBackend.setPowerRole(newRole);
 
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index b350778..7f14c0d 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -27,4 +27,5 @@
     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";
+    public static final String SLICE_INJECTION = "settings_slice_injection";
 }
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 56e9ee5..1916110 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -295,7 +295,13 @@
                 if (!controller.isAvailable()) {
                     continue;
                 }
+
                 final String key = controller.getPreferenceKey();
+                if (TextUtils.isEmpty(key)) {
+                    Log.d(TAG, String.format("Preference key is %s in Controller %s",
+                            key, controller.getClass().getSimpleName()));
+                    continue;
+                }
 
                 final Preference preference = screen.findPreference(key);
                 if (preference == null) {
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index 6f5f346..462f6d9 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -16,6 +16,10 @@
 
 package com.android.settings.deviceinfo;
 
+import static android.content.Context.CLIPBOARD_SERVICE;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
 import android.content.Context;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -23,6 +27,7 @@
 import android.text.BidiFormatter;
 import android.text.TextDirectionHeuristics;
 import android.text.TextUtils;
+import android.widget.Toast;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -30,12 +35,14 @@
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.slices.Copyable;
 import com.android.settingslib.DeviceInfoUtils;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class PhoneNumberPreferenceController extends BasePreferenceController {
+public class PhoneNumberPreferenceController extends BasePreferenceController implements
+        Copyable {
 
     private final static String KEY_PHONE_NUMBER = "phone_number";
 
@@ -46,7 +53,7 @@
     public PhoneNumberPreferenceController(Context context, String key) {
         super(context, key);
         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
-        mSubscriptionManager =  mContext.getSystemService(SubscriptionManager.class);
+        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
     }
 
     @Override
@@ -91,6 +98,17 @@
         return true;
     }
 
+    @Override
+    public void copy() {
+        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
+                CLIPBOARD_SERVICE);
+        clipboard.setPrimaryClip(ClipData.newPlainText("text", getFirstPhoneNumber()));
+
+        final String toast = mContext.getString(R.string.copyable_slice_toast,
+                mContext.getText(R.string.status_number));
+        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
+    }
+
     private CharSequence getFirstPhoneNumber() {
         final List<SubscriptionInfo> subscriptionInfoList =
                 mSubscriptionManager.getActiveSubscriptionInfoList();
diff --git a/src/com/android/settings/display/TopLevelDisplayPreferenceController.java b/src/com/android/settings/display/TopLevelDisplayPreferenceController.java
index 88b87e0..ed85a4a 100644
--- a/src/com/android/settings/display/TopLevelDisplayPreferenceController.java
+++ b/src/com/android/settings/display/TopLevelDisplayPreferenceController.java
@@ -29,7 +29,9 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return AVAILABLE;
+        return mContext.getResources().getBoolean(R.bool.config_show_top_level_display)
+        ? AVAILABLE
+        : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/BatterySaverController.java b/src/com/android/settings/fuelgauge/BatterySaverController.java
index 28cc893..cd32c6c 100644
--- a/src/com/android/settings/fuelgauge/BatterySaverController.java
+++ b/src/com/android/settings/fuelgauge/BatterySaverController.java
@@ -15,6 +15,7 @@
  */
 package com.android.settings.fuelgauge;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.os.Handler;
@@ -22,6 +23,7 @@
 import android.os.PowerManager;
 import android.provider.Settings;
 
+import android.provider.Settings.Global;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
@@ -31,6 +33,7 @@
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.fuelgauge.BatterySaverUtils;
 
 public class BatterySaverController extends BasePreferenceController
         implements LifecycleObserver, OnStart, OnStop, BatterySaverReceiver.BatterySaverListener {
@@ -45,6 +48,7 @@
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mBatteryStateChangeReceiver = new BatterySaverReceiver(context);
         mBatteryStateChangeReceiver.setBatterySaverListener(this);
+        BatterySaverUtils.revertScheduleToNoneIfNeeded(context);
     }
 
     @Override
@@ -81,16 +85,23 @@
 
     @Override
     public CharSequence getSummary() {
+        final ContentResolver resolver = mContext.getContentResolver();
         final boolean isPowerSaveOn = mPowerManager.isPowerSaveMode();
-        final int percent = Settings.Global.getInt(mContext.getContentResolver(),
+        final int percent = Settings.Global.getInt(resolver,
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        final int mode = Settings.Global.getInt(resolver,
+                Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
         if (isPowerSaveOn) {
             return mContext.getString(R.string.battery_saver_on_summary);
-        } else if (percent != 0) {
-            return mContext.getString(R.string.battery_saver_off_scheduled_summary,
-                    Utils.formatPercentage(percent));
+        } else if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
+            if (percent != 0) {
+                return mContext.getString(R.string.battery_saver_off_scheduled_summary,
+                        Utils.formatPercentage(percent));
+            } else {
+                return mContext.getString(R.string.battery_saver_off_summary);
+            }
         } else {
-            return mContext.getString(R.string.battery_saver_off_summary);
+            return mContext.getString(R.string.battery_saver_auto_routine);
         }
     }
 
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index c071284..6f77953 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -449,12 +449,14 @@
         final BatteryStats stats = statsHelper.getStats();
         BatteryInfo batteryInfo;
 
-        final Estimate estimate;
+        Estimate estimate = null;
         // Get enhanced prediction if available
         if (mPowerUsageFeatureProvider != null &&
                 mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(mContext)) {
             estimate = mPowerUsageFeatureProvider.getEnhancedBatteryPrediction(mContext);
-        } else {
+        }
+
+        if (estimate == null) {
             estimate = new Estimate(
                     PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)),
                     false /* isBasedOnUsage */,
diff --git a/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java b/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
index 8205818..ce85be8 100644
--- a/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
@@ -48,7 +48,9 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return AVAILABLE_UNSEARCHABLE;
+        return mContext.getResources().getBoolean(R.bool.config_show_top_level_battery)
+        ? AVAILABLE_UNSEARCHABLE
+        : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySaverPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySaverPreferenceController.java
deleted file mode 100644
index c0ecbf9..0000000
--- a/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySaverPreferenceController.java
+++ /dev/null
@@ -1,70 +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.fuelgauge.batterysaver;
-
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.core.TogglePreferenceController;
-import com.android.settingslib.fuelgauge.BatterySaverUtils;
-
-/**
- * Controller that update whether to turn on battery saver automatically
- */
-public class AutoBatterySaverPreferenceController extends TogglePreferenceController implements
-        Preference.OnPreferenceChangeListener {
-
-    /**
-     * Default value for {@link Settings.Global#LOW_POWER_MODE_TRIGGER_LEVEL}.
-     */
-    static final int DEFAULT_TRIGGER_LEVEL = 0;
-
-    /**
-     * The default value to set to {@link Settings.Global#LOW_POWER_MODE_TRIGGER_LEVEL} when the
-     * user enables battery saver.
-     */
-    private final int mDefaultTriggerLevelForOn;
-
-    @VisibleForTesting
-    static final String KEY_AUTO_BATTERY_SAVER = "auto_battery_saver";
-
-    public AutoBatterySaverPreferenceController(Context context) {
-        super(context, KEY_AUTO_BATTERY_SAVER);
-        mDefaultTriggerLevelForOn = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_lowBatteryWarningLevel);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
-    }
-
-    @Override
-    public boolean isChecked() {
-        return Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, DEFAULT_TRIGGER_LEVEL) != 0;
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        BatterySaverUtils.setAutoBatterySaverTriggerLevel(mContext,
-                isChecked ? mDefaultTriggerLevelForOn : 0);
-        return true;
-    }
-}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java
deleted file mode 100644
index 0fbba0b..0000000
--- a/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java
+++ /dev/null
@@ -1,166 +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.fuelgauge.batterysaver;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settings.widget.SeekBarPreference;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
-
-/**
- * Controller that update the battery saver seekbar
- */
-public class AutoBatterySeekBarPreferenceController extends BasePreferenceController implements
-        LifecycleObserver, OnStart, OnStop, SeekBarPreference.OnPreferenceChangeListener {
-    private static final String TAG = "AutoBatterySeekBarPreferenceController";
-    private static final int INTERVAL = 5;
-    @VisibleForTesting
-    static final String KEY_AUTO_BATTERY_SEEK_BAR = "battery_saver_seek_bar";
-    private SeekBarPreference mPreference;
-    private AutoBatterySaverSettingObserver mContentObserver;
-
-    public AutoBatterySeekBarPreferenceController(Context context, Lifecycle lifecycle) {
-        super(context, KEY_AUTO_BATTERY_SEEK_BAR);
-        mContentObserver = new AutoBatterySaverSettingObserver(new Handler(Looper.getMainLooper()));
-        if (lifecycle != null) {
-            lifecycle.addObserver(this);
-        }
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mPreference = (SeekBarPreference) screen.findPreference(
-                KEY_AUTO_BATTERY_SEEK_BAR);
-        mPreference.setContinuousUpdates(true);
-        mPreference.setAccessibilityRangeInfoType(
-                AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_PERCENT);
-        updatePreference(mPreference);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        super.updateState(preference);
-        updatePreference(preference);
-    }
-
-    @Override
-    public void onStart() {
-        mContentObserver.registerContentObserver();
-    }
-
-    @Override
-    public void onStop() {
-        mContentObserver.unRegisterContentObserver();
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        final int progress = (int) newValue;
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, progress * INTERVAL);
-        return true;
-    }
-
-    @VisibleForTesting
-    void updatePreference(Preference preference) {
-        final ContentResolver contentResolver = mContext.getContentResolver();
-
-        // Override the max value with LOW_POWER_MODE_TRIGGER_LEVEL_MAX, if set.
-        final int maxLevel = Settings.Global.getInt(contentResolver,
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0) / INTERVAL;
-        if (maxLevel > 0) {
-            if (!(preference instanceof SeekBarPreference)) {
-                Log.e(TAG, "Unexpected preference class: " + preference.getClass());
-            } else {
-                final SeekBarPreference seekBarPreference = (SeekBarPreference) preference;
-                if (maxLevel < seekBarPreference.getMin()) {
-                    Log.e(TAG, "LOW_POWER_MODE_TRIGGER_LEVEL_MAX too low; ignored.");
-                } else {
-                    seekBarPreference.setMax(maxLevel);
-                }
-            }
-        }
-
-        // Set the current value.
-        final int level = Settings.Global.getInt(contentResolver,
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL,
-                AutoBatterySaverPreferenceController.DEFAULT_TRIGGER_LEVEL);
-        if (level == 0) {
-            preference.setVisible(false);
-        } else {
-            preference.setVisible(true);
-            preference.setTitle(mContext.getString(R.string.battery_saver_seekbar_title,
-                    Utils.formatPercentage(level)));
-            SeekBarPreference seekBarPreference = (SeekBarPreference) preference;
-            seekBarPreference.setProgress(level / INTERVAL);
-            seekBarPreference.setSeekBarContentDescription(
-                    mContext.getString(R.string.battery_saver_turn_on_automatically_title));
-        }
-    }
-
-    /**
-     * Observer that listens to change from {@link Settings.Global#LOW_POWER_MODE_TRIGGER_LEVEL}
-     */
-    private final class AutoBatterySaverSettingObserver extends ContentObserver {
-        private final Uri mUri = Settings.Global.getUriFor(
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL);
-        private final ContentResolver mContentResolver;
-
-        public AutoBatterySaverSettingObserver(Handler handler) {
-            super(handler);
-            mContentResolver = mContext.getContentResolver();
-        }
-
-        public void registerContentObserver() {
-            mContentResolver.registerContentObserver(mUri, false, this);
-        }
-
-        public void unRegisterContentObserver() {
-            mContentResolver.unregisterContentObserver(this);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri, int userId) {
-            if (mUri.equals(uri)) {
-                updatePreference(mPreference);
-            }
-        }
-    }
-}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java
index cc6aa00..868c73f 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java
@@ -26,7 +26,13 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.fuelgauge.BatterySaverUtils;
 
+/**
+ * Simple controller to navigate users to the scheduling page from
+ * "Settings > Battery > Battery Saver". Also updates the summary for preference based on
+ * the currently selected settings.
+ */
 public class BatterySaverSchedulePreferenceController extends BasePreferenceController {
 
     @VisibleForTesting
@@ -36,6 +42,7 @@
 
     public BatterySaverSchedulePreferenceController(Context context) {
         super(context, KEY_BATTERY_SAVER_SCHEDULE);
+        BatterySaverUtils.revertScheduleToNoneIfNeeded(context);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
new file mode 100644
index 0000000..d49eb0a
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge.batterysaver;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+
+/**
+ * Responds to user actions in the Settings > Battery > Set a Schedule Screen
+ *
+ * Note that this is not a preference controller since that screen does not inherit from
+ * DashboardFragment.
+ *
+ * Will call the appropriate power manager APIs and modify the correct settings to enable
+ * users to control their automatic battery saver toggling preferences.
+ * See {@link Settings.Global#AUTOMATIC_POWER_SAVER_MODE} for more details.
+ */
+public class BatterySaverScheduleRadioButtonsController {
+
+    public static final String KEY_NO_SCHEDULE = "key_battery_saver_no_schedule";
+    public static final String KEY_ROUTINE = "key_battery_saver_routine";
+    public static final String KEY_PERCENTAGE = "key_battery_saver_percentage";
+
+    private Context mContext;
+    private BatterySaverScheduleSeekBarController mSeekBarController;
+
+    public BatterySaverScheduleRadioButtonsController(Context context,
+            BatterySaverScheduleSeekBarController seekbar) {
+        mContext = context;
+        mSeekBarController = seekbar;
+    }
+
+    public String getDefaultKey() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        // Note: this can also be obtained via PowerManager.getPowerSaveMode()
+        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        // if mode is "dynamic" we are in routine mode, percentage with non-zero threshold is
+        // percentage mode, otherwise it is no schedule mode
+        if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
+            final int threshold =
+                    Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+            if (threshold <= 0) {
+                return KEY_NO_SCHEDULE;
+            }
+            return KEY_PERCENTAGE;
+        }
+        return KEY_ROUTINE;
+    }
+
+    public boolean setDefaultKey(String key) {
+        final ContentResolver resolver = mContext.getContentResolver();
+        switch(key) {
+            case KEY_NO_SCHEDULE:
+                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                        PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+                Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+                break;
+            case KEY_PERCENTAGE:
+                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                        PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+                Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
+                break;
+            case KEY_ROUTINE:
+                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                        PowerManager.POWER_SAVER_MODE_DYNAMIC);
+                break;
+            default:
+                throw new IllegalStateException(
+                        "Not a valid key for " + this.getClass().getSimpleName());
+        }
+        mSeekBarController.updateSeekBar();
+        return true;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
new file mode 100644
index 0000000..215f400
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
@@ -0,0 +1,100 @@
+/*
+ * 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.fuelgauge.batterysaver;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.PreferenceScreen;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.widget.SeekBarPreference;
+
+/**
+ * Responds to user actions in the Settings > Battery > Set a Schedule Screen for the seekbar.
+ * Note that this seekbar is only visible when the radio button selected is "Percentage".
+ *
+ * Note that this is not a preference controller since that screen does not inherit from
+ * DashboardFragment.
+ *
+ * Will call the appropriate power manager APIs and modify the correct settings to enable
+ * users to control their automatic battery saver toggling preferences.
+ * See {@link Settings.Global#AUTOMATIC_POWER_SAVER_MODE} for more details.
+ */
+public class BatterySaverScheduleSeekBarController implements
+        OnPreferenceChangeListener {
+
+    public static final int MAX_SEEKBAR_VALUE = 15;
+    public static final int MIN_SEEKBAR_VALUE = 1;
+    public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
+
+    @VisibleForTesting
+    public SeekBarPreference mSeekBarPreference;
+    private Context mContext;
+
+    public BatterySaverScheduleSeekBarController(Context context) {
+        mContext = context;
+        mSeekBarPreference = new SeekBarPreference(context);
+        mSeekBarPreference.setOnPreferenceChangeListener(this);
+        mSeekBarPreference.setMax(BatterySaverScheduleSeekBarController.MAX_SEEKBAR_VALUE);
+        mSeekBarPreference.setMin(BatterySaverScheduleSeekBarController.MIN_SEEKBAR_VALUE);
+        mSeekBarPreference.setKey(KEY_BATTERY_SAVER_SEEK_BAR);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        // The nits are in intervals of 5%
+        final int percentage = ((Integer) newValue) * 5;
+        Settings.Global.putInt(mContext.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL,
+                percentage);
+        preference.setTitle(mContext.getString(
+                R.string.battery_saver_seekbar_title, Utils.formatPercentage(percentage)));
+        return true;
+    }
+
+    public void updateSeekBar() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        // Note: this can also be obtained via PowerManager.getPowerSaveMode()
+        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        // if mode is "dynamic" we are in routine mode, percentage with non-zero threshold is
+        // percentage mode, otherwise it is no schedule mode
+        if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
+            final int threshold =
+                    Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+            if (threshold <= 0) {
+                mSeekBarPreference.setVisible(false);
+            } else {
+                mSeekBarPreference.setVisible(true);
+                mSeekBarPreference.setProgress(MIN_SEEKBAR_VALUE);
+                mSeekBarPreference.setTitle(mContext.getString(
+                        R.string.battery_saver_seekbar_title,
+                        Utils.formatPercentage(MIN_SEEKBAR_VALUE * 5)));
+            }
+        } else {
+            mSeekBarPreference.setVisible(false);
+        }
+    }
+
+    public void addToScreen(PreferenceScreen screen) {
+        screen.addPreference(mSeekBarPreference);
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
index fad9f31..6e9c711 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
@@ -18,24 +18,32 @@
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.text.TextUtils;
 import android.view.View;
 import androidx.preference.PreferenceScreen;
 import com.android.settings.widget.RadioButtonPickerFragment;
 import com.android.settings.R;
 import com.android.settings.widget.RadioButtonPreference;
-import com.android.settings.widget.SeekBarPreference;
+import com.android.settingslib.fuelgauge.BatterySaverUtils;
 import com.android.settingslib.widget.CandidateInfo;
 import com.google.common.collect.Lists;
 import java.util.List;
 
+/**
+ * Fragment that allows users to customize their automatic battery saver mode settings.
+ *
+ * Location: Settings > Battery > Battery Saver > Set a Schedule
+ * See {@link BatterySaverSchedulePreferenceController} for the controller that manages navigation
+ * to this screen from "Settings > Battery > Battery Saver" and the summary.
+ * See {@link BatterySaverScheduleRadioButtonsController} &
+ * {@link BatterySaverScheduleSeekBarController} for the controller that manages user
+ * interactions in this screen.
+ */
 public class BatterySaverScheduleSettings extends RadioButtonPickerFragment {
 
-    private static final String KEY_NO_SCHEDULE = "key_battery_saver_no_schedule";
-    private static final String KEY_ROUTINE = "key_battery_saver_routine";
-    private static final String KEY_PERCENTAGE = "key_battery_saver_percentage";
-    public static final int MAX_SEEKBAR_VALUE = 15;
-    public static final int MIN_SEEKBAR_VALUE = 1;
-    public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
+    public BatterySaverScheduleRadioButtonsController mRadioButtonController;
+    private BatterySaverScheduleSeekBarController mSeekBarController;
 
     @Override
     protected int getPreferenceScreenResId() {
@@ -43,23 +51,44 @@
     }
 
     @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mSeekBarController = new BatterySaverScheduleSeekBarController(context);
+        mRadioButtonController = new BatterySaverScheduleRadioButtonsController(
+                context, mSeekBarController);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
     protected List<? extends CandidateInfo> getCandidates() {
         Context context = getContext();
         List<CandidateInfo> candidates = Lists.newArrayList();
+        String routineProviderApp = getContext().getResources()
+                .getString(com.android.internal.R.string.config_batterySaverScheduleProvider);
         candidates.add(new BatterySaverScheduleCandidateInfo(
                 context.getText(R.string.battery_saver_auto_no_schedule),
                 /* summary */ null,
-                KEY_NO_SCHEDULE,
+                BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE,
                 /* enabled */ true));
-        candidates.add(new BatterySaverScheduleCandidateInfo(
-                context.getText(R.string.battery_saver_auto_routine),
-                context.getText(R.string.battery_saver_auto_routine_summary),
-                KEY_ROUTINE,
-                /* enabled */ true));
+        // only add routine option if an app has been specified
+        if (!TextUtils.isEmpty(routineProviderApp)) {
+            candidates.add(new BatterySaverScheduleCandidateInfo(
+                    context.getText(R.string.battery_saver_auto_routine),
+                    context.getText(R.string.battery_saver_auto_routine_summary),
+                    BatterySaverScheduleRadioButtonsController.KEY_ROUTINE,
+                    /* enabled */ true));
+        } else {
+            // Make sure routine is not selected if no provider app is configured
+            BatterySaverUtils.revertScheduleToNoneIfNeeded(context);
+        }
         candidates.add(new BatterySaverScheduleCandidateInfo(
                 context.getText(R.string.battery_saver_auto_percentage),
                 /* summary */ null,
-                KEY_PERCENTAGE,
+                BatterySaverScheduleRadioButtonsController.KEY_PERCENTAGE,
                 /* enabled */ true));
 
         return candidates;
@@ -79,22 +108,18 @@
 
     @Override
     protected void addStaticPreferences(PreferenceScreen screen) {
-        SeekBarPreference seekbar = new SeekBarPreference(getContext());
-        seekbar.setMax(MAX_SEEKBAR_VALUE);
-        seekbar.setMin(MIN_SEEKBAR_VALUE);
-        seekbar.setTitle(R.string.battery_saver_seekbar_title_placeholder);
-        seekbar.setKey(KEY_BATTERY_SAVER_SEEK_BAR);
-        screen.addPreference(seekbar);
+        mSeekBarController.updateSeekBar();
+        mSeekBarController.addToScreen(screen);
     }
 
     @Override
     protected String getDefaultKey() {
-        return null;
+        return mRadioButtonController.getDefaultKey();
     }
 
     @Override
     protected boolean setDefaultKey(String key) {
-        return false;
+        return mRadioButtonController.setDefaultKey(key);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
index 8b0409c..6aef9b5 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
@@ -61,23 +61,10 @@
     }
 
     @Override
-    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
-        return buildPreferenceControllers(context, getSettingsLifecycle());
-    }
-
-    @Override
     public int getHelpResource() {
         return R.string.help_url_battery_saver_settings;
     }
 
-    private static List<AbstractPreferenceController> buildPreferenceControllers(
-            Context context, Lifecycle lifecycle) {
-        final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(new AutoBatterySaverPreferenceController(context));
-        controllers.add(new AutoBatterySeekBarPreferenceController(context, lifecycle));
-        return controllers;
-    }
-
     /**
      * For Search.
      */
@@ -90,11 +77,5 @@
                     sir.xmlResId = R.xml.battery_saver_settings;
                     return Arrays.asList(sir);
                 }
-
-                @Override
-                public List<AbstractPreferenceController> createPreferenceControllers(
-                        Context context) {
-                    return buildPreferenceControllers(context, null);
-                }
             };
 }
diff --git a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
index 164afdd..b9bab21 100644
--- a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
@@ -197,12 +197,11 @@
     }
 
     Cursor getContextualCards() {
-        final SQLiteDatabase db = this.getReadableDatabase();
+        final SQLiteDatabase db = getReadableDatabase();
         final String selection = CardColumns.CARD_DISMISSED + "=0";
-        Cursor cursor = db.query(CARD_TABLE, null /* columns */, selection,
+        return db.query(CARD_TABLE, null /* columns */, selection,
                 null /* selectionArgs */, null /* groupBy */, null /* having */,
                 CardColumns.SCORE + " DESC" /* orderBy */);
-        return cursor;
     }
 
     /**
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
index 5ebc924..b1e9d33 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
@@ -16,24 +16,21 @@
 
 package com.android.settings.homepage.contextualcards;
 
-import android.content.Context;
-
 import java.util.List;
 
 /** Feature provider for the contextual card feature. */
 public interface ContextualCardFeatureProvider {
 
     /** Homepage displays. */
-    void logHomepageDisplay(Context context, long latency);
+    void logHomepageDisplay(long latency);
 
     /** When user clicks dismiss in contextual card */
-    void logContextualCardDismiss(Context context, ContextualCard card);
+    void logContextualCardDismiss(ContextualCard card);
 
     /** After ContextualCardManager decides which cards will be displayed/hidden */
-    void logContextualCardDisplay(Context context, List<ContextualCard> showedCards,
+    void logContextualCardDisplay(List<ContextualCard> showedCards,
             List<ContextualCard> hiddenCards);
 
     /** When user clicks toggle/title area of a contextual card. */
-    void logContextualCardClick(Context context, ContextualCard card, int row,
-            int tapTarget);
+    void logContextualCardClick(ContextualCard card, int row, int tapTarget);
 }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
index dc295fc..12590ff 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
@@ -51,6 +51,9 @@
     // contextual card name
     private static final String EXTRA_CONTEXTUALCARD_NAME = "name";
 
+    // contextual card uri
+    private static final String EXTRA_CONTEXTUALCARD_URI = "uri";
+
     // contextual card score
     private static final String EXTRA_CONTEXTUALCARD_SCORE = "score";
 
@@ -84,51 +87,59 @@
     // Click slider
     private static final int TARGET_SLIDER = 3;
 
+    private final Context mContext;
+
+    public ContextualCardFeatureProviderImpl(Context context) {
+        mContext = context;
+    }
+
     @Override
-    public void logHomepageDisplay(Context context, long latency) {
-        sendBroadcast(context, new Intent()
+    public void logHomepageDisplay(long latency) {
+        sendBroadcast(new Intent()
                 .putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_HOME_SHOW)
                 .putExtra(EXTRA_LATENCY, latency));
     }
 
     @Override
-    public void logContextualCardDismiss(Context context, ContextualCard card) {
+    public void logContextualCardDismiss(ContextualCard card) {
         final Intent intent = new Intent();
         intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_DISMISS);
         intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
+        intent.putExtra(EXTRA_CONTEXTUALCARD_URI, card.getSliceUri().toString());
         intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
-        sendBroadcast(context, intent);
+        sendBroadcast(intent);
     }
 
     @Override
-    public void logContextualCardDisplay(Context context, List<ContextualCard> visibleCards,
+    public void logContextualCardDisplay(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);
+        sendBroadcast(intent);
     }
 
     @Override
-    public void logContextualCardClick(Context context, ContextualCard card, int row,
+    public void logContextualCardClick(ContextualCard card, int row,
             int actionType) {
         final Intent intent = new Intent();
         intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_CLICK);
         intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
+        intent.putExtra(EXTRA_CONTEXTUALCARD_URI, card.getSliceUri().toString());
         intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
         intent.putExtra(EXTRA_CONTEXTUALCARD_ROW, row);
         intent.putExtra(EXTRA_CONTEXTUALCARD_TAP_TARGET, actionTypeToTapTarget(actionType));
-        sendBroadcast(context, intent);
+        sendBroadcast(intent);
     }
 
     @VisibleForTesting
-    void sendBroadcast(final Context context, final Intent intent) {
-        intent.setPackage(context.getString(R.string.config_settingsintelligence_package_name));
-        final String action = context.getString(R.string.config_settingsintelligence_log_action);
+    void sendBroadcast(final Intent intent) {
+        intent.setPackage(mContext.getString(R.string.config_settingsintelligence_package_name));
+        final String action = mContext.getString(R.string.config_settingsintelligence_log_action);
         if (!TextUtils.isEmpty(action)) {
             intent.setAction(action);
-            context.sendBroadcastAsUser(intent, UserHandle.ALL);
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
         }
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 71b262d..88478e3 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -21,7 +21,7 @@
 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 static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI;
 
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
@@ -149,10 +149,10 @@
             // Two large cards
             return visibleCards;
         } finally {
+            //TODO(b/121196921): Should not call this if user click dismiss
             final ContextualCardFeatureProvider contextualCardFeatureProvider =
-                    FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
-            contextualCardFeatureProvider.logContextualCardDisplay(mContext, visibleCards,
-                    hiddenCards);
+                    FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
+            contextualCardFeatureProvider.logContextualCardDisplay(visibleCards, hiddenCards);
         }
     }
 
@@ -204,7 +204,7 @@
     }
 
     private boolean isLargeCard(ContextualCard card) {
-        return card.getSliceUri().equals(WIFI_SLICE_URI)
+        return card.getSliceUri().equals(CONTEXTUAL_WIFI_SLICE_URI)
                 || card.getSliceUri().equals(BLUETOOTH_DEVICES_SLICE_URI);
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 24266ee..067de7c 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -35,6 +35,7 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -56,7 +57,9 @@
  * get the page refreshed.
  */
 public class ContextualCardManager implements ContextualCardLoader.CardContentLoaderListener,
-        ContextualCardUpdateListener {
+        ContextualCardUpdateListener, LifecycleObserver, OnSaveInstanceState {
+
+    private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards";
 
     private static final String TAG = "ContextualCardManager";
 
@@ -68,6 +71,9 @@
     final List<ContextualCard> mContextualCards;
     @VisibleForTesting
     long mStartTime;
+    boolean mIsFirstLaunch;
+    @VisibleForTesting
+    List<String> mSavedCards;
 
     private final Context mContext;
     private final ControllerRendererPool mControllerRendererPool;
@@ -76,12 +82,20 @@
 
     private ContextualCardUpdateListener mListener;
 
-    public ContextualCardManager(Context context, Lifecycle lifecycle) {
+    public ContextualCardManager(Context context, Lifecycle lifecycle, Bundle savedInstanceState) {
         mContext = context;
         mLifecycle = lifecycle;
         mContextualCards = new ArrayList<>();
         mLifecycleObservers = new ArrayList<>();
         mControllerRendererPool = new ControllerRendererPool();
+        mLifecycle.addObserver(this);
+
+        if (savedInstanceState == null) {
+            mIsFirstLaunch = true;
+            mSavedCards = null;
+        } else {
+            mSavedCards = savedInstanceState.getStringArrayList(KEY_CONTEXTUAL_CARDS);
+        }
         //for data provided by Settings
         for (@ContextualCard.CardType int cardType : SETTINGS_CARDS) {
             setupController(cardType);
@@ -172,13 +186,34 @@
     @Override
     public void onFinishCardLoading(List<ContextualCard> cards) {
         final long loadTime = System.currentTimeMillis() - mStartTime;
+        final List<ContextualCard> cardsToKeep = getCardsToKeep(cards);
+
+        //navigate back to the homepage or after card dismissal
+        if (!mIsFirstLaunch) {
+            onContextualCardUpdated(cardsToKeep.stream()
+                    .collect(groupingBy(ContextualCard::getCardType)));
+            return;
+        }
+
+        //only log homepage display upon a fresh launch
         if (loadTime <= ContextualCardLoader.CARD_CONTENT_LOADER_TIMEOUT_MS) {
-            onContextualCardUpdated(
-                    cards.stream().collect(groupingBy(ContextualCard::getCardType)));
+            onContextualCardUpdated(cards.stream()
+                    .collect(groupingBy(ContextualCard::getCardType)));
         }
         final long totalTime = System.currentTimeMillis() - mStartTime;
-        FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider()
-                .logHomepageDisplay(mContext, totalTime);
+        FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext)
+                .logHomepageDisplay(totalTime);
+
+        mIsFirstLaunch = false;
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        final ArrayList<String> cards = mContextualCards.stream()
+                .map(ContextualCard::getName)
+                .collect(Collectors.toCollection(ArrayList::new));
+
+        outState.putStringArrayList(KEY_CONTEXTUAL_CARDS, cards);
     }
 
     public ControllerRendererPool getControllerRendererPool() {
@@ -189,6 +224,22 @@
         mListener = listener;
     }
 
+    private List<ContextualCard> getCardsToKeep(List<ContextualCard> cards) {
+        if (mSavedCards != null) {
+            //screen rotate
+            final List<ContextualCard> cardsToKeep = cards.stream()
+                    .filter(card -> mSavedCards.contains(card.getName()))
+                    .collect(Collectors.toList());
+            mSavedCards = null;
+            return cardsToKeep;
+        } else {
+            //navigate back to the homepage or after dismissing a card
+            return cards.stream()
+                    .filter(card -> mContextualCards.contains(card))
+                    .collect(Collectors.toList());
+        }
+    }
+
     static class CardContentLoaderCallbacks implements
             LoaderManager.LoaderCallbacks<List<ContextualCard>> {
 
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index 5f9bf0d..e598e4c 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -42,7 +42,8 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle());
+        mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle(),
+                savedInstanceState);
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index d5500fb..5797043 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -34,8 +34,8 @@
     public ContextualCardList getContextualCards() {
         final ContextualCard wifiCard =
                 ContextualCard.newBuilder()
-                        .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI.toString())
-                        .setCardName(CustomSliceRegistry.WIFI_SLICE_URI.toString())
+                        .setSliceUri(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString())
+                        .setCardName(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString())
                         .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
         final ContextualCard connectedDeviceCard =
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java
deleted file mode 100644
index bce7c5d..0000000
--- a/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java
+++ /dev/null
@@ -1,108 +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.conditional;
-
-import android.content.Context;
-import android.os.PowerManager;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.R;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.fuelgauge.BatterySaverReceiver;
-import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
-import com.android.settings.homepage.contextualcards.ContextualCard;
-import com.android.settingslib.fuelgauge.BatterySaverUtils;
-
-import java.util.Objects;
-
-public class BatterySaverConditionController implements ConditionalCardController,
-        BatterySaverReceiver.BatterySaverListener {
-    static final int ID = Objects.hash("BatterySaverConditionController");
-
-    private final Context mAppContext;
-    private final ConditionManager mConditionManager;
-    private final BatterySaverReceiver mReceiver;
-    private final PowerManager mPowerManager;
-
-    public BatterySaverConditionController(Context appContext, ConditionManager conditionManager) {
-        mAppContext = appContext;
-        mConditionManager = conditionManager;
-        mPowerManager = appContext.getSystemService(PowerManager.class);
-        mReceiver = new BatterySaverReceiver(appContext);
-        mReceiver.setBatterySaverListener(this);
-    }
-
-    @Override
-    public long getId() {
-        return ID;
-    }
-
-    @Override
-    public boolean isDisplayable() {
-        return mPowerManager.isPowerSaveMode();
-    }
-
-    @Override
-    public void onPrimaryClick(Context context) {
-        new SubSettingLauncher(context)
-                .setDestination(BatterySaverSettings.class.getName())
-                .setSourceMetricsCategory(MetricsProto.MetricsEvent.DASHBOARD_SUMMARY)
-                .setTitleRes(R.string.battery_saver)
-                .launch();
-    }
-
-    @Override
-    public void onActionClick() {
-        BatterySaverUtils.setPowerSaveMode(mAppContext, false,
-                /*needFirstTimeWarning*/ false);
-    }
-
-    @Override
-    public ContextualCard buildContextualCard() {
-        return new ConditionalContextualCard.Builder()
-                .setConditionId(ID)
-                .setMetricsConstant(MetricsProto.MetricsEvent.SETTINGS_CONDITION_BATTERY_SAVER)
-                .setActionText(mAppContext.getText(R.string.condition_turn_off))
-                .setName(mAppContext.getPackageName() + "/"
-                        + mAppContext.getText(R.string.condition_battery_title))
-                .setTitleText(mAppContext.getText(R.string.condition_battery_title).toString())
-                .setSummaryText(mAppContext.getText(R.string.condition_battery_summary).toString())
-                .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_battery_saver_accent_24dp))
-                .setIsHalfWidth(true)
-                .build();
-    }
-
-    @Override
-    public void startMonitoringStateChange() {
-        mReceiver.setListening(true);
-    }
-
-    @Override
-    public void stopMonitoringStateChange() {
-        mReceiver.setListening(false);
-    }
-
-    @Override
-    public void onPowerSaveModeChanged() {
-        mConditionManager.onConditionChanged();
-    }
-
-    @Override
-    public void onBatteryChanged(boolean pluggedIn) {
-
-    }
-}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
index c741b98..39f4903 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
@@ -154,7 +154,6 @@
         mCardControllers.add(new AirplaneModeConditionController(mAppContext, this /* manager */));
         mCardControllers.add(
                 new BackgroundDataConditionController(mAppContext, this /* manager */));
-        mCardControllers.add(new BatterySaverConditionController(mAppContext, this /* manager */));
         mCardControllers.add(new CellularDataConditionController(mAppContext, this /* manager */));
         mCardControllers.add(new DndConditionCardController(mAppContext, this /* manager */));
         mCardControllers.add(new HotspotConditionController(mAppContext, this /* manager */));
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
index 8720a3c..eb062e8 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
@@ -70,8 +70,8 @@
         });
         showFeedbackDialog(card);
         final ContextualCardFeatureProvider contextualCardFeatureProvider =
-                FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
-        contextualCardFeatureProvider.logContextualCardDismiss(mContext, card);
+                FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
+        contextualCardFeatureProvider.logContextualCardDismiss(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 172c3b2..17e9d48 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -173,8 +173,9 @@
             if (sliceItem.getSlice().getUri().toString().startsWith(
                     card.getSliceUri().toString())) {
                 ContextualCardFeatureProvider contexualCardFeatureProvider =
-                        FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
-                contexualCardFeatureProvider.logContextualCardClick(mContext, card,
+                        FeatureFactory.getFactory(mContext)
+                                .getContextualCardFeatureProvider(mContext);
+                contexualCardFeatureProvider.logContextualCardClick(card,
                         eventInfo.rowIndex, eventInfo.actionType);
                 break;
             }
diff --git a/src/com/android/settings/location/AppLocationPermissionPreferenceController.java b/src/com/android/settings/location/AppLocationPermissionPreferenceController.java
index f920fdc..5bfc584 100644
--- a/src/com/android/settings/location/AppLocationPermissionPreferenceController.java
+++ b/src/com/android/settings/location/AppLocationPermissionPreferenceController.java
@@ -1,18 +1,38 @@
 package com.android.settings.location;
 
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+
 import android.content.Context;
+import android.location.LocationManager;
+import android.permission.RuntimePermissionPresenter;
 import android.provider.Settings;
 
+import androidx.preference.Preference;
+
+import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class AppLocationPermissionPreferenceController extends
-        AbstractPreferenceController implements PreferenceControllerMixin {
+        LocationBasePreferenceController implements PreferenceControllerMixin {
 
     private static final String KEY_APP_LEVEL_PERMISSIONS = "app_level_permissions";
+    /** Total number of apps that has location permission. */
+    private int mNumTotal = -1;
+    /** Total number of apps that has background location permission. */
+    private int mNumBackground = -1;
+    private final LocationManager mLocationManager;
+    private Preference mPreference;
 
-    public AppLocationPermissionPreferenceController(Context context) {
-        super(context);
+    public AppLocationPermissionPreferenceController(Context context, Lifecycle lifecycle) {
+        super(context, lifecycle);
+        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
     }
 
     @Override
@@ -25,4 +45,53 @@
         return Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED, 1) == 1;
     }
+
+    @Override
+    public CharSequence getSummary() {
+        if (mLocationManager.isLocationEnabled()) {
+            if (mNumTotal == -1 || mNumBackground == -1) {
+                return mContext.getString(R.string.location_settings_loading_app_permission_stats);
+            }
+            return mContext.getResources().getQuantityString(
+                    R.plurals.location_app_permission_summary_location_on, mNumBackground,
+                    mNumBackground, mNumTotal);
+        } else {
+            return mContext.getString(R.string.location_app_permission_summary_location_off);
+        }
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        mPreference = preference;
+        final AtomicInteger loadingInProgress = new AtomicInteger(2);
+        refreshSummary(preference);
+        // Bail out if location has been disabled.
+        if (!mLocationManager.isLocationEnabled()) {
+            return;
+        }
+        RuntimePermissionPresenter.getInstance(mContext).countPermissionApps(
+                Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), false, false,
+                (numApps) -> {
+                    mNumTotal = numApps;
+                    if (loadingInProgress.decrementAndGet() == 0) {
+                        refreshSummary(preference);
+                    }
+                }, null);
+
+        RuntimePermissionPresenter.getInstance(mContext).countPermissionApps(
+                Collections.singletonList(ACCESS_BACKGROUND_LOCATION), true, false,
+                (numApps) -> {
+                    mNumBackground = numApps;
+                    if (loadingInProgress.decrementAndGet() == 0) {
+                        refreshSummary(preference);
+                    }
+                }, null);
+    }
+
+    @Override
+    public void onLocationModeChanged(int mode, boolean restricted) {
+        // 'null' is checked inside updateState(), so no need to check here.
+        updateState(mPreference);
+    }
 }
diff --git a/src/com/android/settings/location/LocationEnabler.java b/src/com/android/settings/location/LocationEnabler.java
index 20c2280..e1bdf16 100644
--- a/src/com/android/settings/location/LocationEnabler.java
+++ b/src/com/android/settings/location/LocationEnabler.java
@@ -35,15 +35,15 @@
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
 
 
 /**
  * A class that listens to location settings change and modifies location settings
  * settings.
  */
-public class LocationEnabler implements LifecycleObserver, OnResume, OnPause {
+public class LocationEnabler implements LifecycleObserver, OnStart, OnStop {
 
     private static final String TAG = "LocationEnabler";
     @VisibleForTesting
@@ -73,7 +73,7 @@
     }
 
     @Override
-    public void onResume() {
+    public void onStart() {
         if (mReceiver == null) {
             mReceiver = new BroadcastReceiver() {
                 @Override
@@ -90,12 +90,8 @@
     }
 
     @Override
-    public void onPause() {
-        try {
-            mContext.unregisterReceiver(mReceiver);
-        } catch (RuntimeException e) {
-            // Ignore exceptions caused by race condition
-        }
+    public void onStop() {
+        mContext.unregisterReceiver(mReceiver);
     }
 
     void refreshLocationMode() {
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 53076e8..4112340 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -35,7 +35,7 @@
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.location.RecentLocationApps;
+import com.android.settingslib.location.RecentLocationAccesses;
 import com.android.settingslib.search.SearchIndexable;
 
 import java.util.ArrayList;
@@ -52,7 +52,7 @@
  *         <li>In switch bar: location master switch. Used to toggle location on and off.
  *         </li>
  *     </ul>
- *     <li>Recent location requests: automatically populated by {@link RecentLocationApps}</li>
+ *     <li>Recent location requests: automatically populated by {@link RecentLocationAccesses}</li>
  *     <li>Location services: multi-app settings provided from outside the Android framework. Each
  *     is injected by a system-partition app via the {@link SettingInjectorService} API.</li>
  * </ul>
@@ -122,13 +122,11 @@
     private static List<AbstractPreferenceController> buildPreferenceControllers(
             Context context, LocationSettings fragment, Lifecycle lifecycle) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(new AppLocationPermissionPreferenceController(context));
+        controllers.add(new AppLocationPermissionPreferenceController(context, lifecycle));
         controllers.add(new LocationForWorkPreferenceController(context, lifecycle));
-        controllers.add(
-                new RecentLocationRequestPreferenceController(context, fragment, lifecycle));
+        controllers.add(new RecentLocationAccessPreferenceController(context));
         controllers.add(new LocationScanningPreferenceController(context));
-        controllers.add(
-                new LocationServicePreferenceController(context, fragment, lifecycle));
+        controllers.add(new LocationServicePreferenceController(context, fragment, lifecycle));
         controllers.add(new LocationFooterPreferenceController(context, lifecycle));
         return controllers;
     }
diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
new file mode 100644
index 0000000..0d5cca5
--- /dev/null
+++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
@@ -0,0 +1,103 @@
+/*
+ * 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.location;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.location.RecentLocationAccesses;
+import com.android.settingslib.widget.AppEntitiesHeaderController;
+import com.android.settingslib.widget.LayoutPreference;
+
+import java.util.List;
+
+public class RecentLocationAccessPreferenceController extends AbstractPreferenceController
+        implements PreferenceControllerMixin {
+    /** Key for the recent location apps dashboard */
+    private static final String KEY_APPS_DASHBOARD = "apps_dashboard";
+    private final RecentLocationAccesses mRecentLocationAccesses;
+    private AppEntitiesHeaderController mController;
+    private static final int MAXIMUM_APP_COUNT = 3;
+
+    public RecentLocationAccessPreferenceController(Context context) {
+        this(context, new RecentLocationAccesses(context));
+    }
+
+    @VisibleForTesting
+    RecentLocationAccessPreferenceController(Context context,
+            RecentLocationAccesses recentAccesses) {
+        super(context);
+        mRecentLocationAccesses = recentAccesses;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_APPS_DASHBOARD;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        final LayoutPreference preference = (LayoutPreference) screen.findPreference(
+                KEY_APPS_DASHBOARD);
+        final View view = preference.findViewById(R.id.app_entities_header);
+        mController = AppEntitiesHeaderController.newInstance(mContext, view)
+                .setHeaderTitleRes(R.string.location_category_recent_location_access)
+                .setHeaderDetailsRes(R.string.location_recent_location_access_view_details)
+                .setHeaderDetailsClickListener((View v) -> {
+                    final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
+                    intent.putExtra(Intent.EXTRA_PERMISSION_NAME,
+                            Manifest.permission.ACCESS_FINE_LOCATION);
+                    mContext.startActivity(intent);
+                });
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        updateRecentApps();
+    }
+
+    private void updateRecentApps() {
+        final List<RecentLocationAccesses.Access> recentLocationAccesses =
+                mRecentLocationAccesses.getAppListSorted();
+        if (recentLocationAccesses.size() > 0) {
+            // Display the top 3 preferences to container in original order.
+            int i = 0;
+            for (; i < Math.min(recentLocationAccesses.size(), MAXIMUM_APP_COUNT); i++) {
+                final RecentLocationAccesses.Access access = recentLocationAccesses.get(i);
+                mController.setAppEntity(i, access.icon, access.label, access.contentDescription);
+            }
+            for (; i < MAXIMUM_APP_COUNT; i++) {
+                mController.removeAppEntity(i);
+            }
+        } else {
+            // If there's no item to display, add a "No recent apps" item.
+        }
+        mController.apply();
+    }
+}
diff --git a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
deleted file mode 100644
index 60374eb..0000000
--- a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
+++ /dev/null
@@ -1,155 +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.location;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.os.UserHandle;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.location.RecentLocationApps;
-import com.android.settingslib.widget.apppreference.AppPreference;
-
-import java.util.List;
-
-public class RecentLocationRequestPreferenceController extends LocationBasePreferenceController {
-
-    /** Key for preference category "Recent location requests" */
-    private static final String KEY_RECENT_LOCATION_REQUESTS = "recent_location_requests";
-    @VisibleForTesting
-    static final String KEY_SEE_ALL_BUTTON = "recent_location_requests_see_all_button";
-    private final LocationSettings mFragment;
-    private final RecentLocationApps mRecentLocationApps;
-    private PreferenceCategory mCategoryRecentLocationRequests;
-    private Preference mSeeAllButton;
-
-    /** Used in this class and {@link RecentLocationRequestSeeAllPreferenceController} */
-    static class PackageEntryClickedListener implements Preference.OnPreferenceClickListener {
-        private final DashboardFragment mFragment;
-        private final String mPackage;
-        private final UserHandle mUserHandle;
-
-        public PackageEntryClickedListener(DashboardFragment fragment, String packageName,
-                UserHandle userHandle) {
-            mFragment = fragment;
-            mPackage = packageName;
-            mUserHandle = userHandle;
-        }
-
-        @Override
-        public boolean onPreferenceClick(Preference preference) {
-            // start new fragment to display extended information
-            final Bundle args = new Bundle();
-            args.putString(AppInfoDashboardFragment.ARG_PACKAGE_NAME, mPackage);
-
-            new SubSettingLauncher(mFragment.getContext())
-                    .setDestination(AppInfoDashboardFragment.class.getName())
-                    .setArguments(args)
-                    .setTitleRes(R.string.application_info_label)
-                    .setUserHandle(mUserHandle)
-                    .setSourceMetricsCategory(mFragment.getMetricsCategory())
-                    .launch();
-            return true;
-        }
-    }
-
-    public RecentLocationRequestPreferenceController(Context context, LocationSettings fragment,
-            Lifecycle lifecycle) {
-        this(context, fragment, lifecycle, new RecentLocationApps(context));
-    }
-
-    @VisibleForTesting
-    RecentLocationRequestPreferenceController(Context context, LocationSettings fragment,
-            Lifecycle lifecycle, RecentLocationApps recentApps) {
-        super(context, lifecycle);
-        mFragment = fragment;
-        mRecentLocationApps = recentApps;
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_RECENT_LOCATION_REQUESTS;
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mCategoryRecentLocationRequests =
-                (PreferenceCategory) screen.findPreference(KEY_RECENT_LOCATION_REQUESTS);
-        mSeeAllButton = screen.findPreference(KEY_SEE_ALL_BUTTON);
-
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        mCategoryRecentLocationRequests.removeAll();
-        mSeeAllButton.setVisible(false);
-
-        final Context prefContext = preference.getContext();
-        final List<RecentLocationApps.Request> recentLocationRequests =
-                mRecentLocationApps.getAppListSorted();
-
-        if (recentLocationRequests.size() > 3) {
-            // Display the top 3 preferences to container in original order.
-            for (int i = 0; i < 3; i++) {
-                mCategoryRecentLocationRequests.addPreference(
-                        createAppPreference(prefContext, recentLocationRequests.get(i)));
-            }
-            // Display a button to list all requests
-            mSeeAllButton.setVisible(true);
-        } else if (recentLocationRequests.size() > 0) {
-            // Add preferences to container in original order (already sorted by recency).
-            for (RecentLocationApps.Request request : recentLocationRequests) {
-                mCategoryRecentLocationRequests.addPreference(
-                        createAppPreference(prefContext, request));
-            }
-        } else {
-            // If there's no item to display, add a "No recent apps" item.
-            final Preference banner = createAppPreference(prefContext);
-            banner.setTitle(R.string.location_no_recent_apps);
-            banner.setSelectable(false);
-            mCategoryRecentLocationRequests.addPreference(banner);
-        }
-    }
-
-    @Override
-    public void onLocationModeChanged(int mode, boolean restricted) {
-        mCategoryRecentLocationRequests.setEnabled(mLocationEnabler.isEnabled(mode));
-    }
-
-    @VisibleForTesting
-    AppPreference createAppPreference(Context prefContext) {
-        return new AppPreference(prefContext);
-    }
-
-    @VisibleForTesting
-    AppPreference createAppPreference(Context prefContext, RecentLocationApps.Request request) {
-        final AppPreference pref = createAppPreference(prefContext);
-        pref.setSummary(request.contentDescription);
-        pref.setIcon(request.icon);
-        pref.setTitle(request.label);
-        pref.setOnPreferenceClickListener(new PackageEntryClickedListener(
-                mFragment, request.packageName, request.userHandle));
-        return pref;
-    }
-}
diff --git a/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java b/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java
deleted file mode 100644
index d256b9b..0000000
--- a/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 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.location;
-
-
-import android.content.Context;
-import android.provider.SearchIndexableResource;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.search.Indexable;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.search.SearchIndexable;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/** Dashboard Fragment to display all recent location requests, sorted by recency. */
-@SearchIndexable
-public class RecentLocationRequestSeeAllFragment extends DashboardFragment {
-
-    private static final String TAG = "RecentLocationReqAll";
-
-    public static final String PATH =
-            "com.android.settings.location.RecentLocationRequestSeeAllFragment";
-
-    @Override
-    public int getMetricsCategory() {
-      return MetricsEvent.RECENT_LOCATION_REQUESTS_ALL;
-    }
-
-    @Override
-    protected int getPreferenceScreenResId() {
-        return R.xml.location_recent_requests_see_all;
-    }
-
-    @Override
-    protected String getLogTag() {
-      return TAG;
-    }
-
-    @Override
-    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
-        return buildPreferenceControllers(context, getSettingsLifecycle(), this);
-    }
-
-    private static List<AbstractPreferenceController> buildPreferenceControllers(
-            Context context, Lifecycle lifecycle, RecentLocationRequestSeeAllFragment fragment) {
-        final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(
-                new RecentLocationRequestSeeAllPreferenceController(context, lifecycle, fragment));
-        return controllers;
-    }
-
-    /**
-     * For Search.
-     */
-    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-            new BaseSearchIndexProvider() {
-                @Override
-                public List<SearchIndexableResource> getXmlResourcesToIndex(
-                        Context context, boolean enabled) {
-                    final SearchIndexableResource sir = new SearchIndexableResource(context);
-                    sir.xmlResId = R.xml.location_recent_requests_see_all;
-                    return Arrays.asList(sir);
-                }
-
-                @Override
-                public List<AbstractPreferenceController> getPreferenceControllers(Context
-                        context) {
-                    return buildPreferenceControllers(
-                            context, /* lifecycle = */ null, /* fragment = */ null);
-                }
-            };
-}
diff --git a/src/com/android/settings/location/RecentLocationRequestSeeAllPreferenceController.java b/src/com/android/settings/location/RecentLocationRequestSeeAllPreferenceController.java
deleted file mode 100644
index 3fa0f00..0000000
--- a/src/com/android/settings/location/RecentLocationRequestSeeAllPreferenceController.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 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.location;
-
-import android.content.Context;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.location.RecentLocationApps;
-import com.android.settingslib.widget.apppreference.AppPreference;
-
-import java.util.List;
-
-/** Preference controller for preference category displaying all recent location requests. */
-public class RecentLocationRequestSeeAllPreferenceController
-        extends LocationBasePreferenceController {
-
-    /** Key for preference category "All recent location requests" */
-    private static final String KEY_ALL_RECENT_LOCATION_REQUESTS = "all_recent_location_requests";
-    private final RecentLocationRequestSeeAllFragment mFragment;
-    private PreferenceCategory mCategoryAllRecentLocationRequests;
-    private RecentLocationApps mRecentLocationApps;
-
-    public RecentLocationRequestSeeAllPreferenceController(
-            Context context, Lifecycle lifecycle, RecentLocationRequestSeeAllFragment fragment) {
-        this(context, lifecycle, fragment, new RecentLocationApps(context));
-    }
-
-    @VisibleForTesting
-    RecentLocationRequestSeeAllPreferenceController(
-            Context context,
-            Lifecycle lifecycle,
-            RecentLocationRequestSeeAllFragment fragment,
-            RecentLocationApps recentLocationApps) {
-        super(context, lifecycle);
-        mFragment = fragment;
-        mRecentLocationApps = recentLocationApps;
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_ALL_RECENT_LOCATION_REQUESTS;
-    }
-
-    @Override
-    public void onLocationModeChanged(int mode, boolean restricted) {
-        mCategoryAllRecentLocationRequests.setEnabled(mLocationEnabler.isEnabled(mode));
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mCategoryAllRecentLocationRequests =
-                (PreferenceCategory) screen.findPreference(KEY_ALL_RECENT_LOCATION_REQUESTS);
-
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        mCategoryAllRecentLocationRequests.removeAll();
-        List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppListSorted();
-        for (RecentLocationApps.Request request : requests) {
-            Preference appPreference = createAppPreference(preference.getContext(), request);
-            mCategoryAllRecentLocationRequests.addPreference(appPreference);
-        }
-    }
-
-    @VisibleForTesting
-    AppPreference createAppPreference(
-            Context prefContext, RecentLocationApps.Request request) {
-        final AppPreference pref = new AppPreference(prefContext);
-        pref.setSummary(request.contentDescription);
-        pref.setIcon(request.icon);
-        pref.setTitle(request.label);
-        pref.setOnPreferenceClickListener(
-                new RecentLocationRequestPreferenceController.PackageEntryClickedListener(
-                        mFragment, request.packageName, request.userHandle));
-        return pref;
-    }
-}
diff --git a/src/com/android/settings/location/ScanningSettings.java b/src/com/android/settings/location/ScanningSettings.java
index b2ce5fb..86402c0 100644
--- a/src/com/android/settings/location/ScanningSettings.java
+++ b/src/com/android/settings/location/ScanningSettings.java
@@ -34,7 +34,7 @@
 /**
  * A page that configures the background scanning settings for Wi-Fi and Bluetooth.
  */
-@SearchIndexable
+@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class ScanningSettings extends DashboardFragment {
     private static final String TAG = "ScanningSettings";
 
diff --git a/src/com/android/settings/location/TopLevelLocationPreferenceController.java b/src/com/android/settings/location/TopLevelLocationPreferenceController.java
new file mode 100644
index 0000000..d0bd9a9
--- /dev/null
+++ b/src/com/android/settings/location/TopLevelLocationPreferenceController.java
@@ -0,0 +1,99 @@
+package com.android.settings.location;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.LocationManager;
+import android.permission.RuntimePermissionPresenter;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+public class TopLevelLocationPreferenceController extends BasePreferenceController implements
+        LifecycleObserver, OnStart, OnStop {
+    private static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED =
+            new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
+    private final LocationManager mLocationManager;
+    /** Total number of apps that has location permission. */
+    private int mNumTotal = -1;
+    private BroadcastReceiver mReceiver;
+    private Preference mPreference;
+
+    public TopLevelLocationPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        if (mLocationManager.isLocationEnabled()) {
+            if (mNumTotal == -1) {
+                return mContext.getString(R.string.location_settings_loading_app_permission_stats);
+            }
+            return mContext.getResources().getQuantityString(
+                    R.plurals.location_settings_summary_location_on,
+                    mNumTotal, mNumTotal);
+        } else {
+            return mContext.getString(R.string.location_settings_summary_location_off);
+        }
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        mPreference = preference;
+        refreshSummary(preference);
+        // Bail out if location has been disabled.
+        if (!mLocationManager.isLocationEnabled()) {
+            return;
+        }
+        RuntimePermissionPresenter.getInstance(mContext).countPermissionApps(
+                Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), false, false,
+                (numApps) -> {
+                    mNumTotal = numApps;
+                    refreshSummary(preference);
+                }, null);
+    }
+
+    @Override
+    public void onStart() {
+        if (mReceiver == null) {
+            mReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    refreshLocationMode();
+                }
+            };
+        }
+        mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED);
+        refreshLocationMode();
+    }
+
+    @Override
+    public void onStop() {
+        mContext.unregisterReceiver(mReceiver);
+    }
+
+    private void refreshLocationMode() {
+        // 'null' is checked inside updateState(), so no need to check here.
+        updateState(mPreference);
+    }
+}
diff --git a/src/com/android/settings/network/MultiNetworkHeaderController.java b/src/com/android/settings/network/MultiNetworkHeaderController.java
index 1c0fc74..8860c47 100644
--- a/src/com/android/settings/network/MultiNetworkHeaderController.java
+++ b/src/com/android/settings/network/MultiNetworkHeaderController.java
@@ -18,19 +18,70 @@
 
 import android.content.Context;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.wifi.WifiConnectionPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
 
 // 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 class MultiNetworkHeaderController extends BasePreferenceController implements
+        WifiConnectionPreferenceController.UpdateListener,
+        SubscriptionsPreferenceController.UpdateListener {
+    public static final String TAG = "MultiNetworkHdrCtrl";
+
+    private WifiConnectionPreferenceController mWifiController;
+    private SubscriptionsPreferenceController mSubscriptionsController;
+    private PreferenceCategory mPreferenceCategory;
 
     public MultiNetworkHeaderController(Context context, String key) {
-      super(context, key);
+        super(context, key);
+    }
+
+    public void init(Lifecycle lifecycle) {
+        mWifiController = createWifiController(lifecycle);
+        mSubscriptionsController = createSubscriptionsController(lifecycle);
+    }
+
+    @VisibleForTesting
+    WifiConnectionPreferenceController createWifiController(Lifecycle lifecycle) {
+        final int prefOrder = 0;
+        return new WifiConnectionPreferenceController(mContext, lifecycle, this, mPreferenceKey,
+                prefOrder, MetricsProto.MetricsEvent.SETTINGS_NETWORK_CATEGORY);
+    }
+
+    @VisibleForTesting
+    SubscriptionsPreferenceController createSubscriptionsController(Lifecycle lifecycle) {
+        final int prefStartOrder = 10;
+        return new SubscriptionsPreferenceController(mContext, lifecycle, this, mPreferenceKey,
+                prefStartOrder);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreferenceCategory = (PreferenceCategory) screen.findPreference(mPreferenceKey);
+        mPreferenceCategory.setVisible(isAvailable());
+        mWifiController.displayPreference(screen);
+        mSubscriptionsController.displayPreference(screen);
     }
 
     @Override
     public int getAvailabilityStatus() {
-        return UNSUPPORTED_ON_DEVICE;
+        if (mSubscriptionsController == null || !mSubscriptionsController.isAvailable()) {
+            return CONDITIONALLY_UNAVAILABLE;
+        } else {
+            return AVAILABLE;
+        }
+    }
+
+    @Override
+    public void onChildrenUpdated() {
+        mPreferenceCategory.setVisible(isAvailable());
     }
 }
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index 70481f1..7d94bba 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -72,6 +72,9 @@
     public void onAttach(Context context) {
         super.onAttach(context);
 
+        if (FeatureFlagUtils.isEnabled(context, FeatureFlags.NETWORK_INTERNET_V2)) {
+            use(MultiNetworkHeaderController.class).init(getSettingsLifecycle());
+        }
         use(AirplaneModePreferenceController.class).setFragment(this);
     }
 
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index cfe27db..6b14759 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -24,8 +24,20 @@
 import java.util.Iterator;
 import java.util.List;
 
+import androidx.annotation.VisibleForTesting;
+
 public class SubscriptionUtil {
+    private static List<SubscriptionInfo> sResultsForTesting;
+
+    @VisibleForTesting
+    static void setAvailableSubscriptionsForTesting(List<SubscriptionInfo> results) {
+        sResultsForTesting = results;
+    }
+
     public static List<SubscriptionInfo> getAvailableSubscriptions(SubscriptionManager manager) {
+        if (sResultsForTesting != null) {
+            return sResultsForTesting;
+        }
         List<SubscriptionInfo> subscriptions = manager.getAvailableSubscriptionInfoList();
         if (subscriptions == null) {
             subscriptions = new ArrayList<>();
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
new file mode 100644
index 0000000..9e55341
--- /dev/null
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -0,0 +1,183 @@
+/*
+ * 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 androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
+import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
+
+import android.content.Context;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.Map;
+
+import androidx.collection.ArrayMap;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+
+/**
+ * This manages a set of Preferences it places into a PreferenceGroup owned by some parent
+ * controller class - one for each available subscription. This controller is only considered
+ * available if there are 2 or more subscriptions.
+ */
+public class SubscriptionsPreferenceController extends AbstractPreferenceController implements
+        LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
+    private static final String TAG = "SubscriptionsPrefCntrlr";
+
+    private UpdateListener mUpdateListener;
+    private String mPreferenceGroupKey;
+    private PreferenceGroup mPreferenceGroup;
+    private SubscriptionManager mManager;
+    private SubscriptionsChangeListener mSubscriptionsListener;
+
+    // Map of subscription id to Preference
+    private Map<Integer, Preference> mSubscriptionPreferences;
+    private int mStartOrder;
+
+    /**
+     * This interface lets a parent of this class know that some change happened - this could
+     * either be because overall availability changed, or because we've added/removed/updated some
+     * preferences.
+     */
+    public interface UpdateListener {
+        void onChildrenUpdated();
+    }
+
+    /**
+     * @param context            the context for the UI where we're placing these preferences
+     * @param lifecycle          for listening to lifecycle events for the UI
+     * @param updateListener     called to let our parent controller know that our availability has
+     *                           changed, or that one or more of the preferences we've placed in the
+     *                           PreferenceGroup has changed
+     * @param preferenceGroupKey the key used to lookup the PreferenceGroup where Preferences will
+     *                           be placed
+     * @param startOrder         the order that should be given to the first Preference placed into
+     *                           the PreferenceGroup; the second will use startOrder+1, third will
+     *                           use startOrder+2, etc. - this is useful for when the parent wants
+     *                           to have other preferences in the same PreferenceGroup and wants
+     *                           a specific ordering relative to this controller's prefs.
+     */
+    public SubscriptionsPreferenceController(Context context, Lifecycle lifecycle,
+            UpdateListener updateListener, String preferenceGroupKey, int startOrder) {
+        super(context);
+        mUpdateListener = updateListener;
+        mPreferenceGroupKey = preferenceGroupKey;
+        mStartOrder = startOrder;
+        mManager = context.getSystemService(SubscriptionManager.class);
+        mSubscriptionPreferences = new ArrayMap<>();
+        mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
+        lifecycle.addObserver(this);
+    }
+
+    @OnLifecycleEvent(ON_RESUME)
+    public void onResume() {
+        mSubscriptionsListener.start();
+        update();
+    }
+
+    @OnLifecycleEvent(ON_PAUSE)
+    public void onPause() {
+        mSubscriptionsListener.stop();
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        mPreferenceGroup = (PreferenceGroup) screen.findPreference(mPreferenceGroupKey);
+        update();
+    }
+
+    private void update() {
+        if (mPreferenceGroup == null) {
+            return;
+        }
+
+        if (mSubscriptionsListener.isAirplaneModeOn()) {
+            for (Preference pref : mSubscriptionPreferences.values()) {
+                mPreferenceGroup.removePreference(pref);
+            }
+            mSubscriptionPreferences.clear();
+            mUpdateListener.onChildrenUpdated();
+            return;
+        }
+
+        final Map<Integer, Preference> existingPrefs = mSubscriptionPreferences;
+        mSubscriptionPreferences = new ArrayMap<>();
+
+        int order = mStartOrder;
+        for (SubscriptionInfo info :  SubscriptionUtil.getAvailableSubscriptions(mManager) ) {
+            final int subId = info.getSubscriptionId();
+            Preference pref = existingPrefs.remove(subId);
+            if (pref == null) {
+                pref = new Preference(mPreferenceGroup.getContext());
+                mPreferenceGroup.addPreference(pref);
+            }
+            pref.setTitle(info.getDisplayName());
+            pref.setIcon(R.drawable.ic_network_cell);
+            pref.setOrder(order++);
+
+            // TODO(asargent) - set summary here to indicate default for calls/sms and data
+
+            pref.setOnPreferenceClickListener(clickedPref -> {
+                // TODO(asargent) - make this start MobileNetworkActivity once we've
+                // added support for it to take a subscription id
+                return true;
+            });
+
+            mSubscriptionPreferences.put(subId, pref);
+        }
+
+        // Remove any old preferences that no longer map to a subscription.
+        for (Preference pref : existingPrefs.values()) {
+            mPreferenceGroup.removePreference(pref);
+        }
+        mUpdateListener.onChildrenUpdated();
+    }
+
+    /**
+     *
+     * @return true if there are at least 2 available subscriptions.
+     */
+    @Override
+    public boolean isAvailable() {
+        if (mSubscriptionsListener.isAirplaneModeOn()) {
+            return false;
+        }
+        return SubscriptionUtil.getAvailableSubscriptions(mManager).size() >= 2;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return null;
+    }
+
+    @Override
+    public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
+        update();
+    }
+
+    @Override
+    public void onSubscriptionsChanged() {
+        update();
+    }
+}
diff --git a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
index d0f1ee6..1499656 100644
--- a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
+++ b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
@@ -21,6 +21,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.provider.Settings;
@@ -82,33 +84,47 @@
         return intent;
     }
 
-    public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
-        if (si == null || si.metaData == null) {
+    public static ZenRuleInfo getRuleInfo(PackageManager pm, ComponentInfo ci) {
+        if (ci == null || ci.metaData == null) {
             return null;
         }
-        final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
-        final ComponentName configurationActivity = getSettingsActivity(si);
+        final String ruleType = (ci instanceof ServiceInfo)
+                ? ci.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE)
+                : ci.metaData.getString(NotificationManager.META_DATA_AUTOMATIC_RULE_TYPE);
+
+        final ComponentName configurationActivity = getSettingsActivity(null, ci);
         if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
             final ZenRuleInfo ri = new ZenRuleInfo();
-            ri.serviceComponent = new ComponentName(si.packageName, si.name);
+            ri.serviceComponent =
+                    (ci instanceof ServiceInfo) ? new ComponentName(ci.packageName, ci.name) : null;
             ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
             ri.title = ruleType;
-            ri.packageName = si.packageName;
-            ri.configurationActivity = getSettingsActivity(si);
-            ri.packageLabel = si.applicationInfo.loadLabel(pm);
-            ri.ruleInstanceLimit =
-                    si.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
+            ri.packageName = ci.packageName;
+            ri.configurationActivity = configurationActivity;
+            ri.packageLabel = ci.applicationInfo.loadLabel(pm);
+            ri.ruleInstanceLimit = (ci instanceof ServiceInfo)
+                    ? ci.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1)
+                    : ci.metaData.getInt(NotificationManager.META_DATA_RULE_INSTANCE_LIMIT, -1);
             return ri;
         }
         return null;
     }
 
-    protected static ComponentName getSettingsActivity(ServiceInfo si) {
-        if (si == null || si.metaData == null) {
+    protected static ComponentName getSettingsActivity(AutomaticZenRule rule, ComponentInfo ci) {
+        // prefer config activity on the rule itself; fallback to manifest definition
+        if (rule != null && rule.getConfigurationActivity() != null) {
+            return rule.getConfigurationActivity();
+        }
+        if (ci == null) {
             return null;
         }
+        // new activity backed rule
+        if (ci instanceof ActivityInfo) {
+            return new ComponentName(ci.packageName, ci.name);
+        }
+        // old service backed rule
         final String configurationActivity =
-                si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
+                ci.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
         if (configurationActivity != null) {
             return ComponentName.unflattenFromString(configurationActivity);
         }
@@ -127,7 +143,7 @@
             mMetricsFeatureProvider.action(mContext,
                     MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
             AutomaticZenRule rule = new AutomaticZenRule(ruleName, mRuleInfo.serviceComponent,
-                    mRuleInfo.defaultConditionId,
+                    mRuleInfo.configurationActivity, mRuleInfo.defaultConditionId, null,
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
             String savedRuleId = mBackend.addZenRule(rule);
             if (savedRuleId != null) {
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index d6a7d72..57ee545 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -18,6 +18,7 @@
 
 import android.app.AlertDialog;
 import android.app.AutomaticZenRule;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
@@ -92,6 +93,7 @@
         return new ManagedServiceSettings.Config.Builder()
                 .setTag(TAG)
                 .setIntentAction(ConditionProviderService.SERVICE_INTERFACE)
+                .setConfigurationIntentAction(NotificationManager.ACTION_AUTOMATIC_ZEN_RULE)
                 .setPermission(android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE)
                 .setNoun("condition provider")
                 .build();
diff --git a/src/com/android/settings/notification/ZenRuleInfo.java b/src/com/android/settings/notification/ZenRuleInfo.java
index 2d7abf8..1a1539b 100644
--- a/src/com/android/settings/notification/ZenRuleInfo.java
+++ b/src/com/android/settings/notification/ZenRuleInfo.java
@@ -24,6 +24,8 @@
                 that.defaultConditionId) : that.defaultConditionId != null) return false;
         if (serviceComponent != null ? !serviceComponent.equals(
                 that.serviceComponent) : that.serviceComponent != null) return false;
+        if (id != null ? !id.equals(that.id) : that.id != null)
+            return false;
         return packageLabel != null ? packageLabel.equals(
                 that.packageLabel) : that.packageLabel == null;
 
@@ -38,4 +40,5 @@
     public boolean isSystem;
     public CharSequence packageLabel;
     public int ruleInstanceLimit = -1;
+    public String id;
 }
diff --git a/src/com/android/settings/notification/ZenRulePreference.java b/src/com/android/settings/notification/ZenRulePreference.java
index 10b49eb..91f68e8 100644
--- a/src/com/android/settings/notification/ZenRulePreference.java
+++ b/src/com/android/settings/notification/ZenRulePreference.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.service.notification.ZenModeConfig;
@@ -45,7 +46,6 @@
     private static final ManagedServiceSettings.Config CONFIG =
             ZenModeAutomationSettings.getConditionProviderConfig();
     final String mId;
-    boolean appExists;
     final Fragment mParent;
     final Preference mPref;
     final Context mContext;
@@ -56,7 +56,6 @@
     final AutomaticZenRule mRule;
     CharSequence mName;
 
-    private boolean mIsSystemRule;
     private Intent mIntent;
     private boolean mChecked;
     private CheckBox mCheckBox;
@@ -163,25 +162,17 @@
         final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
                 rule.getConditionId(), true);
         final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
-        mIsSystemRule = isSchedule || isEvent;
 
-        try {
-            ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
-            setSummary(computeRuleSummary(rule));
-        } catch (PackageManager.NameNotFoundException e) {
-            appExists = false;
-            return;
-        }
+        setSummary(computeRuleSummary(rule));
 
-        appExists = true;
         setTitle(mName);
         setPersistent(false);
 
         final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
                 : isEvent ? ZenModeEventRuleSettings.ACTION : "";
-        ServiceInfo si = mServiceListing.findService(rule.getOwner());
+        ComponentInfo si = mServiceListing.findService(rule.getOwner());
         ComponentName settingsActivity = AbstractZenModeAutomaticRulePreferenceController.
-                getSettingsActivity(si);
+                getSettingsActivity(rule, si);
         mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
                 settingsActivity, mId);
         setKey(mId);
diff --git a/src/com/android/settings/notification/ZenRuleSelectionDialog.java b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
index abda376..7f0b4c2 100644
--- a/src/com/android/settings/notification/ZenRuleSelectionDialog.java
+++ b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.graphics.drawable.Drawable;
@@ -192,16 +193,17 @@
     private final ZenServiceListing.Callback mServiceListingCallback = new
             ZenServiceListing.Callback() {
         @Override
-        public void onServicesReloaded(Set<ServiceInfo> services) {
-            if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size());
+        public void onComponentsReloaded(Set<ComponentInfo> componentInfos) {
+            if (DEBUG) Log.d(TAG, "Reloaded: count=" + componentInfos.size());
+
             Set<ZenRuleInfo> externalRuleTypes = new TreeSet<>(RULE_TYPE_COMPARATOR);
-            for (ServiceInfo serviceInfo : services) {
+            for (ComponentInfo ci : componentInfos) {
                 final ZenRuleInfo ri = AbstractZenModeAutomaticRulePreferenceController.
-                        getRuleInfo(mPm, serviceInfo);
+                        getRuleInfo(mPm, ci);
                 if (ri != null && ri.configurationActivity != null
                         && mNm.isNotificationPolicyAccessGrantedForPackage(ri.packageName)
                         && (ri.ruleInstanceLimit <= 0 || ri.ruleInstanceLimit
-                        >= (mNm.getRuleInstanceCount(serviceInfo.getComponentName()) + 1))) {
+                        >= (mNm.getRuleInstanceCount(ci.getComponentName()) + 1))) {
                     externalRuleTypes.add(ri);
                 }
             }
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index a52619b..cf7df8d 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -23,6 +23,8 @@
 import com.android.settings.R;
 import com.android.settings.accounts.AccountFeatureProvider;
 import com.android.settings.applications.ApplicationFeatureProvider;
+import com.android.settings.biometrics.face.FaceFeatureProvider;
+import com.android.settings.bluetooth.BluetoothFeatureProvider;
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
@@ -109,7 +111,11 @@
 
     public abstract PanelFeatureProvider getPanelFeatureProvider();
 
-    public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider();
+    public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider(Context context);
+
+    public abstract FaceFeatureProvider getFaceFeatureProvider();
+
+    public abstract BluetoothFeatureProvider getBluetoothFeatureProvider(Context context);
 
     public static final class FactoryNotFoundException extends RuntimeException {
         public FactoryNotFoundException(Throwable throwable) {
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 3515ac0..e10aa41 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -28,6 +28,10 @@
 import com.android.settings.accounts.AccountFeatureProviderImpl;
 import com.android.settings.applications.ApplicationFeatureProvider;
 import com.android.settings.applications.ApplicationFeatureProviderImpl;
+import com.android.settings.biometrics.face.FaceFeatureProvider;
+import com.android.settings.biometrics.face.FaceFeatureProviderImpl;
+import com.android.settings.bluetooth.BluetoothFeatureProvider;
+import com.android.settings.bluetooth.BluetoothFeatureProviderImpl;
 import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl;
 import com.android.settings.core.instrumentation.SettingsMetricsFeatureProvider;
 import com.android.settings.dashboard.DashboardFeatureProvider;
@@ -78,6 +82,8 @@
     private AccountFeatureProvider mAccountFeatureProvider;
     private PanelFeatureProvider mPanelFeatureProvider;
     private ContextualCardFeatureProvider mContextualCardFeatureProvider;
+    private FaceFeatureProvider mFaceFeatureProvider;
+    private BluetoothFeatureProvider mBluetoothFeatureProvider;
 
     @Override
     public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -224,10 +230,29 @@
         return mPanelFeatureProvider;
     }
 
-    public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
+    @Override
+    public ContextualCardFeatureProvider getContextualCardFeatureProvider(Context context) {
         if (mContextualCardFeatureProvider == null) {
-            mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl();
+            mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl(
+                    context.getApplicationContext());
         }
         return mContextualCardFeatureProvider;
     }
+
+    @Override
+    public FaceFeatureProvider getFaceFeatureProvider() {
+        if (mFaceFeatureProvider == null) {
+            mFaceFeatureProvider = new FaceFeatureProviderImpl();
+        }
+        return mFaceFeatureProvider;
+    }
+
+    @Override
+    public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
+        if (mBluetoothFeatureProvider == null) {
+            mBluetoothFeatureProvider = new BluetoothFeatureProviderImpl(
+                    context.getApplicationContext());
+        }
+        return mBluetoothFeatureProvider;
+    }
 }
diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java
index b96c57df..8454cc5 100644
--- a/src/com/android/settings/password/SetupChooseLockPassword.java
+++ b/src/com/android/settings/password/SetupChooseLockPassword.java
@@ -135,8 +135,9 @@
         @Override
         protected void updateUi() {
             super.updateUi();
-            mSkipButton.setVisibility(mForFingerprint ? View.GONE : View.VISIBLE);
 
+            // Show the skip button during SUW but not during Settings > Biometric Enrollment
+            mSkipButton.setVisibility(View.VISIBLE);
             if (mOptionsButton != null) {
                 mOptionsButton.setVisibility(
                         mUiStage == Stage.Introduction ? View.VISIBLE : View.GONE);
diff --git a/src/com/android/settings/password/SetupChooseLockPattern.java b/src/com/android/settings/password/SetupChooseLockPattern.java
index 696380c..b24936b 100644
--- a/src/com/android/settings/password/SetupChooseLockPattern.java
+++ b/src/com/android/settings/password/SetupChooseLockPattern.java
@@ -70,17 +70,15 @@
                         ChooseLockTypeDialogFragment.newInstance(mUserId)
                                 .show(getChildFragmentManager(), null));
             }
-            // enable skip button only during setup wizard and not with fingerprint flow.
-            if (!mForFingerprint) {
-                Button skipButton = view.findViewById(R.id.skip_button);
-                skipButton.setVisibility(View.VISIBLE);
-                skipButton.setOnClickListener(v -> {
-                    SetupSkipDialog dialog = SetupSkipDialog.newInstance(
-                            getActivity().getIntent()
-                                    .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false));
-                    dialog.show(getFragmentManager());
+            // Show the skip button during SUW but not during Settings > Biometric Enrollment
+            Button skipButton = view.findViewById(R.id.skip_button);
+            skipButton.setVisibility(View.VISIBLE);
+            skipButton.setOnClickListener(v -> {
+                SetupSkipDialog dialog = SetupSkipDialog.newInstance(
+                        getActivity().getIntent()
+                                .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false));
+                dialog.show(getFragmentManager());
                 });
-            }
             return view;
         }
 
diff --git a/src/com/android/settings/security/trustagent/TrustAgentsExtendUnlockPreferenceController.java b/src/com/android/settings/security/trustagent/TrustAgentsExtendUnlockPreferenceController.java
new file mode 100644
index 0000000..bfbebaf
--- /dev/null
+++ b/src/com/android/settings/security/trustagent/TrustAgentsExtendUnlockPreferenceController.java
@@ -0,0 +1,48 @@
+/*
+ * 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.security.trustagent;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+
+public class TrustAgentsExtendUnlockPreferenceController extends TogglePreferenceController {
+
+    public TrustAgentsExtendUnlockPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK, 1) == 1;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK, isChecked ? 1 : 0);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/security/trustagent/TrustLostLocksScreenPreferenceController.java b/src/com/android/settings/security/trustagent/TrustLostLocksScreenPreferenceController.java
new file mode 100644
index 0000000..b5e0dd7
--- /dev/null
+++ b/src/com/android/settings/security/trustagent/TrustLostLocksScreenPreferenceController.java
@@ -0,0 +1,48 @@
+/*
+ * 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.security.trustagent;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+
+public class TrustLostLocksScreenPreferenceController extends TogglePreferenceController {
+
+    public TrustLostLocksScreenPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST, 1) == 1;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST, isChecked ? 1 : 0);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/slices/CopyableSlice.java b/src/com/android/settings/slices/Copyable.java
similarity index 96%
rename from src/com/android/settings/slices/CopyableSlice.java
rename to src/com/android/settings/slices/Copyable.java
index 31fc151..12159d1 100644
--- a/src/com/android/settings/slices/CopyableSlice.java
+++ b/src/com/android/settings/slices/Copyable.java
@@ -19,7 +19,7 @@
 /**
  * Provide the copy ability for preference controller to copy the data to the clipboard.
  */
-public interface CopyableSlice {
+public interface Copyable {
     /**
      * Copy the key slice information to the clipboard.
      * It is highly recommended to show the toast to notify users when implemented this function.
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
index 4a9de15..bb47df2 100644
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ b/src/com/android/settings/slices/CustomSliceManager.java
@@ -32,7 +32,8 @@
 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 com.android.settings.wifi.slice.ContextualWifiSlice;
+import com.android.settings.wifi.slice.WifiSlice;
 
 import java.util.Map;
 import java.util.WeakHashMap;
@@ -107,6 +108,7 @@
         mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
         mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class);
         mUriMap.put(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
+        mUriMap.put(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.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);
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index 1b8cffe..bdf8b35 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -80,6 +80,17 @@
             .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
             .appendPath("bluetooth_devices")
             .build();
+
+    /**
+     * Backing Uri for the Wifi Slice.
+     */
+    public static final Uri CONTEXTUAL_WIFI_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSlicesContract.AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("contextual_wifi")
+            .build();
+
     /**
      * Backing Uri for the Data usage Slice.
      */
@@ -216,6 +227,7 @@
             .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
             .appendPath(KEY_WIFI)
             .build();
+
     /**
      * Backing Uri for the Zen Mode Slice.
      */
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 823c729..28b2f81 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -185,7 +185,7 @@
 
         final BasePreferenceController controller = getPreferenceController(context, key);
 
-        if (!(controller instanceof CopyableSlice)) {
+        if (!(controller instanceof Copyable)) {
             throw new IllegalArgumentException(
                     "Copyable action passed for a non-copyable key:" + key);
         }
@@ -198,7 +198,7 @@
             return;
         }
 
-        ((CopyableSlice) controller).copy();
+        ((Copyable) controller).copy();
     }
 
     /**
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index d75eaa2..b2b8310 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -94,7 +94,7 @@
             return buildUnavailableSlice(context, sliceData);
         }
 
-        if (controller instanceof CopyableSlice) {
+        if (controller instanceof Copyable) {
             return buildCopyableSlice(context, sliceData, controller);
         }
 
diff --git a/src/com/android/settings/slices/SlicePreference.java b/src/com/android/settings/slices/SlicePreference.java
new file mode 100644
index 0000000..98719f7
--- /dev/null
+++ b/src/com/android/settings/slices/SlicePreference.java
@@ -0,0 +1,48 @@
+/*
+ * 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.slices;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceView;
+
+import com.android.settings.R;
+import com.android.settingslib.widget.LayoutPreference;
+
+/**
+ * Preference for {@link SliceView}
+ */
+public class SlicePreference extends LayoutPreference {
+    private SliceView mSliceView;
+
+    public SlicePreference(Context context, AttributeSet attrs) {
+        super(context, attrs, R.attr.slicePreferenceStyle);
+        mSliceView = findViewById(R.id.slice_view);
+    }
+
+    public SlicePreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, R.attr.slicePreferenceStyle);
+        mSliceView = findViewById(R.id.slice_view);
+    }
+
+    public void onSliceUpdated(Slice slice) {
+        mSliceView.onChanged(slice);
+        notifyChanged();
+    }
+}
diff --git a/src/com/android/settings/slices/SlicePreferenceController.java b/src/com/android/settings/slices/SlicePreferenceController.java
new file mode 100644
index 0000000..8c751c8
--- /dev/null
+++ b/src/com/android/settings/slices/SlicePreferenceController.java
@@ -0,0 +1,89 @@
+/*
+ * 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.slices;
+
+import android.content.Context;
+import android.net.Uri;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.Observer;
+import androidx.preference.PreferenceScreen;
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceLiveData;
+import androidx.slice.widget.SliceView;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+/**
+ * Default {@link BasePreferenceController} for {@link SliceView}. It will take {@link Uri} for
+ * Slice and display what's inside this {@link Uri}
+ */
+public class SlicePreferenceController extends BasePreferenceController implements
+        LifecycleObserver, OnStart, OnStop, Observer<Slice> {
+    @VisibleForTesting
+    LiveData<Slice> mLiveData;
+    private SlicePreference mSlicePreference;
+    private Uri mUri;
+
+    public SlicePreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+
+        mSlicePreference = (SlicePreference) screen.findPreference(
+                getPreferenceKey());
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mUri != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    public void setSliceUri(Uri uri) {
+        mUri = uri;
+        mLiveData = SliceLiveData.fromUri(mContext, mUri);
+
+        //TODO(b/120803703): figure out why we need to remove observer first
+        mLiveData.removeObserver(this);
+    }
+
+    @Override
+    public void onStart() {
+        if (mLiveData != null) {
+            mLiveData.observeForever(this);
+        }
+    }
+
+    @Override
+    public void onStop() {
+        if (mLiveData != null) {
+            mLiveData.removeObserver(this);
+        }
+    }
+
+    @Override
+    public void onChanged(Slice slice) {
+        mSlicePreference.onSliceUpdated(slice);
+    }
+}
diff --git a/src/com/android/settings/utils/ManagedServiceSettings.java b/src/com/android/settings/utils/ManagedServiceSettings.java
index e5dfb06..16f79c2 100644
--- a/src/com/android/settings/utils/ManagedServiceSettings.java
+++ b/src/com/android/settings/utils/ManagedServiceSettings.java
@@ -240,9 +240,11 @@
         public final int warningDialogTitle;
         public final int warningDialogSummary;
         public final int emptyText;
+        public final String configIntentAction;
 
-        private Config(String tag, String setting, String intentAction, String permission,
-                String noun, int warningDialogTitle, int warningDialogSummary, int emptyText) {
+        private Config(String tag, String setting, String intentAction, String configIntentAction,
+                String permission, String noun, int warningDialogTitle, int warningDialogSummary,
+                int emptyText) {
             this.tag = tag;
             this.setting = setting;
             this.intentAction = intentAction;
@@ -251,6 +253,7 @@
             this.warningDialogTitle = warningDialogTitle;
             this.warningDialogSummary = warningDialogSummary;
             this.emptyText = emptyText;
+            this.configIntentAction = configIntentAction;
         }
 
         public static class Builder{
@@ -262,6 +265,7 @@
             private int mWarningDialogTitle;
             private int mWarningDialogSummary;
             private int mEmptyText;
+            private String mConfigIntentAction;
 
             public Builder setTag(String tag) {
                 mTag = tag;
@@ -278,6 +282,11 @@
                 return this;
             }
 
+            public Builder setConfigurationIntentAction(String action) {
+                mConfigIntentAction = action;
+                return this;
+            }
+
             public Builder setPermission(String permission) {
                 mPermission = permission;
                 return this;
@@ -304,8 +313,8 @@
             }
 
             public Config build() {
-                return new Config(mTag, mSetting, mIntentAction, mPermission, mNoun,
-                        mWarningDialogTitle, mWarningDialogSummary, mEmptyText);
+                return new Config(mTag, mSetting, mIntentAction, mConfigIntentAction, mPermission,
+                        mNoun, mWarningDialogTitle, mWarningDialogSummary, mEmptyText);
             }
         }
     }
diff --git a/src/com/android/settings/utils/ZenServiceListing.java b/src/com/android/settings/utils/ZenServiceListing.java
index e87cc51..99f56f6 100644
--- a/src/com/android/settings/utils/ZenServiceListing.java
+++ b/src/com/android/settings/utils/ZenServiceListing.java
@@ -20,6 +20,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
@@ -34,7 +36,7 @@
 
     private final Context mContext;
     private final ManagedServiceSettings.Config mConfig;
-    private final Set<ServiceInfo> mApprovedServices = new ArraySet<ServiceInfo>();
+    private final Set<ComponentInfo> mApprovedComponents = new ArraySet<>();
     private final List<Callback> mZenCallbacks = new ArrayList<>();
     private final NotificationManager mNm;
 
@@ -44,11 +46,14 @@
         mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
     }
 
-    public ServiceInfo findService(final ComponentName cn) {
-        for (ServiceInfo service : mApprovedServices) {
-            final ComponentName serviceCN = new ComponentName(service.packageName, service.name);
-            if (serviceCN.equals(cn)) {
-                return service;
+    public ComponentInfo findService(final ComponentName cn) {
+        if (cn == null) {
+            return null;
+        }
+        for (ComponentInfo component : mApprovedComponents) {
+            final ComponentName ci = new ComponentName(component.packageName, component.name);
+            if (ci.equals(cn)) {
+                return component;
             }
         }
         return null;
@@ -63,32 +68,29 @@
     }
 
     public void reloadApprovedServices() {
-        mApprovedServices.clear();
+        mApprovedComponents.clear();
 
         List<String> enabledNotificationListenerPkgs = mNm.getEnabledNotificationListenerPackages();
-        List<ServiceInfo> services = new ArrayList<>();
-        getServices(mConfig, services, mContext.getPackageManager());
-        for (ServiceInfo service : services) {
-            final String servicePackage = service.getComponentName().getPackageName();
-            if (mNm.isNotificationPolicyAccessGrantedForPackage(servicePackage)
-                || enabledNotificationListenerPkgs.contains(servicePackage)) {
-                mApprovedServices.add(service);
+        List<ComponentInfo> components = new ArrayList<>();
+        getServices(mConfig, components, mContext.getPackageManager());
+        getActivities(mConfig, components, mContext.getPackageManager());
+        for (ComponentInfo componentInfo : components) {
+            final String pkg = componentInfo.getComponentName().getPackageName();
+            if (mNm.isNotificationPolicyAccessGrantedForPackage(pkg)
+                || enabledNotificationListenerPkgs.contains(pkg)) {
+                mApprovedComponents.add(componentInfo);
             }
         }
 
-        if (!mApprovedServices.isEmpty()) {
+        if (!mApprovedComponents.isEmpty()) {
             for (Callback callback : mZenCallbacks) {
-                callback.onServicesReloaded(mApprovedServices);
+                callback.onComponentsReloaded(mApprovedComponents);
             }
         }
     }
 
-    private static int getServices(ManagedServiceSettings.Config c, List<ServiceInfo> list,
+    private static void getServices(ManagedServiceSettings.Config c, List<ComponentInfo> list,
             PackageManager pm) {
-        int services = 0;
-        if (list != null) {
-            list.clear();
-        }
         final int user = ActivityManager.getCurrentUser();
 
         List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
@@ -110,12 +112,28 @@
             if (list != null) {
                 list.add(info);
             }
-            services++;
         }
-        return services;
+    }
+
+    private static void getActivities(ManagedServiceSettings.Config c, List<ComponentInfo> list,
+            PackageManager pm) {
+        final int user = ActivityManager.getCurrentUser();
+
+        List<ResolveInfo> resolveInfos = pm.queryIntentActivitiesAsUser(
+                new Intent(c.configIntentAction),
+                PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA,
+                user);
+
+        for (int i = 0, count = resolveInfos.size(); i < count; i++) {
+            ResolveInfo resolveInfo = resolveInfos.get(i);
+            ActivityInfo info = resolveInfo.activityInfo;
+            if (list != null) {
+                list.add(info);
+            }
+        }
     }
 
     public interface Callback {
-        void onServicesReloaded(Set<ServiceInfo> services);
+        void onComponentsReloaded(Set<ComponentInfo> components);
     }
 }
diff --git a/src/com/android/settings/wifi/AddNetworkFragment.java b/src/com/android/settings/wifi/AddNetworkFragment.java
index 72d878b..cd8f76e 100644
--- a/src/com/android/settings/wifi/AddNetworkFragment.java
+++ b/src/com/android/settings/wifi/AddNetworkFragment.java
@@ -73,7 +73,7 @@
                 scannerButton.setOnClickListener((View v) -> {
                     // Launch QR code scanner to join a network.
                     getContext().startActivity(
-                            WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
+                            WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
                 });
             }
         }
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index efb3f8c..30c2cd9 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -30,6 +30,7 @@
 import android.widget.BaseAdapter;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
 import androidx.preference.internal.PreferenceImageView;
 
@@ -46,7 +47,10 @@
 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.core.lifecycle.Lifecycle;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -62,10 +66,14 @@
     /** Message sent to us to stop scanning wifi and pop up timeout dialog. */
     private static final int MESSAGE_STOP_SCAN_WIFI_LIST = 0;
 
+    /** Spec defines there should be 5 wifi ap on the list at most. */
+    private static final int MAX_NUMBER_LIST_ITEM = 5;
+
     /** Delayed time to stop scanning wifi. */
     private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000;
 
     private List<AccessPoint> mAccessPointList;
+    private FilterWifiTracker mFilterWifiTracker;
     private AccessPointAdapter mDialogAdapter;
     private NetworkRequestUserSelectionCallback mUserSelectionCallback;
 
@@ -129,8 +137,16 @@
         }
 
         if (which < accessPointList.size()) {
-            WifiConfiguration wifiConfig = accessPointList.get(which).getConfig();
-            mUserSelectionCallback.select(wifiConfig);
+            final AccessPoint selectedAccessPoint = accessPointList.get(which);
+            WifiConfiguration wifiConfig = selectedAccessPoint.getConfig();
+            if (wifiConfig == null) {
+                wifiConfig = WifiUtils.getWifiConfig(selectedAccessPoint, /* scanResult */
+                        null, /* password */ null);
+            }
+
+            if (wifiConfig != null) {
+                mUserSelectionCallback.select(wifiConfig);
+            }
         }
     }
 
@@ -151,6 +167,19 @@
         if (wifiManager != null) {
             wifiManager.unregisterNetworkRequestMatchCallback(this);
         }
+
+        if (mFilterWifiTracker != null) {
+            mFilterWifiTracker.onPause();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (mFilterWifiTracker != null) {
+            mFilterWifiTracker.onDestroy();
+            mFilterWifiTracker = null;
+        }
     }
 
     @Override
@@ -164,6 +193,11 @@
         }
         // Sets time-out to stop scanning.
         mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
+
+        if (mFilterWifiTracker == null) {
+            mFilterWifiTracker = new FilterWifiTracker(getActivity(), getSettingsLifecycle());
+        }
+        mFilterWifiTracker.onResume();
     }
 
     private final Handler mHandler = new Handler() {
@@ -260,17 +294,33 @@
 
     @Override
     public void onMatch(List<ScanResult> scanResults) {
-        // TODO(b/119846365): Checks if we could escalate the converting effort.
-        // Converts ScanResult to WifiConfiguration.
-        List<WifiConfiguration> wifiConfigurations = null;
-        final WifiManager wifiManager = getContext().getApplicationContext()
-                .getSystemService(WifiManager.class);
-        if (wifiManager != null) {
-            wifiConfigurations = wifiManager.getAllMatchingWifiConfigs(scanResults);
+        mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
+        renewAccessPointList(scanResults);
+
+        notifyAdapterRefresh();
+    }
+
+    // Updates internal AccessPoint list from WifiTracker. scanResults are used to update key list
+    // of AccessPoint, and could be null if there is no necessary to update key list.
+    private void renewAccessPointList(List<ScanResult> scanResults) {
+        if (mFilterWifiTracker == null) {
+            return;
         }
 
-        setUpAccessPointList(wifiConfigurations);
+        // TODO(b/119846365): Checks if we could escalate the converting effort.
+        // Updates keys of scanResults into FilterWifiTracker for updating matched AccessPoints.
+        if (scanResults != null) {
+            mFilterWifiTracker.updateKeys(scanResults);
+        }
 
+        // Re-gets matched AccessPoints from WifiTracker.
+        final List<AccessPoint> list = getAccessPointList();
+        list.clear();
+        list.addAll(mFilterWifiTracker.getAccessPoints());
+    }
+
+    @VisibleForTesting
+    void notifyAdapterRefresh() {
         if (getDialogAdapter() != null) {
             getDialogAdapter().notifyDataSetChanged();
         }
@@ -278,48 +328,99 @@
 
     @Override
     public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) {
-        if (getDialogAdapter() != null) {
-            updateAccessPointListItem(wificonfiguration);
-            getDialogAdapter().notifyDataSetChanged();
-        }
+        // Dismisses current dialog, since connection is success.
+        dismiss();
     }
 
     @Override
     public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
-        if (mDialogAdapter != null) {
-            updateAccessPointListItem(wificonfiguration);
-            getDialogAdapter().notifyDataSetChanged();
-        }
+        stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
     }
 
-    private void updateAccessPointListItem(WifiConfiguration wificonfiguration) {
-        if (wificonfiguration == null) {
-            return;
+    private final class FilterWifiTracker {
+        private final List<String> mAccessPointKeys;
+        private final WifiTracker mWifiTracker;
+
+        public FilterWifiTracker(Context context, Lifecycle lifecycle) {
+            mWifiTracker = WifiTrackerFactory.create(context, mWifiListener,
+                    lifecycle, /* includeSaved */ true, /* includeScans */ true);
+            mAccessPointKeys = new ArrayList<>();
         }
 
-        final List<AccessPoint> accessPointList = getAccessPointList();
-        final int accessPointListSize = accessPointList.size();
-
-        for (int i = 0; i < accessPointListSize; i++) {
-            AccessPoint accessPoint = accessPointList.get(i);
-            // It is the same AccessPoint SSID, and should be replaced to update latest properties.
-            if (accessPoint.matches(wificonfiguration)) {
-                accessPointList.set(i, new AccessPoint(getContext(), wificonfiguration));
-                break;
+        /**
+         * Updates key list from input. {@code onMatch()} may be called in multi-times according
+         * wifi scanning result, so needs patchwork here.
+         */
+        public void updateKeys(List<ScanResult> scanResults) {
+            for (ScanResult scanResult : scanResults) {
+                final String key = AccessPoint.getKey(scanResult);
+                if (!mAccessPointKeys.contains(key)) {
+                    mAccessPointKeys.add(key);
+                }
             }
         }
-    }
 
-    private void setUpAccessPointList(List<WifiConfiguration> wifiConfigurations) {
-        // Grants for zero size input, since maybe current wifi is off or somethings are wrong.
-        if (wifiConfigurations == null) {
-            return;
+        /**
+         * Returns only AccessPoints whose key is in {@code mAccessPointKeys}.
+         *
+         * @return List of matched AccessPoints.
+         */
+        public List<AccessPoint> getAccessPoints() {
+            final List<AccessPoint> allAccessPoints = mWifiTracker.getAccessPoints();
+            final List<AccessPoint> result = new ArrayList<>();
+
+            // The order should be kept, because order means wifi score (sorting in WifiTracker).
+            int count = 0;
+            for (AccessPoint accessPoint : allAccessPoints) {
+                final String key = accessPoint.getKey();
+                if (mAccessPointKeys.contains(key)) {
+                    result.add(accessPoint);
+
+                    count++;
+                    // Limits how many count of items could show.
+                    if (count >= MAX_NUMBER_LIST_ITEM) {
+                        break;
+                    }
+                }
+            }
+
+            return result;
         }
 
-        final List<AccessPoint> accessPointList = getAccessPointList();
-        accessPointList.clear();
-        for (WifiConfiguration config : wifiConfigurations) {
-            accessPointList.add(new AccessPoint(getContext(), config));
+        private WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
+
+            @Override
+            public void onWifiStateChanged(int state) {
+                notifyAdapterRefresh();
+            }
+
+            @Override
+            public void onConnectedChanged() {
+                notifyAdapterRefresh();
+            }
+
+            @Override
+            public void onAccessPointsChanged() {
+                notifyAdapterRefresh();
+            }
+        };
+
+        public void onDestroy() {
+            if (mWifiTracker != null) {
+                mWifiTracker.onDestroy();
+            }
+        }
+
+        public void onResume() {
+            if (mWifiTracker != null) {
+                mWifiTracker.onStart();
+            }
+        }
+
+        public void onPause() {
+            if (mWifiTracker != null) {
+                mWifiTracker.onStop();
+            }
         }
     }
 }
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 2e3b76a..67f59ea 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -279,7 +279,7 @@
                 mHiddenSettingsSpinner.setSelection(config.hiddenSSID
                         ? HIDDEN_NETWORK
                         : NOT_HIDDEN_NETWORK);
-                //TODO(b/117957974): set MAC randomization value to mPrivacySettingsSpinner
+                mPrivacySettingsSpinner.setSelection(config.macRandomizationSetting);
                 if (config.getIpAssignment() == IpAssignment.STATIC) {
                     mIpSettingsSpinner.setSelection(STATIC_IP);
                     showAdvancedFields = true;
@@ -759,7 +759,7 @@
         }
 
         if (mPrivacySettingsSpinner != null) {
-            //TODO(b/117957974): set MAC randomization value to WifiConfiguration
+            config.macRandomizationSetting = mPrivacySettingsSpinner.getSelectedItemPosition();
         }
 
         return config;
diff --git a/src/com/android/settings/wifi/WifiConnectionPreferenceController.java b/src/com/android/settings/wifi/WifiConnectionPreferenceController.java
new file mode 100644
index 0000000..b73bce9
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiConnectionPreferenceController.java
@@ -0,0 +1,177 @@
+/*
+ * 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.content.Context;
+import android.os.Bundle;
+
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.AccessPointPreference;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
+
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+
+/**
+ * This places a preference into a PreferenceGroup owned by some parent
+ * controller class when there is a wifi connection present.
+ */
+public class WifiConnectionPreferenceController extends AbstractPreferenceController implements
+        WifiTracker.WifiListener {
+
+    private static final String TAG = "WifiConnPrefCtrl";
+
+    private static final String KEY = "active_wifi_connection";
+
+    private UpdateListener mUpdateListener;
+    private Context mPrefContext;
+    private String mPreferenceGroupKey;
+    private PreferenceGroup mPreferenceGroup;
+    private WifiTracker mWifiTracker;
+    private AccessPointPreference mPreference;
+    private AccessPointPreference.UserBadgeCache mBadgeCache;
+    private int order;
+    private int mMetricsCategory;
+
+    /**
+     * Used to notify a parent controller that this controller has changed in availability, or has
+     * updated the content in the preference that it manages.
+     */
+    public interface UpdateListener {
+        void onChildrenUpdated();
+    }
+
+    /**
+     * @param context            the context for the UI where we're placing the preference
+     * @param lifecycle          for listening to lifecycle events for the UI
+     * @param updateListener     for notifying a parent controller of changes
+     * @param preferenceGroupKey the key to use to lookup the PreferenceGroup where this controller
+     *                           will add its preference
+     * @param order              the order that the preference added by this controller should use -
+     *                           useful when this preference needs to be ordered in a specific way
+     *                           relative to others in the PreferenceGroup
+     * @param metricsCategory    - the category to use as the source when handling the click on the
+     *                           pref to go to the wifi connection detail page
+     */
+    public WifiConnectionPreferenceController(Context context, Lifecycle lifecycle,
+            UpdateListener updateListener, String preferenceGroupKey, int order,
+            int metricsCategory) {
+        super(context);
+        mUpdateListener = updateListener;
+        mPreferenceGroupKey = preferenceGroupKey;
+        mWifiTracker = WifiTrackerFactory.create(context, this, lifecycle, true /* includeSaved */,
+                true /* includeScans */);
+        this.order = order;
+        mMetricsCategory = metricsCategory;
+        mBadgeCache = new AccessPointPreference.UserBadgeCache(context.getPackageManager());
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mWifiTracker.isConnected() && getCurrentAccessPoint() != null;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreferenceGroup = (PreferenceGroup) screen.findPreference(mPreferenceGroupKey);
+        mPrefContext = screen.getContext();
+        update();
+    }
+
+    private AccessPoint getCurrentAccessPoint() {
+        for (AccessPoint accessPoint : mWifiTracker.getAccessPoints()) {
+            if (accessPoint.isActive()) {
+                return accessPoint;
+            }
+        }
+        return null;
+    }
+
+    private void updatePreference(AccessPoint accessPoint) {
+        if (mPreference != null) {
+            mPreferenceGroup.removePreference(mPreference);
+            mPreference = null;
+        }
+        if (accessPoint == null) {
+            return;
+        }
+        if (mPrefContext != null) {
+            mPreference = new AccessPointPreference(accessPoint, mPrefContext, mBadgeCache,
+                    R.drawable.ic_wifi_signal_0, false /* forSavedNetworks */);
+            mPreference.setKey(KEY);
+            mPreference.refresh();
+            mPreference.setOrder(order);
+
+            mPreference.setOnPreferenceClickListener(pref -> {
+                Bundle args = new Bundle();
+                mPreference.getAccessPoint().saveWifiState(args);
+                new SubSettingLauncher(mPrefContext)
+                        .setTitleRes(R.string.pref_title_network_details)
+                        .setDestination(WifiNetworkDetailsFragment.class.getName())
+                        .setArguments(args)
+                        .setSourceMetricsCategory(mMetricsCategory)
+                        .launch();
+                return true;
+            });
+            mPreferenceGroup.addPreference(mPreference);
+        }
+    }
+
+    private void update() {
+        AccessPoint connectedAccessPoint = null;
+        if (mWifiTracker.isConnected()) {
+            connectedAccessPoint = getCurrentAccessPoint();
+        }
+        if (connectedAccessPoint == null) {
+            updatePreference(null);
+        } else {
+          if (mPreference == null || !mPreference.getAccessPoint().equals(connectedAccessPoint)) {
+              updatePreference(connectedAccessPoint);
+          } else if (mPreference != null) {
+              mPreference.refresh();
+          }
+        }
+        mUpdateListener.onChildrenUpdated();
+    }
+
+    @Override
+    public void onWifiStateChanged(int state) {
+        update();
+    }
+
+    @Override
+    public void onConnectedChanged() {
+        update();
+    }
+
+    @Override
+    public void onAccessPointsChanged() {
+        update();
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiDialog.java b/src/com/android/settings/wifi/WifiDialog.java
index 0e2ca60..0bee671 100644
--- a/src/com/android/settings/wifi/WifiDialog.java
+++ b/src/com/android/settings/wifi/WifiDialog.java
@@ -86,9 +86,13 @@
             if (scannerButton != null) {
                 scannerButton.setVisibility(View.VISIBLE);
                 scannerButton.setOnClickListener((View v) -> {
+                    String ssid = null;
+                    if (mAccessPoint != null) {
+                        ssid = mAccessPoint.getSsidStr();
+                    }
                     // Launch QR code scanner to join a network.
                     getContext().startActivity(
-                            WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
+                            WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid));
                 });
             }
         }
diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java
index 9ef6a39..c32bcf3 100644
--- a/src/com/android/settings/wifi/WifiDialogActivity.java
+++ b/src/com/android/settings/wifi/WifiDialogActivity.java
@@ -38,6 +38,8 @@
 
     private static final String TAG = "WifiDialogActivity";
 
+    public static final String KEY_ACCESS_POINT_STATE = "access_point_state";
+
     /**
      * Boolean extra indicating whether this activity should connect to an access point on the
      * caller's behalf. If this is set to false, the caller should check
@@ -46,9 +48,8 @@
      */
     @VisibleForTesting
     static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller";
-    static final String KEY_ACCESS_POINT_STATE = "access_point_state";
-    private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration";
 
+    private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration";
     private static final int RESULT_CONNECTED = RESULT_FIRST_USER;
     private static final int RESULT_FORGET = RESULT_FIRST_USER + 1;
 
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 54de28d..95e912d 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -244,7 +244,7 @@
             mAddPreference.setButtonOnClickListener((View v) -> {
                 // Launch QR code scanner to join a network.
                 getContext().startActivity(
-                        WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
+                        WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
             });
         }
         mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index ff8570e..7970b2a 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -22,10 +22,13 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.NetworkCapabilities;
+import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.provider.Settings;
 import android.text.TextUtils;
 
+import com.android.settingslib.wifi.AccessPoint;
+
 import java.nio.charset.StandardCharsets;
 
 public class WifiUtils {
@@ -110,4 +113,144 @@
         return (capabilities != null
                 && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL));
     }
+
+    /**
+     * Provides a simple way to generate a new {@link WifiConfiguration} obj from
+     * {@link ScanResult} or {@link AccessPoint}. Either {@code accessPoint} or {@code scanResult
+     * } input should be not null for retrieving information, otherwise will throw
+     * IllegalArgumentException.
+     * This method prefers to take {@link AccessPoint} input in priority. Therefore this method
+     * will take {@link AccessPoint} input as preferred data extraction source when you input
+     * both {@link AccessPoint} and {@link ScanResult}, and ignore {@link ScanResult} input.
+     *
+     * Duplicated and simplified method from {@link WifiConfigController#getConfig()}.
+     * TODO(b/120827021): Should be removed if the there is have a common one in shared place (e.g.
+     * SettingsLib).
+     *
+     * @param accessPoint Input data for retrieving WifiConfiguration.
+     * @param scanResult  Input data for retrieving WifiConfiguration.
+     * @return WifiConfiguration obj based on input.
+     */
+    public static WifiConfiguration getWifiConfig(AccessPoint accessPoint, ScanResult scanResult,
+            String password) {
+        if (accessPoint == null && scanResult == null) {
+            throw new IllegalArgumentException(
+                    "At least one of AccessPoint and ScanResult input is required.");
+        }
+
+        final WifiConfiguration config = new WifiConfiguration();
+        final int security;
+
+        if (accessPoint == null) {
+            config.SSID = AccessPoint.convertToQuotedString(scanResult.SSID);
+            security = getAccessPointSecurity(scanResult);
+        } else {
+            if (!accessPoint.isSaved()) {
+                config.SSID = AccessPoint.convertToQuotedString(
+                        accessPoint.getSsidStr());
+            } else {
+                config.networkId = accessPoint.getConfig().networkId;
+                config.hiddenSSID = accessPoint.getConfig().hiddenSSID;
+            }
+            security = accessPoint.getSecurity();
+        }
+
+        switch (security) {
+            case AccessPoint.SECURITY_NONE:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                break;
+
+            case AccessPoint.SECURITY_WEP:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
+                if (!TextUtils.isEmpty(password)) {
+                    int length = password.length();
+                    // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
+                    if ((length == 10 || length == 26 || length == 58)
+                            && password.matches("[0-9A-Fa-f]*")) {
+                        config.wepKeys[0] = password;
+                    } else {
+                        config.wepKeys[0] = '"' + password + '"';
+                    }
+                }
+                break;
+
+            case AccessPoint.SECURITY_PSK:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                if (!TextUtils.isEmpty(password)) {
+                    if (password.matches("[0-9A-Fa-f]{64}")) {
+                        config.preSharedKey = password;
+                    } else {
+                        config.preSharedKey = '"' + password + '"';
+                    }
+                }
+                break;
+
+            case AccessPoint.SECURITY_EAP:
+            case AccessPoint.SECURITY_EAP_SUITE_B:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+                if (security == AccessPoint.SECURITY_EAP_SUITE_B) {
+                    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
+                    config.requirePMF = true;
+                    config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
+                    config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+                    config.allowedGroupMgmtCiphers.set(WifiConfiguration.GroupMgmtCipher
+                            .BIP_GMAC_256);
+                    config.allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+                }
+
+                if (!TextUtils.isEmpty(password)) {
+                    config.enterpriseConfig.setPassword(password);
+                }
+                break;
+            case AccessPoint.SECURITY_SAE:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
+                config.requirePMF = true;
+                if (!TextUtils.isEmpty(password)) {
+                    config.preSharedKey = '"' + password + '"';
+                }
+                break;
+
+            case AccessPoint.SECURITY_OWE:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
+                config.requirePMF = true;
+                break;
+
+            default:
+                break;
+        }
+
+        return config;
+    }
+
+
+    /**
+     * Gets security value from ScanResult.
+     *
+     * Duplicated method from {@link AccessPoint#getSecurity(ScanResult)}.
+     * TODO(b/120827021): Should be removed if the there is have a common one in shared place (e.g.
+     * SettingsLib).
+     *
+     * @param result ScanResult
+     * @return Related security value based on {@link AccessPoint}.
+     */
+    public static int getAccessPointSecurity(ScanResult result) {
+        if (result.capabilities.contains("WEP")) {
+            return AccessPoint.SECURITY_WEP;
+        } else if (result.capabilities.contains("SAE")) {
+            return AccessPoint.SECURITY_SAE;
+        } else if (result.capabilities.contains("PSK")) {
+            return AccessPoint.SECURITY_PSK;
+        } else if (result.capabilities.contains("EAP_SUITE_B_192")) {
+            return AccessPoint.SECURITY_EAP_SUITE_B;
+        } else if (result.capabilities.contains("EAP")) {
+            return AccessPoint.SECURITY_EAP;
+        } else if (result.capabilities.contains("OWE")) {
+            return AccessPoint.SECURITY_OWE;
+        }
+
+        return AccessPoint.SECURITY_NONE;
+    }
 }
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index e1179f8..f3e8fc1 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -549,11 +549,8 @@
      * 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,
+        Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntent(mAccessPoint.getSsidStr(),
                 mAccessPoint.getSecurityString(/* concise */ false));
-        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, mAccessPoint.getSsidStr());
         mContext.startActivity(intent);
     }
 
diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
index 177e79d..8d6aa68 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
@@ -18,6 +18,7 @@
 
 import android.os.Bundle;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 
 /**
@@ -31,6 +32,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
+    }
+
+    @Override
     public void onActivityCreated (Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
     }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
index 7d031c1..66bc349 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
@@ -18,6 +18,7 @@
 
 import android.os.Bundle;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 
 /**
@@ -31,6 +32,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
+    }
+
+    @Override
     public void onActivityCreated (Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
     }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index e4ae292..6c95f09 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -27,7 +27,6 @@
 import androidx.fragment.app.FragmentTransaction;
 
 import com.android.internal.logging.nano.MetricsProto;
-
 import com.android.settings.core.InstrumentedActivity;
 import com.android.settings.R;
 
@@ -67,8 +66,7 @@
 
     @Override
     public int getMetricsCategory() {
-        //TODO:Should we use a new metrics category for Wi-Fi DPP?
-        return MetricsProto.MetricsEvent.WIFI_NETWORK_DETAILS;
+        return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
index 7c58fd5..920e736 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
@@ -27,7 +27,6 @@
 import androidx.fragment.app.FragmentTransaction;
 
 import com.android.internal.logging.nano.MetricsProto;
-
 import com.android.settings.core.InstrumentedActivity;
 import com.android.settings.R;
 
@@ -35,7 +34,7 @@
  * To provision "this" device with specified Wi-Fi network.
  *
  * To use intent action {@code ACTION_ENROLLEE_QR_CODE_SCANNER}, specify the SSID string of the
- * Wi-Fi network to be provisioned in {@code WifiDppUtils.EXTRA_QR_CODE}.
+ * Wi-Fi network to be provisioned in {@code WifiDppUtils.EXTRA_WIFI_SSID}.
  */
 public class WifiDppEnrolleeActivity extends InstrumentedActivity {
     private static final String TAG = "WifiDppEnrolleeActivity";
@@ -47,8 +46,7 @@
 
     @Override
     public int getMetricsCategory() {
-        //TODO:Should we use a new metrics category for Wi-Fi DPP?
-        return MetricsProto.MetricsEvent.WIFI_NETWORK_DETAILS;
+        return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_ENROLLEE;
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
index cddd55c..6792dee 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
@@ -18,7 +18,6 @@
 
 import android.os.Bundle;
 import android.view.LayoutInflater;
-import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
@@ -27,14 +26,11 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-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;
 
 /**
- * TODO: Should refine code to only initiate UI component in each child fragment.
+ * TODO: b/120645817 should refine code to only initiate UI component in each child fragment.
  */
 
 /**
@@ -47,17 +43,12 @@
  * {@code WifiDppAddDeviceFragment}
  */
 public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
+    private ImageView mHeaderIcon;
     private TextView mTitle;
     private TextView mDescription;
 
-    private SurfaceView mPreviewView;       //optional, for WifiDppQrCodeScannerFragment
-    private QrDecorateView mDecorateViiew;  //optional, for WifiDppQrCodeScannerFragment
     private TextView mErrorMessage;         //optional, for WifiDppQrCodeScannerFragment
-
-    private ImageView mBarcodeView;         //optional, for WifiDppQrCodeGeneratorFragment
-
     private ListView mSavedWifiNetworkList; //optional, for WifiDppChooseSavedWifiNetworkFragment
-
     private ProgressBar mProgressBar;       //optional, for WifiDppAddDeviceFragment
     private ImageView mWifiApPictureView;   //optional, for WifiDppAddDeviceFragment
     private TextView mChooseDifferentNetwork;//optional, for WifiDppAddDeviceFragment
@@ -70,12 +61,6 @@
     abstract protected int getLayout();
 
     @Override
-    public int getMetricsCategory() {
-        //TODO:Should we use a new metrics category for Wi-Fi DPP?
-        return MetricsProto.MetricsEvent.WIFI_NETWORK_DETAILS;
-    }
-
-    @Override
     public final void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
     }
@@ -89,15 +74,11 @@
     }
 
     private void initView(View view) {
+        mHeaderIcon = view.findViewById(R.id.header_icon);
         mTitle = view.findViewById(R.id.title);
         mDescription = view.findViewById(R.id.description);
-
-        mPreviewView = view.findViewById(R.id.preview_view);
-        mDecorateViiew = view.findViewById(R.id.decorate_view);
         mErrorMessage = view.findViewById(R.id.error_message);
 
-        mBarcodeView = view.findViewById(R.id.barcode_view);
-
         mSavedWifiNetworkList = view.findViewById(R.id.saved_wifi_network_list);
 
         mProgressBar = view.findViewById(R.id.progress_bar);
@@ -108,6 +89,10 @@
         mButtonRight = view.findViewById(R.id.button_right);
     }
 
+    protected void setHeaderIconImageResource(int resId) {
+        mHeaderIcon.setImageResource(resId);
+    }
+
     protected void setTitle(String title) {
         mTitle.setText(title);
     }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index b064253..81def9b 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -23,6 +23,7 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 
 /**
@@ -35,6 +36,11 @@
         return R.layout.wifi_dpp_qrcode_generator_fragment;
     }
 
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
+    }
+
     // Container Activity must implement this interface
     public interface OnQrCodeGeneratorFragmentAddButtonClickedListener {
         public void onQrCodeGeneratorFragmentAddButtonClicked();
@@ -45,6 +51,7 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
+        setHeaderIconImageResource(R.drawable.ic_qrcode_24dp);
         WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
                 .getWifiNetworkConfig();
         if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
@@ -79,7 +86,7 @@
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.next_label);
-        item.setIcon(R.drawable.ic_menu_add);
+        item.setIcon(R.drawable.ic_scan_24dp);
         item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
 
         super.onCreateOptionsMenu(menu, inflater);
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 5689c56..8cd3c562 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -21,24 +21,28 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
 import android.os.Bundle;
+import android.text.TextUtils;
 import android.util.Size;
 import android.view.Menu;
 import android.view.MenuInflater;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
+import android.view.TextureView;
+import android.view.TextureView.SurfaceTextureListener;
 import android.view.View;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.wifi.qrcode.QrCamera;
 import com.android.settings.wifi.qrcode.QrDecorateView;
 
 public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
-        SurfaceHolder.Callback,
+        SurfaceTextureListener,
         QrCamera.ScannerCallback {
     private QrCamera mCamera;
-    private SurfaceView mSurfaceView;
+    private TextureView mTextureView;
     private QrDecorateView mDecorateView;
 
     /** true if the fragment working for configurator, false enrollee*/
@@ -52,6 +56,15 @@
         return R.layout.wifi_dpp_qrcode_scanner_fragment;
     }
 
+    @Override
+    public int getMetricsCategory() {
+        if (mConfiguratorMode) {
+            return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
+        } else {
+            return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_ENROLLEE;
+        }
+    }
+
     /**
      * Configurator container activity of the fragment should create instance with this constructor.
      */
@@ -76,6 +89,8 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
+        setHeaderIconImageResource(R.drawable.ic_scan_24dp);
+
         if (mConfiguratorMode) {
             setTitle(getString(R.string.wifi_dpp_add_device_to_network));
 
@@ -87,7 +102,14 @@
             setDescription(getString(R.string.wifi_dpp_center_qr_code, wifiNetworkConfig.getSsid()));
         } else {
             setTitle(getString(R.string.wifi_dpp_scan_qr_code));
-            setDescription(getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid));
+
+            String description;
+            if (TextUtils.isEmpty(mSsid)) {
+                description = getString(R.string.wifi_dpp_scan_qr_code_join_unknown_network, mSsid);
+            } else {
+                description = getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid);
+            }
+            setDescription(description);
         }
 
         ActionBar actionBar = getActivity().getActionBar();
@@ -101,23 +123,13 @@
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
-        mSurfaceView = (SurfaceView) view.findViewById(R.id.preview_view);
-        final SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
-        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
-        surfaceHolder.addCallback(this);
+        mTextureView = (TextureView) view.findViewById(R.id.preview_view);
+        mTextureView.setSurfaceTextureListener(this);
 
         mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view);
     }
 
     @Override
-    public void onDestroyView() {
-        SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
-        surfaceHolder.removeCallback(this);
-
-        super.onDestroyView();
-    }
-
-    @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         menu.removeItem(Menu.FIRST);
 
@@ -125,23 +137,29 @@
     }
 
     @Override
-    public void surfaceCreated(final SurfaceHolder holder) {
-        initCamera(holder);
+    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+        initCamera(surface);
     }
 
     @Override
-    public void surfaceDestroyed(SurfaceHolder holder) {
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        // Do nothing
+    }
+
+    @Override
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
         destroyCamera();
+        return true;
     }
 
     @Override
-    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
         // Do nothing
     }
 
     @Override
     public Size getViewSize() {
-        return new Size(mSurfaceView.getWidth(), mSurfaceView.getHeight());
+        return new Size(mTextureView.getWidth(), mTextureView.getHeight());
     }
 
     @Override
@@ -150,6 +168,11 @@
     }
 
     @Override
+    public void setTransform(Matrix transform) {
+        mTextureView.setTransform(transform);
+    }
+
+    @Override
     public void handleSuccessfulResult(String qrCode) {
         destroyCamera();
         mDecorateView.setFocused(true);
@@ -161,11 +184,11 @@
         destroyCamera();
     }
 
-    private void initCamera(SurfaceHolder holder) {
+    private void initCamera(SurfaceTexture surface) {
         // Check if the camera has already created.
         if (mCamera == null) {
             mCamera = new QrCamera(getContext(), this);
-            mCamera.start(holder);
+            mCamera.start(surface);
         }
     }
 
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index dc0ff84..3275695 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -88,14 +88,14 @@
     }
 
     /**
-     * Returns an intent to launch QR code scanner.
+     * Returns an intent to launch QR code scanner for Wi-Fi DPP enrollee.
      *
      * @param ssid The data corresponding to {@code WifiConfiguration} SSID
      * @return Intent for launching QR code scanner
      */
-    public static Intent getConfiguratorQRCodeScannerIntent(String ssid) {
+    public static Intent getEnrolleeQrCodeScannerIntent(String ssid) {
         final Intent intent = new Intent(
-                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+                WifiDppEnrolleeActivity.ACTION_ENROLLEE_QR_CODE_SCANNER);
         if (!TextUtils.isEmpty(ssid)) {
             intent.putExtra(EXTRA_WIFI_SSID, ssid);
         }
@@ -109,7 +109,8 @@
      * @param Security The data is from {@code AccessPoint.securityToString}
      * @return Intent for launching QR code generator
      */
-    public static Intent getConfiguratorQRCodeGeneratorIntent(String ssid, String Security) {
+    public static Intent getConfiguratorQrCodeGeneratorIntent(String ssid, String Security) {
+        //TODO: b/118794858#comment6 should put password & hideSsid in intent extra
         final Intent intent = new Intent(
                 WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
         if (!TextUtils.isEmpty(ssid)) {
diff --git a/src/com/android/settings/wifi/qrcode/QrCamera.java b/src/com/android/settings/wifi/qrcode/QrCamera.java
index dc650b9..c60c30e 100644
--- a/src/com/android/settings/wifi/qrcode/QrCamera.java
+++ b/src/com/android/settings/wifi/qrcode/QrCamera.java
@@ -17,7 +17,10 @@
 package com.android.settings.wifi.qrcode;
 
 import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
 import android.hardware.Camera.CameraInfo;
 import android.hardware.Camera.Parameters;
@@ -29,7 +32,6 @@
 import android.util.Log;
 import android.util.Size;
 import android.view.Surface;
-import android.view.SurfaceHolder;
 import android.view.WindowManager;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.BinaryBitmap;
@@ -50,7 +52,7 @@
 
 /**
  * Manage the camera for the QR scanner and help the decoder to get the image inside the scanning
- * frame. Caller prepares a {@link SurfaceHolder} then call {@link #start(SurfaceHolder)} to
+ * frame. Caller prepares a {@link SurfaceTexture} then call {@link #start(SurfaceTexture)} to
  * start QR Code scanning. The scanning result will return by ScannerCallback interface. Caller
  * can also call {@link #stop()} to halt QR Code scanning before the result returned.
  */
@@ -90,12 +92,11 @@
      * The function start camera preview and capture pictures to decode QR code continuously in a
      * background task.
      *
-     * @param surfaceHolder the Surface to be used for live preview, must already contain a surface
-     *                      when this method is called.
+     * @param surface The surface to be used for live preview.
      */
-    public void start(SurfaceHolder surfaceHolder) {
+    public void start(SurfaceTexture surface) {
         if (mDecodeTask == null) {
-            mDecodeTask = new DecodingTask(surfaceHolder);
+            mDecodeTask = new DecodingTask(surface);
             // Execute in the separate thread pool to prevent block other AsyncTask.
             mDecodeTask.executeOnExecutor(Executors.newSingleThreadExecutor());
         }
@@ -144,6 +145,13 @@
          * @return The rectangle would like to crop from the camera preview shot.
          */
         Rect getFramePosition(Size previewSize, int cameraOrientation);
+
+        /**
+         * Sets the transform to associate with preview area.
+         *
+         * @param transform The transform to apply to the content of preview
+         */
+        void setTransform(Matrix transform);
     }
 
     private void setCameraParameter() {
@@ -200,15 +208,15 @@
 
     private class DecodingTask extends AsyncTask<Void, Void, String> {
         private QrYuvLuminanceSource mImage;
-        private SurfaceHolder mSurfaceHolder;
+        private SurfaceTexture mSurface;
 
-        private DecodingTask(SurfaceHolder surfaceHolder) {
-            mSurfaceHolder = surfaceHolder;
+        private DecodingTask(SurfaceTexture surface) {
+            mSurface = surface;
         }
 
         @Override
         protected String doInBackground(Void... tmp) {
-            if (!initCamera(mSurfaceHolder)) {
+            if (!initCamera(mSurface)) {
                 return null;
             }
 
@@ -253,7 +261,7 @@
             }
         }
 
-        private boolean initCamera(SurfaceHolder surfaceHolder) {
+        private boolean initCamera(SurfaceTexture surface) {
             final int numberOfCameras = Camera.getNumberOfCameras();
             Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
             try {
@@ -261,7 +269,7 @@
                     Camera.getCameraInfo(i, cameraInfo);
                     if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                         mCamera = Camera.open(i);
-                        mCamera.setPreviewDisplay(surfaceHolder);
+                        mCamera.setPreviewTexture(surface);
                         mCameraOrientation = cameraInfo.orientation;
                         break;
                     }
@@ -272,6 +280,7 @@
                     return false;
                 }
                 setCameraParameter();
+                setTransformationMatrix(mScannerCallback.getViewSize());
                 if (!startPreview()) {
                     Log.e(TAG, "Error to init Camera");
                     mCamera = null;
@@ -288,6 +297,36 @@
         }
     }
 
+    /** Set transfom matrix to crop and center the preview picture */
+    private void setTransformationMatrix(Size viewSize) {
+        // Check aspect ratio, can only handle square view.
+        final int viewRatio = (int)getRatio(viewSize.getWidth(), viewSize.getHeight());
+        if (viewRatio != 1) {
+            throw new IllegalArgumentException("Preview area should be square");
+        }
+
+        final boolean isPortrait = mContext.get().getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_PORTRAIT ? true : false;
+
+        final int previewWidth = isPortrait ? mPreviewSize.getWidth() : mPreviewSize.getHeight();
+        final int previewHeight = isPortrait ? mPreviewSize.getHeight() : mPreviewSize.getWidth();
+        final float ratioPreview = (float) getRatio(previewWidth, previewHeight);
+
+        // Calculate transformation matrix.
+        float scaleX = 1.0f;
+        float scaleY = 1.0f;
+        if (previewWidth > previewHeight) {
+            scaleY = scaleX / ratioPreview;
+        } else {
+            scaleX = scaleY / ratioPreview;
+        }
+
+        // Set the transform matrix.
+        final Matrix matrix = new Matrix();
+        matrix.setScale(scaleX, scaleY);
+        mScannerCallback.setTransform(matrix);
+    }
+
     private QrYuvLuminanceSource getFrameImage(byte[] imageData) {
         final Rect frame = mScannerCallback.getFramePosition(mPreviewSize, mCameraOrientation);
         final Camera.Size size = mParameters.getPictureSize();
diff --git a/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java b/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java
new file mode 100644
index 0000000..56566ae
--- /dev/null
+++ b/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java
@@ -0,0 +1,50 @@
+/*
+ * 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.qrcode;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.FrameLayout;
+
+/**
+ * A customize square {@link FrameLayout}.
+ * This is used for camera preview. Choose the smaller size of both dimensions as length and width.
+ */
+public class QrPreviewLayout extends FrameLayout {
+    public QrPreviewLayout(Context context) {
+        super(context);
+    }
+
+    public QrPreviewLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public QrPreviewLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // Choose the smaller size of the two dimensions.
+        if (MeasureSpec.getSize(widthMeasureSpec) > MeasureSpec.getSize(heightMeasureSpec)) {
+            super.onMeasure(heightMeasureSpec, heightMeasureSpec);
+        } else {
+            super.onMeasure(widthMeasureSpec, widthMeasureSpec);
+        }
+    }
+}
diff --git a/src/com/android/settings/wifi/slice/ContextualWifiSlice.java b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
new file mode 100644
index 0000000..fa8c267
--- /dev/null
+++ b/src/com/android/settings/wifi/slice/ContextualWifiSlice.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.wifi.slice;
+
+import android.content.Context;
+import android.net.Uri;
+import android.net.wifi.WifiSsid;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.slice.Slice;
+
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
+
+/**
+ * {@link CustomSliceable} for Wi-Fi, used by contextual homepage.
+ */
+public class ContextualWifiSlice extends WifiSlice {
+
+    private static final String TAG = "ContextualWifiSlice";
+    @VisibleForTesting
+    boolean mPreviouslyDisplayed;
+
+    public ContextualWifiSlice(Context context) {
+        super(context);
+    }
+
+    @Override
+    public Uri getUri() {
+        return CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI;
+    }
+
+    @Override
+    public Slice getSlice() {
+        if (!mPreviouslyDisplayed && !TextUtils.equals(getActiveSSID(), WifiSsid.NONE)) {
+            Log.d(TAG, "Wifi is connected, no point showing any suggestion.");
+            return null;
+        }
+        // Set mPreviouslyDisplayed to true - we will show *something* on the screen. So we should
+        // keep showing this card to keep UI stable, even if wifi connects to a network later.
+        mPreviouslyDisplayed = true;
+
+        return super.getSlice();
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java
similarity index 95%
rename from src/com/android/settings/wifi/WifiSlice.java
rename to src/com/android/settings/wifi/slice/WifiSlice.java
index 9f05783..4d3a95a 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.wifi;
+package com.android.settings.wifi.slice;
 
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 import static android.provider.SettingsSlicesContract.KEY_WIFI;
@@ -46,6 +46,8 @@
 import com.android.settings.slices.CustomSliceable;
 import com.android.settings.slices.SliceBackgroundWorker;
 import com.android.settings.slices.SliceBuilderUtils;
+import com.android.settings.wifi.WifiDialogActivity;
+import com.android.settings.wifi.WifiSettings;
 import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.settingslib.wifi.WifiTracker;
@@ -54,15 +56,15 @@
 import java.util.List;
 
 /**
- * Utility class to build a Wifi Slice, and handle all associated actions.
+ * {@link CustomSliceable} for Wi-Fi, used by generic clients.
  */
 public class WifiSlice implements CustomSliceable {
 
     @VisibleForTesting
     static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
 
+    protected final WifiManager mWifiManager;
     private final Context mContext;
-    private final WifiManager mWifiManager;
 
     public WifiSlice(Context context) {
         mContext = context;
@@ -77,6 +79,7 @@
     @Override
     public Slice getSlice() {
         final boolean isWifiEnabled = isWifiEnabled();
+
         final IconCompat icon = IconCompat.createWithResource(mContext,
                 R.drawable.ic_settings_wireless);
         final String title = mContext.getString(R.string.wifi_settings);
@@ -208,6 +211,13 @@
         return intent;
     }
 
+    protected String getActiveSSID() {
+        if (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED) {
+            return WifiSsid.NONE;
+        }
+        return WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo().getSSID());
+    }
+
     private boolean isWifiEnabled() {
         switch (mWifiManager.getWifiState()) {
             case WifiManager.WIFI_STATE_ENABLED:
@@ -221,8 +231,7 @@
     private CharSequence getSummary() {
         switch (mWifiManager.getWifiState()) {
             case WifiManager.WIFI_STATE_ENABLED:
-                final String ssid = WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo()
-                        .getSSID());
+                final String ssid = getActiveSSID();
                 if (TextUtils.equals(ssid, WifiSsid.NONE)) {
                     return mContext.getText(R.string.disconnected);
                 }
diff --git a/tests/anomaly-tester/Android.mk b/tests/anomaly-tester/Android.mk
index 9a0a875..4dffeab 100644
--- a/tests/anomaly-tester/Android.mk
+++ b/tests/anomaly-tester/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
+    androidx.test.rules \
     mockito-target \
     ub-uiautomator \
     truth-prebuilt \
diff --git a/tests/anomaly-tester/AndroidManifest.xml b/tests/anomaly-tester/AndroidManifest.xml
index 7893b86..d6f68a8 100644
--- a/tests/anomaly-tester/AndroidManifest.xml
+++ b/tests/anomaly-tester/AndroidManifest.xml
@@ -44,7 +44,7 @@
     </application>
 
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.settings"
         android:label="Settings Test Cases">
     </instrumentation>
diff --git a/tests/anomaly-tester/src/com/android/settings/anomaly/tests/BluetoothAnomalyTest.java b/tests/anomaly-tester/src/com/android/settings/anomaly/tests/BluetoothAnomalyTest.java
index 3630ce4..0477e09 100644
--- a/tests/anomaly-tester/src/com/android/settings/anomaly/tests/BluetoothAnomalyTest.java
+++ b/tests/anomaly-tester/src/com/android/settings/anomaly/tests/BluetoothAnomalyTest.java
@@ -19,13 +19,14 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.Until;
 import android.text.format.DateUtils;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/anomaly-tester/src/com/android/settings/anomaly/tests/WakelockAnomalyTest.java b/tests/anomaly-tester/src/com/android/settings/anomaly/tests/WakelockAnomalyTest.java
index a2f3804..c44e2ea 100644
--- a/tests/anomaly-tester/src/com/android/settings/anomaly/tests/WakelockAnomalyTest.java
+++ b/tests/anomaly-tester/src/com/android/settings/anomaly/tests/WakelockAnomalyTest.java
@@ -19,13 +19,14 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.Until;
 import android.text.format.DateUtils;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor b/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor
index befd880..ce03d95 100644
--- a/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor
+++ b/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor
@@ -7,7 +7,6 @@
 com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController
 com.android.settings.datausage.DataUsageSummaryPreferenceController
 com.android.settings.fuelgauge.RestrictAppPreferenceController
-com.android.settings.fuelgauge.batterysaver.AutoBatterySeekBarPreferenceController
 com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceController
 com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController
 com.android.settings.security.VisiblePatternProfilePreferenceController
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index c5c552e..101a6b8 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -58,6 +58,9 @@
     <bool name="config_show_system_update_settings">false</bool>
     <bool name="config_wifi_support_connected_mac_randomization">false</bool>
     <bool name="config_show_device_model">false</bool>
+    <bool name="config_show_top_level_battery">false</bool>
+    <bool name="config_show_top_level_connected_devices">false</bool>
+    <bool name="config_show_top_level_display">false</bool>
     <bool name="config_show_wifi_ip_address">false</bool>
     <bool name="config_show_wifi_mac_address">false</bool>
     <bool name="config_disable_uninstall_update">true</bool>
diff --git a/tests/robotests/src/com/android/settings/MasterClearTest.java b/tests/robotests/src/com/android/settings/MasterClearTest.java
index 21cb09c..388440e 100644
--- a/tests/robotests/src/com/android/settings/MasterClearTest.java
+++ b/tests/robotests/src/com/android/settings/MasterClearTest.java
@@ -51,6 +51,7 @@
 import androidx.fragment.app.FragmentActivity;
 
 import com.android.settings.testutils.shadow.ShadowUtils;
+import com.google.android.setupcompat.item.FooterButton;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -386,7 +387,7 @@
     public void testOnGlobalLayout_shouldNotRemoveListener() {
         final ViewTreeObserver viewTreeObserver = mock(ViewTreeObserver.class);
         mMasterClear.mScrollView = mScrollView;
-        mMasterClear.mInitiateButton = mock(Button.class);
+        mMasterClear.mInitiateButton = mock(FooterButton.class);
         doReturn(true).when(mMasterClear).hasReachedBottom(any());
         when(mScrollView.getViewTreeObserver()).thenReturn(viewTreeObserver);
 
diff --git a/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java b/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
index 5136973..6007791 100644
--- a/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
@@ -21,8 +21,6 @@
 import android.content.Intent;
 import android.os.SystemProperties;
 
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
 import com.google.android.setupcompat.util.WizardManagerHelper;
 import com.google.android.setupdesign.util.ThemeHelper;
 
diff --git a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
index 9cfdf98..ebbf5e0 100644
--- a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.app.admin.DevicePolicyManager;
@@ -30,6 +31,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.location.LocationManager;
 import android.os.Build;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -83,6 +85,8 @@
     private IPackageManager mPackageManagerService;
     @Mock
     private DevicePolicyManager mDevicePolicyManager;
+    @Mock
+    private LocationManager mLocationManager;
 
     private ApplicationFeatureProvider mProvider;
 
@@ -95,6 +99,7 @@
 
         when(mContext.getApplicationContext()).thenReturn(mContext);
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager);
 
         mProvider = new ApplicationFeatureProviderImpl(mContext, mPackageManager,
                 mPackageManagerService, mDevicePolicyManager);
@@ -255,19 +260,27 @@
 
     @Test
     @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class})
-    public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSms() {
+    public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSmsAndLocationHistory() {
         final String testDialer = "com.android.test.defaultdialer";
         final String testSms = "com.android.test.defaultsms";
+        final String testLocationHistory = "com.android.test.location.history";
+
         final String settingsIntelligence = RuntimeEnvironment.application.getString(
                 R.string.config_settingsintelligence_package_name);
         ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
         ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
-        ReflectionHelpers.setField(mProvider, "mContext", RuntimeEnvironment.application);
+
+        // Spy the real context to mock LocationManager.
+        Context spyContext = spy(RuntimeEnvironment.application);
+        when(mLocationManager.getLocationControllerExtraPackage()).thenReturn(testLocationHistory);
+        when(spyContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager);
+
+        ReflectionHelpers.setField(mProvider, "mContext", spyContext);
 
         final Set<String> keepEnabledPackages = mProvider.getKeepEnabledPackages();
 
         final List<String> expectedPackages = Arrays.asList(testDialer, testSms,
-                settingsIntelligence);
+                settingsIntelligence, testLocationHistory);
         assertThat(keepEnabledPackages).containsExactlyElementsIn(expectedPackages);
     }
 
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/RolesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/RolesPreferenceControllerTest.java
index 0946f37..5bf2b7e 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/RolesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/RolesPreferenceControllerTest.java
@@ -32,7 +32,6 @@
 import androidx.preference.Preference;
 
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -40,8 +39,9 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(SettingsRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 public class RolesPreferenceControllerTest {
 
     private static final String PREFERENCE_KEY = "roles";
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsControllerTest.java
new file mode 100644
index 0000000..39a05cb
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsControllerTest.java
@@ -0,0 +1,125 @@
+package com.android.settings.applications.specialaccess.financialapps;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import static android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS;
+import static android.Manifest.permission.READ_SMS;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
+public class FinancialAppsControllerTest {
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private AppOpsManager mAppOpsManager;
+    @Mock
+    private PreferenceScreen mRoot;
+    @Mock
+    private Preference mPreference;
+
+    private Context mContext;
+    private PackageInfo mPackageInfoNoPermissionRequested;
+    private PackageInfo mPackageInfoPermissionRequestedQPlus;
+    private PackageInfo mPackageInfoPermissionRequestedPreQ;
+    private FinancialAppsController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+
+        initializePackageInfos();
+
+        mController = new FinancialAppsController(mContext, "key");
+        mController.displayPreference(mRoot);
+    }
+
+    private void initializePackageInfos() {
+      mPackageInfoNoPermissionRequested = new PackageInfo();
+      mPackageInfoNoPermissionRequested.applicationInfo = new ApplicationInfo();
+
+      mPackageInfoPermissionRequestedQPlus = new PackageInfo();
+      mPackageInfoPermissionRequestedQPlus.applicationInfo = new ApplicationInfo();
+      // TODO(b/121161546): update after robolectric test support Q
+      //mPackageInfoPermissionRequestedQPlus.applicationInfo.targetSdkVersion =
+      //        Build.VERSION_CODES.Q;
+      mPackageInfoPermissionRequestedQPlus.applicationInfo.uid = 2001;
+      mPackageInfoPermissionRequestedQPlus.applicationInfo.nonLocalizedLabel = "QPLUS Package";
+      mPackageInfoPermissionRequestedQPlus.packageName = "QPLUS";
+      mPackageInfoPermissionRequestedQPlus.requestedPermissions =
+              new String[] {SMS_FINANCIAL_TRANSACTIONS};
+
+      mPackageInfoPermissionRequestedPreQ = new PackageInfo();
+      mPackageInfoPermissionRequestedPreQ.applicationInfo = new ApplicationInfo();
+      mPackageInfoPermissionRequestedPreQ.applicationInfo.targetSdkVersion = Build.VERSION_CODES.M;
+      mPackageInfoPermissionRequestedPreQ.applicationInfo.uid = 2002;
+      mPackageInfoPermissionRequestedPreQ.applicationInfo.nonLocalizedLabel = "PREQ Package";
+      mPackageInfoPermissionRequestedPreQ.packageName = "PREQ";
+      mPackageInfoPermissionRequestedPreQ.requestedPermissions = new String[] {READ_SMS};
+    }
+
+    @Test
+    public void isAvailable_true() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void noPreferenceAddedWhenNoPackageRequestPermission() {
+        when(mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS))
+            .thenReturn(new ArrayList<PackageInfo>(
+                    Arrays.asList(mPackageInfoNoPermissionRequested)));
+        mController.updateState(null);
+        assertThat(mController.mRoot.getPreferenceCount()).isEqualTo(0);
+    }
+
+    //TODO(b/121161546): Add these tests after robolectric test support Q
+    /*
+    @Test
+    public void preferenceAddedWhenPreQPackageRequestPermission() {
+        when(mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS))
+            .thenReturn(new ArrayList<PackageInfo>(
+                    Arrays.asList(mPackageInfoPermissionRequestedPreQ)));
+        mController.updateState(null);
+        assertThat(mController.mRoot.getPreferenceCount()).isEqualTo(1);
+        SwitchPreference pref = (SwitchPreference) mController.mRoot.getPreference(0);
+        assertThat(pref).isNotNull();
+    }
+
+    @Test
+    public void preferenceAddedWhenQPlusPackageRequestPermission() {
+        when(mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS))
+            .thenReturn(new ArrayList<PackageInfo>(
+                    Arrays.asList(mPackageInfoPermissionRequestedQPlus)));
+        mController.updateState(null);
+        assertThat(mController.mRoot.getPreferenceCount()).isEqualTo(1);
+        SwitchPreference pref = (SwitchPreference) mController.mRoot.getPreference(0);
+        assertThat(pref).isNotNull();
+        }*/
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
new file mode 100644
index 0000000..887f58c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothFeatureProviderImplTest {
+    private static final String PARAMETER_KEY = "addr";
+    private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
+    private BluetoothFeatureProvider mBluetoothFeatureProvider;
+
+    @Before
+    public void setUp() {
+        mBluetoothFeatureProvider = new BluetoothFeatureProviderImpl(
+                RuntimeEnvironment.application);
+    }
+
+    @Test
+    public void getBluetoothDeviceSettingsUri_containCorrectMacAddress() {
+        final Uri uri = mBluetoothFeatureProvider.getBluetoothDeviceSettingsUri(MAC_ADDRESS);
+        assertThat(uri.getQueryParameterNames()).containsExactly(PARAMETER_KEY);
+        assertThat(uri.getQueryParameter(PARAMETER_KEY)).isEqualTo(MAC_ADDRESS);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
index 8470ef9..c4b5901 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
@@ -119,7 +119,8 @@
         mAvailableMediaDeviceGroupController.onDeviceAdded(mPreference);
 
         assertThat(mPreferenceGroup.isVisible()).isTrue();
-        assertThat(mPreferenceGroup.findPreference(PREFERENCE_KEY_1)).isEqualTo(mPreference);
+        assertThat((Preference) mPreferenceGroup.findPreference(PREFERENCE_KEY_1))
+                .isEqualTo(mPreference);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
index c9e2644..23754a0 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
@@ -100,7 +100,8 @@
         mConnectedDeviceGroupController.onDeviceAdded(mPreference);
 
         assertThat(mPreferenceGroup.isVisible()).isTrue();
-        assertThat(mPreferenceGroup.findPreference(PREFERENCE_KEY_1)).isEqualTo(mPreference);
+        assertThat((Preference) mPreferenceGroup.findPreference(PREFERENCE_KEY_1))
+                .isEqualTo(mPreference);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/TopLevelConnectedDevicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/TopLevelConnectedDevicesPreferenceControllerTest.java
index f6b18a3..ab73370 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/TopLevelConnectedDevicesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/TopLevelConnectedDevicesPreferenceControllerTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.connecteddevice;
 
+import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
@@ -44,6 +47,17 @@
     }
 
     @Test
+    public void getAvailibilityStatus_availableByDefault() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void getAvailabilityStatus_unsupportedWhenSet() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
     @Config(shadows = ShadowAdvancedConnectedDeviceController.class)
     public void getSummary_shouldCallAdvancedConnectedDeviceController() {
         assertThat(mController.getSummary())
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdaterTest.java
index b698b3a..7c6a305 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdaterTest.java
@@ -15,6 +15,11 @@
  */
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.verify;
@@ -22,7 +27,6 @@
 
 import android.content.Context;
 import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
 
 import com.android.settings.R;
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
@@ -78,7 +82,7 @@
     public void initUsbPreference_usbConnected_preferenceAdded() {
         mDeviceUpdater.initUsbPreference(mContext);
         mDeviceUpdater.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
-                UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+                UsbManager.FUNCTION_NONE, POWER_ROLE_SINK, DATA_ROLE_DEVICE);
 
         verify(mDevicePreferenceCallback).onDeviceAdded(mDeviceUpdater.mUsbPreference);
     }
@@ -87,7 +91,7 @@
     public void initUsbPreference_usbDisconnected_preferenceRemoved() {
         mDeviceUpdater.initUsbPreference(mContext);
         mDeviceUpdater.mUsbConnectionListener.onUsbConnectionChanged(false /* connected */,
-                UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                UsbManager.FUNCTION_NONE, POWER_ROLE_NONE, DATA_ROLE_NONE);
 
         verify(mDevicePreferenceCallback).onDeviceRemoved(mDeviceUpdater.mUsbPreference);
     }
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbBackendTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbBackendTest.java
index 333d2b6..4e5897d 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbBackendTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbBackendTest.java
@@ -16,6 +16,11 @@
 
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Answers.RETURNS_DEEP_STUBS;
@@ -40,6 +45,8 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 
+import java.util.Collections;
+
 @RunWith(RobolectricTestRunner.class)
 public class UsbBackendTest {
 
@@ -64,9 +71,9 @@
         when((Object) mContext.getSystemService(UsbManager.class)).thenReturn(mUsbManager);
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(mConnectivityManager);
-        when(mUsbManager.getPorts()).thenReturn(new UsbPort[] {mUsbPort});
+        when(mUsbManager.getPorts()).thenReturn(Collections.singletonList(mUsbPort));
         when(mUsbPortStatus.isConnected()).thenReturn(true);
-        when(mUsbManager.getPortStatus(mUsbPort)).thenReturn(mUsbPortStatus);
+        when(mUsbPort.getStatus()).thenReturn(mUsbPortStatus);
     }
 
     @Test
@@ -74,22 +81,22 @@
         final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
 
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
+                .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE))
                 .thenReturn(true);
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST))
+                .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST))
                 .thenReturn(true);
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE))
+                .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE))
                 .thenReturn(true);
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST))
+                .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))
                 .thenReturn(true);
-        when(mUsbPortStatus.getCurrentPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+        when(mUsbPortStatus.getCurrentPowerRole()).thenReturn(POWER_ROLE_SINK);
 
-        usbBackend.setDataRole(UsbPort.DATA_ROLE_HOST);
+        usbBackend.setDataRole(DATA_ROLE_HOST);
 
-        verify(mUsbManager).setPortRoles(mUsbPort, UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST);
+        verify(mUsbPort).setRoles(POWER_ROLE_SINK, DATA_ROLE_HOST);
     }
 
     @Test
@@ -97,17 +104,16 @@
         final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
 
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
+                .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE))
                 .thenReturn(true);
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST))
+                .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))
                 .thenReturn(true);
-        when(mUsbPortStatus.getCurrentPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+        when(mUsbPortStatus.getCurrentPowerRole()).thenReturn(POWER_ROLE_SINK);
 
-        usbBackend.setDataRole(UsbPort.DATA_ROLE_HOST);
+        usbBackend.setDataRole(DATA_ROLE_HOST);
 
-        verify(mUsbManager)
-                .setPortRoles(mUsbPort, UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+        verify(mUsbPort).setRoles(POWER_ROLE_SOURCE, DATA_ROLE_HOST);
     }
 
     @Test
@@ -115,23 +121,22 @@
         final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
 
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
+                .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE))
                 .thenReturn(true);
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST))
+                .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST))
                 .thenReturn(true);
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE))
+                .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE))
                 .thenReturn(true);
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST))
+                .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))
                 .thenReturn(true);
-        when(mUsbPortStatus.getCurrentDataRole()).thenReturn(UsbPort.DATA_ROLE_DEVICE);
+        when(mUsbPortStatus.getCurrentDataRole()).thenReturn(DATA_ROLE_DEVICE);
 
-        usbBackend.setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+        usbBackend.setPowerRole(POWER_ROLE_SOURCE);
 
-        verify(mUsbManager)
-                .setPortRoles(mUsbPort, UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE);
+        verify(mUsbPort).setRoles(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE);
     }
 
     @Test
@@ -139,17 +144,16 @@
         final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
 
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
+                .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE))
                 .thenReturn(true);
         when(mUsbPortStatus
-                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST))
+                .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))
                 .thenReturn(true);
-        when(mUsbPortStatus.getCurrentDataRole()).thenReturn(UsbPort.DATA_ROLE_DEVICE);
+        when(mUsbPortStatus.getCurrentDataRole()).thenReturn(DATA_ROLE_DEVICE);
 
-        usbBackend.setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+        usbBackend.setPowerRole(POWER_ROLE_SOURCE);
 
-        verify(mUsbManager)
-                .setPortRoles(mUsbPort, UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+        verify(mUsbPort).setRoles(POWER_ROLE_SOURCE, DATA_ROLE_HOST);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
index 1689ee7..1da97f5 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
@@ -15,6 +15,11 @@
  */
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.verify;
@@ -22,7 +27,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
 import android.hardware.usb.UsbPortStatus;
 
 import org.junit.Before;
@@ -63,7 +67,7 @@
         mReceiver.onReceive(mContext, intent);
 
         verify(mListener).onUsbConnectionChanged(true /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
     }
 
     @Test
@@ -75,7 +79,7 @@
         mReceiver.onReceive(mContext, intent);
 
         verify(mListener).onUsbConnectionChanged(false /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
     }
 
     @Test
@@ -89,21 +93,21 @@
         mReceiver.onReceive(mContext, intent);
 
         verify(mListener).onUsbConnectionChanged(true /* connected */, UsbManager.FUNCTION_MTP,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
     }
 
     @Test
     public void onReceive_usbPortStatus_invokeCallback() {
         final Intent intent = new Intent();
         intent.setAction(UsbManager.ACTION_USB_PORT_CHANGED);
-        final UsbPortStatus status = new UsbPortStatus(0, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE, 0);
+        final UsbPortStatus status = new UsbPortStatus(0, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE, 0);
         intent.putExtra(UsbManager.EXTRA_PORT_STATUS, status);
 
         mReceiver.onReceive(mContext, intent);
 
         verify(mListener).onUsbConnectionChanged(false /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+                POWER_ROLE_SINK, DATA_ROLE_DEVICE);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleControllerTest.java
index 3eda3d1..91e680b 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleControllerTest.java
@@ -16,6 +16,12 @@
 
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -24,7 +30,6 @@
 
 import android.content.Context;
 import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
 import android.os.Handler;
 
 import androidx.fragment.app.FragmentActivity;
@@ -92,11 +97,11 @@
     public void displayRefresh_deviceRole_shouldCheckDevice() {
         mDetailsDataRoleController.displayPreference(mScreen);
 
-        mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
 
-        final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
-        final RadioButtonPreference hostPref = getRadioPreference(UsbPort.DATA_ROLE_HOST);
+        final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
+        final RadioButtonPreference hostPref = getRadioPreference(DATA_ROLE_HOST);
         assertThat(devicePref.isChecked()).isTrue();
         assertThat(hostPref.isChecked()).isFalse();
     }
@@ -105,11 +110,11 @@
     public void displayRefresh_hostRole_shouldCheckHost() {
         mDetailsDataRoleController.displayPreference(mScreen);
 
-        mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_HOST);
+        mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_HOST);
 
-        final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
-        final RadioButtonPreference hostPref = getRadioPreference(UsbPort.DATA_ROLE_HOST);
+        final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
+        final RadioButtonPreference hostPref = getRadioPreference(DATA_ROLE_HOST);
         assertThat(devicePref.isChecked()).isFalse();
         assertThat(hostPref.isChecked()).isTrue();
     }
@@ -118,8 +123,8 @@
     public void displayRefresh_disconnected_shouldDisable() {
         mDetailsDataRoleController.displayPreference(mScreen);
 
-        mDetailsDataRoleController.refresh(false, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsDataRoleController.refresh(false, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
 
         assertThat(mPreference.isEnabled()).isFalse();
     }
@@ -127,12 +132,12 @@
     @Test
     public void onClickDevice_hostEnabled_shouldSetDevice() {
         mDetailsDataRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+        when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
 
-        final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+        final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
         devicePref.performClick();
 
-        verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+        verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
         assertThat(devicePref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
     }
@@ -140,50 +145,50 @@
     @Test
     public void onClickDeviceTwice_hostEnabled_shouldSetDeviceOnce() {
         mDetailsDataRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+        when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
 
-        final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+        final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
         devicePref.performClick();
 
         assertThat(devicePref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
         devicePref.performClick();
-        verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+        verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
     }
 
     @Test
     public void onClickDeviceAndRefresh_success_shouldClearSubtext() {
         mDetailsDataRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+        when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
 
-        final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+        final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
         devicePref.performClick();
 
-        verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+        verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
         assertThat(devicePref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
         mDetailsDataRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
         mDetailsDataRoleController.refresh(true /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+                POWER_ROLE_SINK, DATA_ROLE_DEVICE);
         assertThat(devicePref.getSummary()).isEqualTo("");
     }
 
     @Test
     public void onClickDeviceAndRefresh_failed_shouldShowFailureText() {
         mDetailsDataRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+        when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
 
-        final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+        final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
         devicePref.performClick();
 
-        verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+        verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
         assertThat(devicePref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
         mDetailsDataRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
         mDetailsDataRoleController.refresh(true /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST);
+                POWER_ROLE_SINK, DATA_ROLE_HOST);
         assertThat(devicePref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching_failed));
     }
@@ -191,18 +196,18 @@
     @Test
     public void onClickDevice_timedOut_shouldShowFailureText() {
         mDetailsDataRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+        when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
 
-        final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+        final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
         devicePref.performClick();
 
-        verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+        verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
         ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
         verify(mHandler).postDelayed(captor.capture(), anyLong());
         assertThat(devicePref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
         mDetailsDataRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
         captor.getValue().run();
 
         assertThat(devicePref.getSummary())
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java
index fc93a58..11fa613 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
 import static android.net.ConnectivityManager.TETHERING_USB;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -105,8 +107,8 @@
         when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
 
         mDetailsFunctionsController.displayPreference(mScreen);
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         List<RadioButtonPreference> prefs = getRadioPreferences();
         Iterator<Long> iter = UsbDetailsFunctionsController.FUNCTIONS_MAP.keySet().iterator();
 
@@ -120,7 +122,7 @@
         when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
 
         mDetailsFunctionsController.refresh(false, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+                POWER_ROLE_SINK, DATA_ROLE_DEVICE);
         assertThat(mPreferenceCategory.isEnabled()).isFalse();
     }
 
@@ -131,8 +133,8 @@
         when(mUsbBackend.areFunctionsSupported(UsbManager.FUNCTION_PTP)).thenReturn(false);
         when(mUsbBackend.areFunctionsSupported(UsbManager.FUNCTION_RNDIS)).thenReturn(false);
 
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         List<RadioButtonPreference> prefs = getRadioPreferences();
         assertThat(prefs.size()).isEqualTo(1);
         assertThat(prefs.get(0).getKey())
@@ -143,8 +145,8 @@
     public void displayRefresh_mtpEnabled_shouldCheckSwitches() {
         when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
 
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         List<RadioButtonPreference> prefs = getRadioPreferences();
 
         assertThat(prefs.get(0).getKey())
@@ -156,8 +158,8 @@
     public void onClickMtp_noneEnabled_shouldEnableMtp() {
         when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
 
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_NONE);
         List<RadioButtonPreference> prefs = getRadioPreferences();
         prefs.get(0).performClick();
@@ -165,8 +167,8 @@
         assertThat(prefs.get(0).getKey())
                 .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MTP));
         verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_MTP);
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         assertThat(prefs.get(0).isChecked()).isTrue();
     }
 
@@ -174,8 +176,8 @@
     public void onClickMtp_ptpEnabled_shouldEnableMtp() {
         when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
 
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_PTP, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_PTP, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_PTP);
         List<RadioButtonPreference> prefs = getRadioPreferences();
         prefs.get(0).performClick();
@@ -183,8 +185,8 @@
         assertThat(prefs.get(0).getKey())
                 .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MTP));
         verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_MTP);
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         assertThat(prefs.get(0).isChecked()).isTrue();
         assertThat(prefs.get(3).getKey())
                 .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_PTP));
@@ -195,8 +197,8 @@
     public void onClickNone_mtpEnabled_shouldDisableMtp() {
         when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
 
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_MTP);
         List<RadioButtonPreference> prefs = getRadioPreferences();
         prefs.get(4).performClick();
@@ -204,8 +206,8 @@
         assertThat(prefs.get(4).getKey())
                 .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_NONE));
         verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_NONE);
-        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         assertThat(prefs.get(0).isChecked()).isFalse();
     }
 
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java
index d72214f..280b8d4 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -101,8 +104,8 @@
     @Test
     public void displayRefresh_charging_shouldSetHeader() {
         mDetailsHeaderController.displayPreference(mScreen);
-        mDetailsHeaderController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsHeaderController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
         verify(mHeaderController).setLabel(mContext.getString(R.string.usb_pref));
         verify(mHeaderController).setIcon(argThat((ArgumentMatcher<Drawable>) t -> {
             DrawableTestHelper.assertDrawableResId(t, R.drawable.ic_usb);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
index 38c92c3..aa62741 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
@@ -16,6 +16,13 @@
 
 package com.android.settings.connecteddevice.usb;
 
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -25,10 +32,10 @@
 
 import android.content.Context;
 import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
 import android.os.Handler;
 
 import androidx.fragment.app.FragmentActivity;
+import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
@@ -94,8 +101,8 @@
         mDetailsPowerRoleController.displayPreference(mScreen);
         when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
 
-        mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
 
         SwitchPreference pref = getPreference();
         assertThat(pref.isChecked()).isFalse();
@@ -107,7 +114,7 @@
         when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
 
         mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+                POWER_ROLE_SOURCE, DATA_ROLE_HOST);
 
         SwitchPreference pref = getPreference();
         assertThat(pref.isChecked()).isTrue();
@@ -119,11 +126,11 @@
         when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
 
         mDetailsPowerRoleController.refresh(false, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+                POWER_ROLE_SINK, DATA_ROLE_DEVICE);
 
         assertThat(mPreference.isEnabled()).isFalse();
-        assertThat(mScreen.findPreference(mDetailsPowerRoleController.getPreferenceKey()))
-                .isEqualTo(mPreference);
+        assertThat((Preference) mScreen.findPreference(
+                mDetailsPowerRoleController.getPreferenceKey())).isEqualTo(mPreference);
     }
 
     @Test
@@ -131,21 +138,22 @@
         mDetailsPowerRoleController.displayPreference(mScreen);
         when(mUsbBackend.areAllRolesSupported()).thenReturn(false);
 
-        mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
-                UsbPort.DATA_ROLE_DEVICE);
+        mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+                DATA_ROLE_DEVICE);
 
-        assertThat(mScreen.findPreference(mDetailsPowerRoleController.getPreferenceKey())).isNull();
+        assertThat((Preference) mScreen.findPreference(
+                mDetailsPowerRoleController.getPreferenceKey())).isNull();
     }
 
     @Test
     public void onClick_sink_shouldSetSource() {
         mDetailsPowerRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+        when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
 
         SwitchPreference pref = getPreference();
         pref.performClick();
 
-        verify(mUsbBackend).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+        verify(mUsbBackend).setPowerRole(POWER_ROLE_SOURCE);
         assertThat(pref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
     }
@@ -153,7 +161,7 @@
     @Test
     public void onClickTwice_sink_shouldSetSourceOnce() {
         mDetailsPowerRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+        when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
 
         SwitchPreference pref = getPreference();
         pref.performClick();
@@ -161,42 +169,42 @@
         assertThat(pref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
         pref.performClick();
-        verify(mUsbBackend, times(1)).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+        verify(mUsbBackend, times(1)).setPowerRole(POWER_ROLE_SOURCE);
     }
 
     @Test
     public void onClickDeviceAndRefresh_success_shouldClearSubtext() {
         mDetailsPowerRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+        when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
 
         SwitchPreference pref = getPreference();
         pref.performClick();
 
-        verify(mUsbBackend).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+        verify(mUsbBackend).setPowerRole(POWER_ROLE_SOURCE);
         assertThat(pref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
         mDetailsPowerRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
         mDetailsPowerRoleController.refresh(true /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE);
+                POWER_ROLE_SOURCE, DATA_ROLE_DEVICE);
         assertThat(pref.getSummary()).isEqualTo("");
     }
 
     @Test
     public void onClickDeviceAndRefresh_failed_shouldShowFailureText() {
         mDetailsPowerRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+        when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
 
         SwitchPreference pref = getPreference();
         pref.performClick();
 
-        verify(mUsbBackend).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+        verify(mUsbBackend).setPowerRole(POWER_ROLE_SOURCE);
         assertThat(pref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
         mDetailsPowerRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
         mDetailsPowerRoleController.refresh(true /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+                POWER_ROLE_SINK, DATA_ROLE_DEVICE);
         assertThat(pref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching_failed));
     }
@@ -204,18 +212,18 @@
     @Test
     public void onClickDevice_timedOut_shouldShowFailureText() {
         mDetailsPowerRoleController.displayPreference(mScreen);
-        when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+        when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
 
         SwitchPreference pref = getPreference();
         pref.performClick();
 
-        verify(mUsbBackend).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+        verify(mUsbBackend).setPowerRole(POWER_ROLE_SOURCE);
         ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
         verify(mHandler).postDelayed(captor.capture(), anyLong());
         assertThat(pref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching));
         mDetailsPowerRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
-                UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+                POWER_ROLE_NONE, DATA_ROLE_NONE);
         captor.getValue().run();
         assertThat(pref.getSummary())
                 .isEqualTo(mContext.getString(R.string.usb_switching_failed));
diff --git a/tests/robotests/src/com/android/settings/core/BasePreferenceControllerSignatureInspector.java b/tests/robotests/src/com/android/settings/core/BasePreferenceControllerSignatureInspector.java
index ce438b0..28e394f 100644
--- a/tests/robotests/src/com/android/settings/core/BasePreferenceControllerSignatureInspector.java
+++ b/tests/robotests/src/com/android/settings/core/BasePreferenceControllerSignatureInspector.java
@@ -71,7 +71,9 @@
                 .that(badClasses.toString())
                 .isEmpty();
 
-        assertWithMessage("Something in the grandfather list is no longer relevant. Please remove")
+        assertWithMessage("Something in the grandfather list is no longer relevant. Please remove"
+            + "it from packages/apps/Settings/tests/robotests/assets/"
+            + "grandfather_invalid_base_preference_controller_constructor")
                 .that(grandfather)
                 .isEmpty();
     }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
index fb674ab..5fb1747 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
@@ -105,7 +105,7 @@
     public void displayPref_shouldAlwaysDisplay() {
         mController.displayPreference(mScreen);
 
-        verify(mScreen.findPreference(mController.getPreferenceKey()))
+        verify((Preference) mScreen.findPreference(mController.getPreferenceKey()))
                 .setSummary(BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY));
         verify(mScreen, never()).removePreference(any(Preference.class));
     }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
index 8e9a48f..d090097 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.deviceinfo;
 
+import static android.content.Context.CLIPBOARD_SERVICE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -24,6 +26,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ClipboardManager;
 import android.content.Context;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -43,6 +46,9 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 public class PhoneNumberPreferenceControllerTest {
 
@@ -146,4 +152,20 @@
     public void isSliceable_shouldBeTrue() {
         assertThat(mController.isSliceable()).isTrue();
     }
+
+    @Test
+    public void copy_shouldCopyPhoneNumberToClipboard() {
+        final List<SubscriptionInfo> list = new ArrayList<>();
+        list.add(mSubscriptionInfo);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(list);
+        final String phoneNumber = "1111111111";
+        doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
+
+        mController.copy();
+
+        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
+                CLIPBOARD_SERVICE);
+        final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
+        assertThat(phoneNumber.contentEquals(data)).isTrue();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/display/TopLevelDisplayPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/TopLevelDisplayPreferenceControllerTest.java
index 9ad05ce..23d794c 100644
--- a/tests/robotests/src/com/android/settings/display/TopLevelDisplayPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/TopLevelDisplayPreferenceControllerTest.java
@@ -17,12 +17,14 @@
 package com.android.settings.display;
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
 
 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.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -40,11 +42,13 @@
 
 import java.util.ArrayList;
 import java.util.List;
+
+import org.robolectric.annotation.Config;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
 public class TopLevelDisplayPreferenceControllerTest {
-    @Mock
     private Context mContext;
     @Mock
     private PackageManager mPackageManager;
@@ -54,6 +58,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getString(R.string.config_wallpaper_picker_package)).thenReturn("pkg");
         when(mContext.getString(R.string.config_wallpaper_picker_class)).thenReturn("cls");
@@ -62,11 +67,17 @@
     }
 
     @Test
-    public void getAvailability_alwaysAvailable() {
+    public void getAvailibilityStatus_availableByDefault() {
         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
 
     @Test
+    @Config(qualifiers = "mcc999")
+    public void getAvailabilityStatus_unsupportedWhenSet() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
     public void getSummary_hasWallpaper_shouldReturnWallpaperSummary() {
         final List<ResolveInfo> resolveInfos = new ArrayList<>();
         resolveInfos.add(mock(ResolveInfo.class));
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index 7c455bb..a60460b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -38,7 +39,10 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AppOpsManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -75,6 +79,8 @@
 @RunWith(RobolectricTestRunner.class)
 public class BatteryUtilsTest {
 
+    private static final String TAG = "BatteryUtilsTest";
+
     // unit that used to converted ms to us
     private static final long UNIT = 1000;
     private static final long TIME_STATE_TOP = 1500 * UNIT;
@@ -160,6 +166,7 @@
     private FakeFeatureFactory mFeatureFactory;
     private PowerUsageFeatureProvider mProvider;
     private List<BatterySipper> mUsageList;
+    private Context mContext;
 
     @Before
     public void setUp() throws PackageManager.NameNotFoundException {
@@ -214,10 +221,10 @@
         mIdleBatterySipper.drainType = BatterySipper.DrainType.IDLE;
         mIdleBatterySipper.totalPowerMah = BATTERY_IDLE_USAGE;
 
-        final Context shadowContext = spy(RuntimeEnvironment.application);
-        doReturn(mPackageManager).when(shadowContext).getPackageManager();
-        doReturn(mAppOpsManager).when(shadowContext).getSystemService(Context.APP_OPS_SERVICE);
-        mBatteryUtils = spy(new BatteryUtils(shadowContext));
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
+        mBatteryUtils = spy(new BatteryUtils(mContext));
         mBatteryUtils.mPowerUsageFeatureProvider = mProvider;
         doReturn(0L).when(mBatteryUtils)
             .getForegroundServiceTotalTimeUs(any(BatteryStats.Uid.class), anyLong());
@@ -710,4 +717,15 @@
         verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
                 PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
     }
+
+    @Test
+    public void getBatteryInfo_providerNull_shouldNotCrash() {
+        when(mProvider.isEnhancedBatteryPredictionEnabled(mContext)).thenReturn(true);
+        when(mProvider.getEnhancedBatteryPrediction(mContext)).thenReturn(null);
+        when(mContext.registerReceiver(nullable(BroadcastReceiver.class),
+                any(IntentFilter.class))).thenReturn(new Intent());
+
+        //Should not crash
+        assertThat(mBatteryUtils.getBatteryInfo(mBatteryStatsHelper, TAG)).isNotNull();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java
index e6efef7..7568987 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.fuelgauge;
 
+import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
 import static com.android.settings.fuelgauge.TopLevelBatteryPreferenceController.getDashboardLabel;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -25,17 +27,30 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
 public class TopLevelBatteryPreferenceControllerTest {
-
     private Context mContext;
+    private TopLevelBatteryPreferenceController mController;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
+        mController = new TopLevelBatteryPreferenceController(mContext, "test_key");
+    }
+
+    @Test
+    public void getAvailibilityStatus_availableByDefault() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void getAvailabilityStatus_unsupportedWhenSet() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySaverPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySaverPreferenceControllerTest.java
deleted file mode 100644
index df1d909..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySaverPreferenceControllerTest.java
+++ /dev/null
@@ -1,89 +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.fuelgauge.batterysaver;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.preference.SwitchPreference;
-
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class AutoBatterySaverPreferenceControllerTest {
-
-    private AutoBatterySaverPreferenceController mController;
-    private Context mContext;
-    private SwitchPreference mPreference;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mContext = RuntimeEnvironment.application;
-        mPreference = new SwitchPreference(mContext);
-        mController = new AutoBatterySaverPreferenceController(mContext);
-    }
-
-    @Test
-    public void testUpdateState_lowPowerLevelZero_preferenceNotChecked() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isChecked()).isFalse();
-    }
-
-    @Test
-    public void testUpdateState_lowPowerLevelZero_preferenceChecked() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15);
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isChecked()).isTrue();
-    }
-
-    @Test
-    public void testOnPreferenceChange_turnOn_setValueNotZero() {
-        mController.onPreferenceChange(mPreference, true);
-
-        assertThat(Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isNotEqualTo(0);
-    }
-
-    @Test
-    public void testOnPreferenceChange_turnOff_setValueZero() {
-        mController.onPreferenceChange(mPreference, false);
-
-        assertThat(Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(0);
-    }
-
-    @Test
-    public void testIsChecked_useDefaultValue_returnFalse() {
-        assertThat(mController.isChecked()).isFalse();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java
deleted file mode 100644
index c13b913..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java
+++ /dev/null
@@ -1,117 +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.fuelgauge.batterysaver;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.lifecycle.LifecycleOwner;
-
-import com.android.settings.widget.SeekBarPreference;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class AutoBatterySeekBarPreferenceControllerTest {
-
-    private static final int TRIGGER_LEVEL = 20;
-    private static final int INTERVAL = 5;
-
-    private AutoBatterySeekBarPreferenceController mController;
-    private Context mContext;
-    private SeekBarPreference mPreference;
-    private Lifecycle mLifecycle;
-    private LifecycleOwner mLifecycleOwner;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-
-        mContext = RuntimeEnvironment.application;
-        mPreference = new SeekBarPreference(mContext);
-        mPreference.setMax(100);
-        mController = new AutoBatterySeekBarPreferenceController(mContext, mLifecycle);
-    }
-
-    @Test
-    public void testPreference_lowPowerLevelZero_preferenceInvisible() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isVisible()).isFalse();
-    }
-
-    @Test
-    public void testPreference_defaultValue_preferenceNotVisible() {
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isVisible()).isFalse();
-    }
-
-    @Test
-    public void testPreference_lowPowerLevelNotZero_updatePreference() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isVisible()).isTrue();
-        assertThat(mPreference.getTitle()).isEqualTo("20%");
-        assertThat(mPreference.getProgress()).isEqualTo(TRIGGER_LEVEL / INTERVAL);
-    }
-
-    @Test
-    public void testOnPreferenceChange_updateValue() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
-
-        mController.onPreferenceChange(mPreference, TRIGGER_LEVEL / INTERVAL);
-
-        assertThat(Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(TRIGGER_LEVEL);
-    }
-
-    @Test
-    public void testOnPreferenceChange_changeMax() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 50);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.getMax()).isEqualTo(50 / INTERVAL);
-    }
-
-    @Test
-    public void testOnPreferenceChange_noChangeMax() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.getMax()).isEqualTo(100);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
new file mode 100644
index 0000000..6d412ee
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
@@ -0,0 +1,57 @@
+package com.android.settings.fuelgauge.batterysaver;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BatterySaverScheduleRadioButtonsControllerTest {
+    private Context mContext;
+    private ContentResolver mResolver;
+    private BatterySaverScheduleRadioButtonsController mController;
+    private BatterySaverScheduleSeekBarController mSeekBarController;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mSeekBarController = new BatterySaverScheduleSeekBarController(mContext);
+        mController = new BatterySaverScheduleRadioButtonsController(
+                mContext, mSeekBarController);
+        mResolver = mContext.getContentResolver();
+    }
+
+    @Test
+    public void getDefaultKey_routine_returnsCorrectValue() {
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_DYNAMIC);
+        assertThat(mController.getDefaultKey())
+                .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_ROUTINE);
+    }
+
+    @Test
+    public void getDefaultKey_automatic_returnsCorrectValue() {
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
+        assertThat(mController.getDefaultKey())
+                .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_PERCENTAGE);
+    }
+
+    @Test
+    public void getDefaultKey_none_returnsCorrectValue() {
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        assertThat(mController.getDefaultKey())
+                .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
new file mode 100644
index 0000000..8aac9d8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
@@ -0,0 +1,65 @@
+package com.android.settings.fuelgauge.batterysaver;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BatterySaverScheduleSeekBarControllerTest {
+
+    private Context mContext;
+    private ContentResolver mResolver;
+    private BatterySaverScheduleSeekBarController mController;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mController = new BatterySaverScheduleSeekBarController(mContext);
+        mResolver = mContext.getContentResolver();
+    }
+
+    @Test
+    public void onPreferenceChange_updatesSettingsGlobal() {
+        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
+        mController.onPreferenceChange(mController.mSeekBarPreference, 10);
+        assertThat(Settings.Global.getInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1))
+                .isEqualTo(50);
+
+        assertThat(mController.mSeekBarPreference.getTitle()).isEqualTo("50%");
+    }
+
+    @Test
+    public void updateSeekBar_routineMode_hasCorrectProperties() {
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_DYNAMIC);
+        mController.updateSeekBar();
+        assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
+    }
+
+    @Test
+    public void updateSeekBar_percentageMode_hasCorrectProperties() {
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
+        mController.updateSeekBar();
+        assertThat(mController.mSeekBarPreference.isVisible()).isTrue();
+    }
+
+    @Test
+    public void updateSeekBar_noneMode_hasCorrectProperties() {
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        mController.updateSeekBar();
+        assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
+    }
+}
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 f1bb3ed..2db7f3f 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
@@ -49,13 +49,13 @@
     @Before
     public void setUp() {
         mContext = spy(RuntimeEnvironment.application);
-        mImpl = new ContextualCardFeatureProviderImpl();
+        mImpl = new ContextualCardFeatureProviderImpl(mContext);
     }
 
     @Test
     public void sendBroadcast_emptyAction_notSendBroadcast() {
         final Intent intent = new Intent();
-        mImpl.sendBroadcast(mContext, intent);
+        mImpl.sendBroadcast(intent);
 
         verify(mContext, never()).sendBroadcastAsUser(intent, UserHandle.ALL);
     }
@@ -64,7 +64,7 @@
     @Config(qualifiers = "mcc999")
     public void sendBroadcast_hasAction_sendBroadcast() {
         final Intent intent = new Intent();
-        mImpl.sendBroadcast(mContext, intent);
+        mImpl.sendBroadcast(intent);
 
         verify(mContext).sendBroadcastAsUser(intent, UserHandle.ALL);
     }
@@ -72,7 +72,7 @@
     @Test
     @Config(qualifiers = "mcc999")
     public void logContextualCardDisplay_hasAction_sendBroadcast() {
-        mImpl.logContextualCardDisplay(mContext, new ArrayList<>(), new ArrayList<>());
+        mImpl.logContextualCardDisplay(new ArrayList<>(), new ArrayList<>());
 
         verify(mContext).sendBroadcastAsUser(any(Intent.class), any());
     }
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 d86b9a3..c62a6bb 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -28,33 +28,27 @@
 import android.net.Uri;
 
 import com.android.settings.slices.CustomSliceRegistry;
-import com.android.settings.slices.SettingsSliceProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowContentResolver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
 
 @RunWith(RobolectricTestRunner.class)
 public class ContextualCardLoaderTest {
 
     private Context mContext;
     private ContextualCardLoader mContextualCardLoader;
-    private SettingsSliceProvider mProvider;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
         mContextualCardLoader = spy(new ContextualCardLoader(mContext));
-        mProvider = new SettingsSliceProvider();
-        ShadowContentResolver.registerProviderInternal(SettingsSliceProvider.SLICE_AUTHORITY,
-                mProvider);
     }
 
     @Test
@@ -151,7 +145,7 @@
         cards.add(new ContextualCard.Builder()
                 .setName("test_wifi")
                 .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI)
+                .setSliceUri(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI)
                 .build());
         cards.add(new ContextualCard.Builder()
                 .setName("test_flashlight")
@@ -210,4 +204,4 @@
                 .build());
         return cards;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
index 2af84f9..c405ffc 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
@@ -42,13 +42,16 @@
 import org.robolectric.RuntimeEnvironment;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @RunWith(RobolectricTestRunner.class)
 public class ContextualCardManagerTest {
 
     private static final String TEST_SLICE_URI = "context://test/test";
+    private static final String TEST_SLICE_NAME = "test_name";
 
     @Mock
     ContextualCardUpdateListener mListener;
@@ -61,7 +64,8 @@
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         final ContextualCardsFragment fragment = new ContextualCardsFragment();
-        mManager = new ContextualCardManager(mContext, fragment.getSettingsLifecycle());
+        mManager = new ContextualCardManager(mContext, fragment.getSettingsLifecycle(),
+                null /* bundle */);
     }
 
     @Test
@@ -135,9 +139,74 @@
         verify(manager, never()).onContextualCardUpdated(anyMap());
     }
 
+    @Test
+    public void onFinishCardLoading_newLaunch_twoLoadedCards_shouldShowTwoCards() {
+        mManager.mStartTime = System.currentTimeMillis();
+        mManager.setListener(mListener);
+        final List<ContextualCard> cards = new ArrayList<>();
+        cards.add(buildContextualCard(TEST_SLICE_URI));
+        cards.add(buildContextualCard(TEST_SLICE_URI));
+
+        mManager.onFinishCardLoading(cards);
+
+        assertThat(mManager.mContextualCards).hasSize(2);
+    }
+
+    @Test
+    public void onFinishCardLoading_hasSavedCard_shouldOnlyShowSavedCard() {
+        mManager.setListener(mListener);
+        final List<String> savedCardNames = new ArrayList<>();
+        savedCardNames.add(TEST_SLICE_NAME);
+        mManager.mIsFirstLaunch = false;
+        mManager.mSavedCards = savedCardNames;
+        final ContextualCard newCard =
+                new ContextualCard.Builder()
+                        .setName("test_name2")
+                        .setCardType(ContextualCard.CardType.SLICE)
+                        .setSliceUri(Uri.parse("content://test/test2"))
+                        .build();
+        final List<ContextualCard> loadedCards = new ArrayList<>();
+        loadedCards.add(buildContextualCard(TEST_SLICE_URI));
+        loadedCards.add(newCard);
+
+        mManager.onFinishCardLoading(loadedCards);
+
+        final List<String> actualCards = mManager.mContextualCards.stream()
+                .map(ContextualCard::getName)
+                .collect(Collectors.toList());
+        final List<String> expectedCards = Arrays.asList(TEST_SLICE_NAME);
+        assertThat(actualCards).containsExactlyElementsIn(expectedCards);
+    }
+
+    @Test
+    public void onFinishCardLoading_reloadData_shouldOnlyShowOldCard() {
+        mManager.setListener(mListener);
+        mManager.mIsFirstLaunch = false;
+        //old card
+        mManager.mContextualCards.add(buildContextualCard(TEST_SLICE_URI));
+        final ContextualCard newCard =
+                new ContextualCard.Builder()
+                        .setName("test_name2")
+                        .setCardType(ContextualCard.CardType.SLICE)
+                        .setSliceUri(Uri.parse("content://test/test2"))
+                        .build();
+        final List<ContextualCard> loadedCards = new ArrayList<>();
+        loadedCards.add(buildContextualCard(TEST_SLICE_URI));
+        loadedCards.add(newCard);
+
+        mManager.onFinishCardLoading(loadedCards);
+
+        final List<String> actualCards = mManager.mContextualCards.stream()
+                .map(ContextualCard::getName)
+                .collect(Collectors.toList());
+        final List<String> expectedCards = Arrays.asList(TEST_SLICE_NAME);
+        assertThat(actualCards).containsExactlyElementsIn(expectedCards);
+    }
+
     private ContextualCard buildContextualCard(String sliceUri) {
         return new ContextualCard.Builder()
-                .setName("test_name")
+                .setName(TEST_SLICE_NAME)
+                .setCardType(ContextualCard.CardType.SLICE)
                 .setSliceUri(Uri.parse(sliceUri))
                 .build();
     }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
index 8f36ea5..d4b67f5 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
@@ -70,11 +70,12 @@
     }
 
     @Test
-    public void getContextualCards_wifiSlice_shouldGetCorrectCategory() {
+    public void getContextualCards_wifiSlice_shouldGetImportantCategory() {
         final ContextualCardList cards = mProvider.getContextualCards();
         ContextualCard wifiCard = null;
         for (ContextualCard card : cards.getCardList()) {
-            if (card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI.toString())) {
+            if (card.getSliceUri().equals(
+                    CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString())) {
                 wifiCard = card;
             }
         }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionControllerTest.java
deleted file mode 100644
index e4ca6c0..0000000
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionControllerTest.java
+++ /dev/null
@@ -1,86 +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.conditional;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.content.IntentFilter;
-import android.os.PowerManager;
-
-import com.android.settings.fuelgauge.BatterySaverReceiver;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
-import org.robolectric.shadows.ShadowPowerManager;
-
-@RunWith(RobolectricTestRunner.class)
-public class BatterySaverConditionControllerTest {
-    @Mock
-    private ConditionManager mConditionManager;
-
-    private ShadowPowerManager mPowerManager;
-    private Context mContext;
-    private BatterySaverConditionController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application);
-        mPowerManager = Shadows.shadowOf(mContext.getSystemService(PowerManager.class));
-        mController = new BatterySaverConditionController(mContext, mConditionManager);
-    }
-
-    @Test
-    public void startMonitor_shouldRegisterReceiver() {
-        mController.startMonitoringStateChange();
-
-        verify(mContext).registerReceiver(any(BatterySaverReceiver.class), any(IntentFilter.class));
-    }
-
-    @Test
-    public void stopMonitor_shouldUnregisterReceiver() {
-        mController.startMonitoringStateChange();
-        mController.stopMonitoringStateChange();
-
-        verify(mContext).unregisterReceiver(any(BatterySaverReceiver.class));
-    }
-
-    @Test
-    public void isDisplayable_PowerSaverOn_true() {
-        mPowerManager.setIsPowerSaveMode(true);
-
-        assertThat(mController.isDisplayable()).isTrue();
-    }
-
-    @Test
-    public void isDisplayable_PowerSaverOff_false() {
-        mPowerManager.setIsPowerSaveMode(false);
-
-        assertThat(mController.isDisplayable()).isFalse();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
index 5bc3698..7e1a32c 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
@@ -91,8 +91,7 @@
         cr.close();
 
         assertThat(qryDismissed).isEqualTo(1);
-        verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(
-                mContext, card);
+        verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(card);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/location/AppLocationPermissionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/AppLocationPermissionPreferenceControllerTest.java
index eff5d43..6379e44 100644
--- a/tests/robotests/src/com/android/settings/location/AppLocationPermissionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/AppLocationPermissionPreferenceControllerTest.java
@@ -5,6 +5,10 @@
 import android.content.Context;
 import android.provider.Settings;
 
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -21,11 +25,16 @@
     @Mock
     private Context mContext;
 
+    private LifecycleOwner mLifecycleOwner;
+    private Lifecycle mLifecycle;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        mController = new AppLocationPermissionPreferenceController(mContext);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+        mController = new AppLocationPermissionPreferenceController(mContext, mLifecycle);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java b/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java
index e380830..806e2ec 100644
--- a/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java
@@ -84,30 +84,31 @@
     }
 
     @Test
-    public void onResume_shouldSetActiveAndRegisterListener() {
-        mEnabler.onResume();
+    public void onStart_shouldSetActiveAndRegisterListener() {
+        mEnabler.onStart();
 
         verify(mContext).registerReceiver(eq(mEnabler.mReceiver),
                 eq(LocationEnabler.INTENT_FILTER_LOCATION_MODE_CHANGED));
     }
 
     @Test
-    public void onResume_shouldRefreshLocationMode() {
-        mEnabler.onResume();
+    public void onStart_shouldRefreshLocationMode() {
+        mEnabler.onStart();
 
         verify(mEnabler).refreshLocationMode();
     }
 
     @Test
-    public void onPause_shouldUnregisterListener() {
-        mEnabler.onPause();
+    public void onStop_shouldUnregisterListener() {
+        mEnabler.onStart();
+        mEnabler.onStop();
 
         verify(mContext).unregisterReceiver(mEnabler.mReceiver);
     }
 
     @Test
     public void onReceive_shouldRefreshLocationMode() {
-        mEnabler.onResume();
+        mEnabler.onStart();
         reset(mListener);
         mEnabler.mReceiver.onReceive(mContext, new Intent());
 
diff --git a/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java
deleted file mode 100644
index d4b4ac3..0000000
--- a/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java
+++ /dev/null
@@ -1,217 +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.location;
-
-import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
-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.Intent;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.location.RecentLocationApps;
-import com.android.settingslib.location.RecentLocationApps.Request;
-import com.android.settingslib.widget.apppreference.AppPreference;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class RecentLocationRequestPreferenceControllerTest {
-
-    @Mock
-    private LocationSettings mFragment;
-    @Mock
-    private PreferenceCategory mCategory;
-    @Mock
-    private PreferenceScreen mScreen;
-    @Mock
-    private RecentLocationApps mRecentLocationApps;
-    @Mock
-    private Preference mSeeAllButton;
-
-    private Context mContext;
-    private RecentLocationRequestPreferenceController mController;
-    private LifecycleOwner mLifecycleOwner;
-    private Lifecycle mLifecycle;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mController = spy(new RecentLocationRequestPreferenceController(
-                mContext, mFragment, mLifecycle, mRecentLocationApps));
-        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mCategory);
-        when(mScreen.findPreference(mController.KEY_SEE_ALL_BUTTON)).thenReturn(mSeeAllButton);
-        final String key = mController.getPreferenceKey();
-        when(mCategory.getKey()).thenReturn(key);
-        when(mCategory.getContext()).thenReturn(mContext);
-    }
-
-    @Test
-    public void onLocationModeChanged_LocationOn_shouldEnablePreference() {
-        mController.displayPreference(mScreen);
-
-        mController.onLocationModeChanged(Settings.Secure.LOCATION_MODE_BATTERY_SAVING, false);
-
-        verify(mCategory).setEnabled(true);
-    }
-
-    @Test
-    public void onLocationModeChanged_LocationOff_shouldDisablePreference() {
-        mController.displayPreference(mScreen);
-
-        mController.onLocationModeChanged(Settings.Secure.LOCATION_MODE_OFF, false);
-
-        verify(mCategory).setEnabled(false);
-    }
-
-    @Test
-    public void updateState_noRecentRequest_shouldRemoveAllAndAddBanner() {
-        doReturn(new ArrayList<>()).when(mRecentLocationApps).getAppListSorted();
-        mController.displayPreference(mScreen);
-
-        mController.updateState(mCategory);
-
-        verify(mCategory).removeAll();
-        final String title = mContext.getString(R.string.location_no_recent_apps);
-        verify(mCategory).addPreference(argThat(titleMatches(title)));
-    }
-
-    @Test
-    public void updateState_hasRecentRequest_shouldRemoveAllAndAddInjectedSettings() {
-        List<Request> requests = createMockRequests(2);
-        doReturn(requests).when(mRecentLocationApps).getAppListSorted();
-
-        mController.displayPreference(mScreen);
-        mController.updateState(mCategory);
-
-        verify(mCategory).removeAll();
-        // Verifies two preferences are added in original order
-        InOrder inOrder = Mockito.inOrder(mCategory);
-        inOrder.verify(mCategory).addPreference(argThat(titleMatches("appTitle0")));
-        inOrder.verify(mCategory).addPreference(argThat(titleMatches("appTitle1")));
-    }
-
-    @Test
-    public void updateState_hasOverThreeRequests_shouldDisplaySeeAllButton() {
-        List<Request> requests = createMockRequests(6);
-        when(mRecentLocationApps.getAppListSorted()).thenReturn(requests);
-
-        mController.displayPreference(mScreen);
-        mController.updateState(mCategory);
-
-        verify(mCategory).removeAll();
-        // Verifies the first three preferences are added
-        InOrder inOrder = Mockito.inOrder(mCategory);
-        inOrder.verify(mCategory).addPreference(argThat(titleMatches("appTitle0")));
-        inOrder.verify(mCategory).addPreference(argThat(titleMatches("appTitle1")));
-        inOrder.verify(mCategory).addPreference(argThat(titleMatches("appTitle2")));
-        verify(mCategory, never()).addPreference(argThat(titleMatches("appTitle3")));
-        // Verifies the "See all" preference is visible
-        verify(mSeeAllButton).setVisible(true);
-    }
-
-    @Test
-    public void createAppPreference_shouldAddClickListener() {
-        final Request request = mock(Request.class);
-        final AppPreference preference = mock(AppPreference.class);
-        doReturn(preference).when(mController).createAppPreference(any(Context.class));
-
-        mController.createAppPreference(mContext, request);
-
-        verify(preference).setOnPreferenceClickListener(
-                any(RecentLocationRequestPreferenceController.PackageEntryClickedListener.class));
-    }
-
-    @Test
-    public void onPreferenceClick_shouldLaunchAppDetails() {
-        final Context context = mock(Context.class);
-        when(mFragment.getContext()).thenReturn(context);
-
-        final List<RecentLocationApps.Request> requests = new ArrayList<>();
-        final Request request = mock(Request.class);
-        requests.add(request);
-        doReturn(requests).when(mRecentLocationApps).getAppListSorted();
-        final AppPreference preference = new AppPreference(mContext);
-        doReturn(preference).when(mController).createAppPreference(any(Context.class));
-        mController.displayPreference(mScreen);
-        mController.updateState(mCategory);
-
-        final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
-
-        preference.performClick();
-
-        verify(context).startActivity(intent.capture());
-
-        assertThat(intent.getValue().getStringExtra(EXTRA_SHOW_FRAGMENT))
-                .isEqualTo(AppInfoDashboardFragment.class.getName());
-    }
-
-    private static ArgumentMatcher<Preference> titleMatches(String expected) {
-        return preference -> TextUtils.equals(expected, preference.getTitle());
-    }
-
-    private List<RecentLocationApps.Request> createMockRequests(int count) {
-        List<RecentLocationApps.Request> requests = new ArrayList<>();
-        for (int i = 0; i < count; i++) {
-            // Add mock requests
-            Request req = mock(Request.class, "request" + i);
-            requests.add(req);
-            // Map mock AppPreferences with mock requests
-            String title = "appTitle" + i;
-            AppPreference appPreference = mock(AppPreference.class, "AppPreference" + i);
-            doReturn(title).when(appPreference).getTitle();
-            doReturn(appPreference)
-                    .when(mController).createAppPreference(any(Context.class), eq(req));
-        }
-        return requests;
-    }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/location/RecentLocationRequestSeeAllPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/RecentLocationRequestSeeAllPreferenceControllerTest.java
deleted file mode 100644
index 7411afe..0000000
--- a/tests/robotests/src/com/android/settings/location/RecentLocationRequestSeeAllPreferenceControllerTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 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.location;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-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.provider.Settings.Secure;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.location.RecentLocationApps;
-import com.android.settingslib.location.RecentLocationApps.Request;
-import com.android.settingslib.widget.apppreference.AppPreference;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-/** Unit tests for {@link RecentLocationRequestSeeAllPreferenceController} */
-@RunWith(RobolectricTestRunner.class)
-public class RecentLocationRequestSeeAllPreferenceControllerTest {
-
-    @Mock
-    RecentLocationRequestSeeAllFragment mFragment;
-    @Mock
-    private PreferenceScreen mScreen;
-    @Mock
-    private PreferenceCategory mCategory;
-    @Mock
-    private RecentLocationApps mRecentLocationApps;
-
-    private Context mContext;
-    private LifecycleOwner mLifecycleOwner;
-    private Lifecycle mLifecycle;
-    private RecentLocationRequestSeeAllPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mController = spy(
-                new RecentLocationRequestSeeAllPreferenceController(
-                        mContext, mLifecycle, mFragment, mRecentLocationApps));
-        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mCategory);
-        final String key = mController.getPreferenceKey();
-        when(mCategory.getKey()).thenReturn(key);
-        when(mCategory.getContext()).thenReturn(mContext);
-    }
-
-    @Test
-    public void onLocationModeChanged_locationOn_shouldEnablePreference() {
-        mController.displayPreference(mScreen);
-
-        mController.onLocationModeChanged(Secure.LOCATION_MODE_HIGH_ACCURACY, false);
-
-        verify(mCategory).setEnabled(true);
-    }
-
-    @Test
-    public void onLocationModeChanged_locationOff_shouldDisablePreference() {
-        mController.displayPreference(mScreen);
-
-        mController.onLocationModeChanged(Secure.LOCATION_MODE_OFF, false);
-
-        verify(mCategory).setEnabled(false);
-    }
-
-    @Test
-    public void updateState_shouldRemoveAll() {
-        doReturn(Collections.EMPTY_LIST).when(mRecentLocationApps).getAppListSorted();
-
-        mController.displayPreference(mScreen);
-        mController.updateState(mCategory);
-
-        verify(mCategory).removeAll();
-    }
-
-    @Test
-    public void updateState_hasRecentLocationRequest_shouldAddPreference() {
-        Request request = mock(Request.class);
-        AppPreference appPreference = mock(AppPreference.class);
-        doReturn(appPreference)
-                .when(mController).createAppPreference(any(Context.class), eq(request));
-        when(mRecentLocationApps.getAppListSorted())
-                .thenReturn(new ArrayList<>(Collections.singletonList(request)));
-
-        mController.displayPreference(mScreen);
-        mController.updateState(mCategory);
-
-        verify(mCategory).removeAll();
-        verify(mCategory).addPreference(appPreference);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/network/MultiNetworkHeaderControllerTest.java b/tests/robotests/src/com/android/settings/network/MultiNetworkHeaderControllerTest.java
new file mode 100644
index 0000000..b4ebcc4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/MultiNetworkHeaderControllerTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doReturn;
+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.telephony.SubscriptionManager;
+
+import com.android.settings.wifi.WifiConnectionPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(RobolectricTestRunner.class)
+public class MultiNetworkHeaderControllerTest {
+    private static final String KEY_HEADER = "multi_network_header";
+
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+    @Mock
+    private PreferenceCategory mPreferenceCategory;
+    @Mock
+    private WifiConnectionPreferenceController mWifiController;
+    @Mock
+    private SubscriptionsPreferenceController mSubscriptionsController;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+
+    private Context mContext;
+    private LifecycleOwner mLifecycleOwner;
+    private Lifecycle mLifecycle;
+    private MultiNetworkHeaderController mHeaderController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+        when(mPreferenceScreen.findPreference(eq(KEY_HEADER))).thenReturn(mPreferenceCategory);
+
+        mHeaderController = spy(new MultiNetworkHeaderController(mContext, KEY_HEADER));
+        doReturn(mWifiController).when(mHeaderController).createWifiController(mLifecycle);
+        doReturn(mSubscriptionsController).when(mHeaderController).createSubscriptionsController(
+                mLifecycle);
+    }
+
+    @Test
+    public void isAvailable_beforeInitIsCalled_notAvailable() {
+        assertThat(mHeaderController.isAvailable()).isFalse();
+    }
+
+    // When calling displayPreference, the header itself should only be visible if the
+    // subscriptions controller says it is available. This is a helper for test cases of this logic.
+    private void displayPreferenceTest(boolean wifiAvailable, boolean subscriptionsAvailable,
+            boolean setVisibleExpectedValue) {
+        when(mWifiController.isAvailable()).thenReturn(wifiAvailable);
+        when(mSubscriptionsController.isAvailable()).thenReturn(subscriptionsAvailable);
+
+        mHeaderController.init(mLifecycle);
+        mHeaderController.displayPreference(mPreferenceScreen);
+        verify(mPreferenceCategory, never()).setVisible(eq(!setVisibleExpectedValue));
+        verify(mPreferenceCategory, atLeastOnce()).setVisible(eq(setVisibleExpectedValue));
+    }
+
+    @Test
+    public void displayPreference_bothNotAvailable_categoryIsNotVisible() {
+        displayPreferenceTest(false, false, false);
+    }
+
+    @Test
+    public void displayPreference_wifiAvailableButNotSubscriptions_categoryIsNotVisible() {
+        displayPreferenceTest(true, false, false);
+    }
+
+    @Test
+    public void displayPreference_subscriptionsAvailableButNotWifi_categoryIsVisible() {
+        displayPreferenceTest(false, true, true);
+    }
+
+    @Test
+    public void displayPreference_bothAvailable_categoryIsVisible() {
+        displayPreferenceTest(true, true, true);
+    }
+
+    @Test
+    public void onChildUpdated_subscriptionsBecameAvailable_categoryIsVisible() {
+        when(mSubscriptionsController.isAvailable()).thenReturn(false);
+        mHeaderController.init(mLifecycle);
+        mHeaderController.displayPreference(mPreferenceScreen);
+
+        when(mSubscriptionsController.isAvailable()).thenReturn(true);
+        mHeaderController.onChildrenUpdated();
+        ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
+
+        verify(mPreferenceCategory, atLeastOnce()).setVisible(captor.capture());
+        List<Boolean> values = captor.getAllValues();
+        assertThat(values.get(values.size()-1)).isEqualTo(Boolean.TRUE);
+    }
+
+    @Test
+    public void onChildUpdated_subscriptionsBecameUnavailable_categoryIsNotVisible() {
+        when(mSubscriptionsController.isAvailable()).thenReturn(true);
+        mHeaderController.init(mLifecycle);
+        mHeaderController.displayPreference(mPreferenceScreen);
+
+        when(mSubscriptionsController.isAvailable()).thenReturn(false);
+        mHeaderController.onChildrenUpdated();
+        ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
+
+        verify(mPreferenceCategory, atLeastOnce()).setVisible(captor.capture());
+        List<Boolean> values = captor.getAllValues();
+        assertThat(values.get(values.size()-1)).isEqualTo(Boolean.FALSE);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
new file mode 100644
index 0000000..016a885
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
@@ -0,0 +1,218 @@
+/*
+ * 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.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(RobolectricTestRunner.class)
+public class SubscriptionsPreferenceControllerTest {
+    private static final String KEY = "preference_group";
+
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private PreferenceCategory mPreferenceCategory;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+
+    private Context mContext;
+    private LifecycleOwner mLifecycleOwner;
+    private Lifecycle mLifecycle;
+    private SubscriptionsPreferenceController mController;
+    private int mOnChildUpdatedCount;
+    private SubscriptionsPreferenceController.UpdateListener mUpdateListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+        when(mScreen.findPreference(eq(KEY))).thenReturn(mPreferenceCategory);
+        when(mPreferenceCategory.getContext()).thenReturn(mContext);
+        mOnChildUpdatedCount = 0;
+        mUpdateListener = () -> mOnChildUpdatedCount++;
+
+        mController = new SubscriptionsPreferenceController(mContext, mLifecycle, mUpdateListener,
+                KEY, 5);
+    }
+
+    @Test
+    public void isAvailable_oneSubscription_availableFalse() {
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(
+                Arrays.asList(mock(SubscriptionInfo.class)));
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_twoSubscriptions_availableTrue() {
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(
+                Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_fiveSubscriptions_availableTrue() {
+        final ArrayList<SubscriptionInfo> subs = new ArrayList<>();
+        for (int i = 0; i < 5; i++) {
+            subs.add(mock(SubscriptionInfo.class));
+        }
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(subs);
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_airplaneModeOn_availableFalse() {
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(
+                Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
+        assertThat(mController.isAvailable()).isTrue();
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void onAirplaneModeChanged_airplaneModeTurnedOn_eventFired() {
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(
+                Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
+        mController.onResume();
+        mController.displayPreference(mScreen);
+        assertThat(mController.isAvailable()).isTrue();
+
+        final int updateCountBeforeModeChange = mOnChildUpdatedCount;
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
+        mController.onAirplaneModeChanged(true);
+        assertThat(mController.isAvailable()).isFalse();
+        assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeModeChange + 1);
+    }
+
+    @Test
+    public void onAirplaneModeChanged_airplaneModeTurnedOff_eventFired() {
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(
+                Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
+        mController.onResume();
+        mController.displayPreference(mScreen);
+        assertThat(mController.isAvailable()).isFalse();
+
+        final int updateCountBeforeModeChange = mOnChildUpdatedCount;
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
+        mController.onAirplaneModeChanged(false);
+        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeModeChange + 1);
+    }
+
+    @Test
+    public void onSubscriptionsChanged_countBecameTwo_eventFired() {
+        final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
+        mController.onResume();
+        mController.displayPreference(mScreen);
+        assertThat(mController.isAvailable()).isFalse();
+
+        final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+        mController.onSubscriptionsChanged();
+        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
+    }
+
+    @Test
+    public void onSubscriptionsChanged_countBecameOne_eventFired() {
+        final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+        mController.onResume();
+        mController.displayPreference(mScreen);
+        assertThat(mController.isAvailable()).isTrue();
+
+        final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
+        mController.onSubscriptionsChanged();
+        assertThat(mController.isAvailable()).isFalse();
+        assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
+    }
+
+
+    @Test
+    public void onSubscriptionsChanged_subscriptionReplaced_preferencesChanged() {
+        final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo sub3 = mock(SubscriptionInfo.class);
+        when(sub1.getDisplayName()).thenReturn("sub1");
+        when(sub2.getDisplayName()).thenReturn("sub2");
+        when(sub3.getDisplayName()).thenReturn("sub3");
+        when(sub1.getSubscriptionId()).thenReturn(1);
+        when(sub2.getSubscriptionId()).thenReturn(2);
+        when(sub3.getSubscriptionId()).thenReturn(3);
+
+        // Start out with only sub1 and sub2.
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+        mController.onResume();
+        mController.displayPreference(mScreen);
+        final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
+        verify(mPreferenceCategory, times(2)).addPreference(captor.capture());
+        assertThat(captor.getAllValues().size()).isEqualTo(2);
+        assertThat(captor.getAllValues().get(0).getTitle()).isEqualTo("sub1");
+        assertThat(captor.getAllValues().get(1).getTitle()).isEqualTo("sub2");
+
+        // Now replace sub2 with sub3, and make sure the old preference was removed and the new
+        // preference was added.
+        final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub3));
+        mController.onSubscriptionsChanged();
+        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
+
+        verify(mPreferenceCategory).removePreference(captor.capture());
+        assertThat(captor.getValue().getTitle()).isEqualTo("sub2");
+        verify(mPreferenceCategory, times(3)).addPreference(captor.capture());
+        assertThat(captor.getValue().getTitle()).isEqualTo("sub3");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/WifiConnectionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/WifiConnectionPreferenceControllerTest.java
new file mode 100644
index 0000000..7037318
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/WifiConnectionPreferenceControllerTest.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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+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.content.Context;
+
+import com.android.settings.wifi.WifiConnectionPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.AccessPointPreference;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
+
+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.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(RobolectricTestRunner.class)
+public class WifiConnectionPreferenceControllerTest {
+    private static final String KEY = "wifi_connection";
+
+    @Mock
+    WifiTracker mWifiTracker;
+    @Mock
+    PreferenceScreen mScreen;
+    @Mock
+    PreferenceCategory mPreferenceCategory;
+
+    private Context mContext;
+    private LifecycleOwner mLifecycleOwner;
+    private Lifecycle mLifecycle;
+    private WifiConnectionPreferenceController mController;
+    private int mOnChildUpdatedCount;
+    private WifiConnectionPreferenceController.UpdateListener mUpdateListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        WifiTrackerFactory.setTestingWifiTracker(mWifiTracker);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+        when(mScreen.findPreference(eq(KEY))).thenReturn(mPreferenceCategory);
+        when(mScreen.getContext()).thenReturn(mContext);
+        mUpdateListener = () -> mOnChildUpdatedCount++;
+
+        mController = new WifiConnectionPreferenceController(mContext, mLifecycle, mUpdateListener,
+                KEY, 0, 0);
+    }
+
+    @Test
+    public void isAvailable_noWiFiConnection_availableIsFalse() {
+        when(mWifiTracker.isConnected()).thenReturn(false);
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void displayPreference_noWiFiConnection_noPreferenceAdded() {
+        when(mWifiTracker.isConnected()).thenReturn(false);
+        when(mWifiTracker.getAccessPoints()).thenReturn(new ArrayList<>());
+        mController.displayPreference(mScreen);
+        verify(mPreferenceCategory, never()).addPreference(any());
+    }
+
+    @Test
+    public void displayPreference_hasWiFiConnection_preferenceAdded() {
+        when(mWifiTracker.isConnected()).thenReturn(true);
+        final AccessPoint accessPoint = mock(AccessPoint.class);
+        when(accessPoint.isActive()).thenReturn(true);
+        when(mWifiTracker.getAccessPoints()).thenReturn(Arrays.asList(accessPoint));
+        mController.displayPreference(mScreen);
+        verify(mPreferenceCategory).addPreference(any(AccessPointPreference.class));
+    }
+
+    @Test
+    public void onConnectedChanged_wifiBecameDisconnected_preferenceRemoved() {
+        when(mWifiTracker.isConnected()).thenReturn(true);
+        final AccessPoint accessPoint = mock(AccessPoint.class);
+
+        when(accessPoint.isActive()).thenReturn(true);
+        when(mWifiTracker.getAccessPoints()).thenReturn(Arrays.asList(accessPoint));
+        mController.displayPreference(mScreen);
+        final ArgumentCaptor<AccessPointPreference> captor = ArgumentCaptor.forClass(
+                AccessPointPreference.class);
+        verify(mPreferenceCategory).addPreference(captor.capture());
+        final AccessPointPreference pref = captor.getValue();
+
+        when(mWifiTracker.isConnected()).thenReturn(false);
+        when(mWifiTracker.getAccessPoints()).thenReturn(new ArrayList<>());
+        final int onUpdatedCountBefore = mOnChildUpdatedCount;
+        mController.onConnectedChanged();
+        verify(mPreferenceCategory).removePreference(pref);
+        assertThat(mOnChildUpdatedCount).isEqualTo(onUpdatedCountBefore + 1);
+    }
+
+
+    @Test
+    public void onAccessPointsChanged_wifiBecameConnectedToDifferentAP_preferenceReplaced() {
+        when(mWifiTracker.isConnected()).thenReturn(true);
+        final AccessPoint accessPoint1 = mock(AccessPoint.class);
+
+        when(accessPoint1.isActive()).thenReturn(true);
+        when(mWifiTracker.getAccessPoints()).thenReturn(Arrays.asList(accessPoint1));
+        mController.displayPreference(mScreen);
+        final ArgumentCaptor<AccessPointPreference> captor = ArgumentCaptor.forClass(
+                AccessPointPreference.class);
+
+
+        final AccessPoint accessPoint2 = mock(AccessPoint.class);
+        when(accessPoint1.isActive()).thenReturn(false);
+        when(accessPoint2.isActive()).thenReturn(true);
+        when(mWifiTracker.getAccessPoints()).thenReturn(Arrays.asList(accessPoint1, accessPoint2));
+        final int onUpdatedCountBefore = mOnChildUpdatedCount;
+        mController.onAccessPointsChanged();
+
+        verify(mPreferenceCategory, times(2)).addPreference(captor.capture());
+        final AccessPointPreference pref1 = captor.getAllValues().get(0);
+        final AccessPointPreference pref2 = captor.getAllValues().get(1);
+        assertThat(pref1.getAccessPoint()).isEqualTo(accessPoint1);
+        assertThat(pref2.getAccessPoint()).isEqualTo(accessPoint2);
+        verify(mPreferenceCategory).removePreference(eq(pref1));
+        assertThat(mOnChildUpdatedCount).isEqualTo(onUpdatedCountBefore + 1);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
index d6a594a..fb4747c 100644
--- a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
@@ -218,7 +218,8 @@
         mController.displayPreference(mScreen);
         mController.onResume();
 
-        verify(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE)).setVisible(false);
+        verify((Preference) mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
+                .setVisible(false);
     }
 
     @Test
@@ -242,11 +243,11 @@
         verify(mWorkCategory, times(2)).setVisible(true);
 
         // Sound preferences should explain that the profile isn't available yet.
-        verify(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
+        verify((Preference) mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
                 .setSummary(eq(notAvailable));
-        verify(mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
+        verify((Preference) mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
                 .setSummary(eq(notAvailable));
-        verify(mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE))
+        verify((Preference) mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE))
                 .setSummary(eq(notAvailable));
     }
 
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
index 5e3d6e9..41227c5 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
@@ -83,12 +83,12 @@
         String ruleId2 = "test2_id";
         String ruleId3 = "test3_id";
 
-        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);
+        AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null, null,
+            null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+        AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null, null,
+            null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
+        AutomaticZenRule autoRule3 = new AutomaticZenRule("test_rule_3", null, null,
+            null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 30);
 
         rMap.put(ruleId1, autoRule1);
         rMap.put(ruleId2, autoRule2);
@@ -109,10 +109,10 @@
         String ruleId1 = "test1_id";
         String ruleId2 = "test2_id";
 
-        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 autoRule1 = new AutomaticZenRule("test_rule_1", null, null,
+            null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+        AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null, null,
+            null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
 
         rMap.put(ruleId1, autoRule1);
         rMap.put(ruleId2, autoRule2);
@@ -130,8 +130,8 @@
         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);
+        AutomaticZenRule rule = new AutomaticZenRule("rule_name", null, null,
+            null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
         rMap.put(testId, rule);
 
         when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES);
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
index 3feff0d..6169f92 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
@@ -69,13 +69,14 @@
 
         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));
+                    null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true,
+                    i * 2));
         }
 
         if (addDefaultRules) {
-            ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
+            ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null, null, null,
                     null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
-            ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
+            ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null, null, null,
                     null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
         }
 
@@ -90,13 +91,14 @@
 
         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));
+                    null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true,
+                    numRules - i));
         }
 
         if (addDefaultRules) {
-            ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
+            ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null, null, null,
                     null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
-            ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
+            ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null, null, null,
                     null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
         }
 
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
index c11d7eb..649a1ba 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
@@ -164,23 +164,6 @@
         assertThat(findFragment(mActivity).mChosenPattern).isNull();
     }
 
-    @Test
-    public void skipButton_shouldNotBeVisible_duringFingerprintFlow() {
-        final Intent intent =
-                SetupChooseLockPattern.modifyIntentForSetup(
-                        application,
-                        new IntentBuilder(application)
-                                .setUserId(UserHandle.myUserId())
-                                .setForFingerprint(true)
-                                .build());
-
-        mActivity = ActivityController.of(new SetupChooseLockPattern(), intent).setup().get();
-        Button skipButton = mActivity.findViewById(R.id.skip_button);
-
-        assertThat(skipButton).isNotNull();
-        assertThat(skipButton.getVisibility()).isEqualTo(View.GONE);
-    }
-
     private ChooseLockPatternFragment findFragment(FragmentActivity activity) {
         return (ChooseLockPatternFragment)
                 activity.getSupportFragmentManager().findFragmentById(R.id.main_content);
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index b129267..7eae3e4 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -55,7 +55,7 @@
 import com.android.settings.testutils.shadow.ShadowThreadUtils;
 import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settings.testutils.shadow.ShadowUtils;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.wifi.slice.WifiSlice;
 import com.android.settingslib.wifi.WifiTracker;
 
 import org.junit.After;
diff --git a/tests/robotests/src/com/android/settings/slices/SlicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/slices/SlicePreferenceControllerTest.java
new file mode 100644
index 0000000..364fb60
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/slices/SlicePreferenceControllerTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.net.Uri;
+
+import androidx.lifecycle.LiveData;
+import androidx.slice.Slice;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class SlicePreferenceControllerTest {
+    private static final String KEY = "slice_preference_key";
+
+    @Mock
+    private LiveData<Slice> mLiveData;
+    private Context mContext;
+    private SlicePreferenceController mController;
+    private Uri mUri;
+
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        mController = new SlicePreferenceController(mContext, KEY);
+        mController.mLiveData = mLiveData;
+        mUri = Uri.EMPTY;
+    }
+
+    @Test
+    public void isAvailable_uriNull_returnFalse() {
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_uriNotNull_returnTrue() {
+        mController.setSliceUri(mUri);
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void onStart_registerObserver() {
+        mController.onStart();
+        verify(mLiveData).observeForever(mController);
+    }
+
+    @Test
+    public void onStop_unregisterObserver() {
+        mController.onStop();
+        verify(mLiveData).removeObserver(mController);
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java b/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
index ac19dd0..31e955c 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
@@ -19,9 +19,9 @@
 import android.content.Context;
 
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.slices.CopyableSlice;
+import com.android.settings.slices.Copyable;
 
-public class FakeCopyableController extends BasePreferenceController implements CopyableSlice {
+public class FakeCopyableController extends BasePreferenceController implements Copyable {
 
     public FakeCopyableController(Context context, String preferenceKey) {
         super(context, preferenceKey);
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index ef07fd4..bf86898 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -23,6 +23,8 @@
 
 import com.android.settings.accounts.AccountFeatureProvider;
 import com.android.settings.applications.ApplicationFeatureProvider;
+import com.android.settings.biometrics.face.FaceFeatureProvider;
+import com.android.settings.bluetooth.BluetoothFeatureProvider;
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
@@ -64,6 +66,8 @@
     public final AssistGestureFeatureProvider assistGestureFeatureProvider;
     public final AccountFeatureProvider mAccountFeatureProvider;
     public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
+    public final FaceFeatureProvider mFaceFeatureProvider;
+    public final BluetoothFeatureProvider mBluetoothFeatureProvider;
 
     public PanelFeatureProvider panelFeatureProvider;
     public SlicesFeatureProvider slicesFeatureProvider;
@@ -108,6 +112,8 @@
         mAccountFeatureProvider = mock(AccountFeatureProvider.class);
         mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
         panelFeatureProvider = mock(PanelFeatureProvider.class);
+        mFaceFeatureProvider = mock(FaceFeatureProvider.class);
+        mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class);
     }
 
     @Override
@@ -195,7 +201,17 @@
         return panelFeatureProvider;
     }
 
-    public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
+    public ContextualCardFeatureProvider getContextualCardFeatureProvider(Context context) {
         return mContextualCardFeatureProvider;
     }
+
+    @Override
+    public FaceFeatureProvider getFaceFeatureProvider() {
+        return mFaceFeatureProvider;
+    }
+
+    @Override
+    public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
+        return mBluetoothFeatureProvider;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
deleted file mode 100644
index 0828cc7..0000000
--- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
+++ /dev/null
@@ -1,27 +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.testutils;
-
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-
-public class SettingsRobolectricTestRunner extends RobolectricTestRunner {
-
-    public SettingsRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
index 3dc109f..7f0598d 100644
--- a/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
@@ -22,18 +22,18 @@
 import android.view.View;
 import android.widget.ImageButton;
 
-import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
 import androidx.preference.PreferenceViewHolder;
 
+import com.android.settings.R;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
-@RunWith(SettingsRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 public class ButtonPreferenceTest {
 
     private Context mContext;
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
index 48f8ec0..107da79 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
@@ -18,9 +18,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.mock;
+
 import androidx.appcompat.app.AlertDialog;
 
 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,6 +38,10 @@
 
     @Test
     public void LaunchActivity_shouldShowNetworkRequestDialog() {
+        // Mocks fake WifiTracker, in case of exception in NetworkRequestDialogFragment.onResume().
+        WifiTracker wifiTracker = mock(WifiTracker.class);
+        WifiTrackerFactory.setTestingWifiTracker(wifiTracker);
+
         Robolectric.setupActivity(NetworkRequestDialogActivity.class);
 
         AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
index c9cdc15..e64fae7 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
@@ -51,6 +51,10 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
+
 import org.robolectric.shadows.ShadowLooper;
 
 @RunWith(RobolectricTestRunner.class)
@@ -58,16 +62,21 @@
 public class NetworkRequestDialogFragmentTest {
 
     private static final String KEY_SSID = "key_ssid";
+    private static final String KEY_SECURITY = "key_security";
 
     private FragmentActivity mActivity;
     private NetworkRequestDialogFragment networkRequestDialogFragment;
     private Context mContext;
+    private WifiTracker mWifiTracker;
 
     @Before
     public void setUp() {
         mActivity = Robolectric.setupActivity(FragmentActivity.class);
         networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
         mContext = spy(RuntimeEnvironment.application);
+
+        mWifiTracker = mock(WifiTracker.class);
+        WifiTrackerFactory.setTestingWifiTracker(mWifiTracker);
     }
 
     @Test
@@ -140,68 +149,47 @@
     }
 
     @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));
-
+    public void updateAccessPointList_onUserSelectionConnectSuccess_shouldCloseTheDialog() {
+        List<AccessPoint> accessPointList = createAccessPointList();
         when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
         networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog.isShowing()).isTrue();
 
         // Test if config would update list.
         WifiConfiguration config = new WifiConfiguration();
         config.SSID = "Test AP 3";
         networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
 
-        AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
-        verify(accessPointList, times(1)).set(2, verifyAccessPoint);
+        assertThat(alertDialog.isShowing()).isFalse();
     }
 
     @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));
+    public void updateAccessPointList_onUserSelectionConnectFailure_shouldCallTimeoutDialog() {
+        FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
+        FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
+        List<AccessPoint> accessPointList = createAccessPointList();
+        when(spyFakeFragment.getAccessPointList()).thenReturn(accessPointList);
+        spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
 
-        when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
-        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog.isShowing()).isTrue();
 
         // Test if config would update list.
         WifiConfiguration config = new WifiConfiguration();
         config.SSID = "Test AP 3";
-        networkRequestDialogFragment.onUserSelectionConnectFailure(config);
+        fakeFragment.onUserSelectionConnectFailure(config);
 
-        AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
-        verify(accessPointList, times(1)).set(2, verifyAccessPoint);
+        assertThat(fakeFragment.bCalledStopAndPop).isTrue();
     }
 
     @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));
+    public void onUserSelectionCallbackRegistration_onClick_shouldCallSelect() {
+        // Assert.
+        final int indexClickItem = 3;
+        List<AccessPoint> accessPointList = createAccessPointList();
+        AccessPoint clickedAccessPoint = accessPointList.get(indexClickItem);
+        clickedAccessPoint.generateOpenNetworkConfig();
         when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
 
         NetworkRequestUserSelectionCallback selectionCallback = mock(
@@ -209,40 +197,66 @@
         AlertDialog dialog = mock(AlertDialog.class);
         networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
 
-        networkRequestDialogFragment.onClick(dialog, 2);
+        // Act.
+        networkRequestDialogFragment.onClick(dialog, indexClickItem);
 
+        // Check.
         verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
     }
 
     @Test
     public void onMatch_shouldUpdatedList() {
-        // Prepares WifiManager.
+        // Assert.
         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);
+        networkRequestDialogFragment.onResume();
 
-        List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
-        WifiConfiguration config = new WifiConfiguration();
+        List<AccessPoint> accessPointList = createAccessPointList();
+        when(mWifiTracker.getAccessPoints()).thenReturn(accessPointList);
+
         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);
+        ScanResult scanResult = new ScanResult();
+        scanResult.SSID = SSID_AP1;
+        scanResult.capabilities = "WEP";
+        scanResults.add(scanResult);
+        scanResult = new ScanResult();
+        scanResult.SSID = SSID_AP2;
+        scanResult.capabilities = "WEP";
+        scanResults.add(scanResult);
 
+        // Act.
         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);
+        // Check.
+        List<AccessPoint> returnList = networkRequestDialogFragment.getAccessPointList();
+        assertThat(returnList).isNotEmpty();
+        assertThat(returnList.size()).isEqualTo(2);
+        assertThat(returnList.get(0).getSsid()).isEqualTo(SSID_AP1);
+        assertThat(returnList.get(1).getSsid()).isEqualTo(SSID_AP2);
+    }
+
+    private List<AccessPoint> createAccessPointList() {
+        List<AccessPoint> accessPointList = spy(new ArrayList<>());
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_SSID, "Test AP 1");
+        bundle.putInt(KEY_SECURITY, 1);
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 2");
+        bundle.putInt(KEY_SECURITY, 1);
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 3");
+        bundle.putInt(KEY_SECURITY, 2);
+        AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
+        accessPointList.add(clickedAccessPoint);
+        bundle.putString(KEY_SSID, "Test AP 4");
+        bundle.putInt(KEY_SECURITY, 0);
+        accessPointList.add(new AccessPoint(mContext, bundle));
+
+        return accessPointList;
     }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiUtilsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiUtilsTest.java
index a95624b..9de095d 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiUtilsTest.java
@@ -22,6 +22,16 @@
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+
+import com.android.settingslib.wifi.AccessPoint;
+
+import org.robolectric.RuntimeEnvironment;
+
 @RunWith(RobolectricTestRunner.class)
 public class WifiUtilsTest {
 
@@ -44,4 +54,23 @@
         assertThat(WifiUtils.isHotspotPasswordValid(longPassword)).isFalse();
         assertThat(WifiUtils.isHotspotPasswordValid("")).isFalse();
     }
-}
+
+    @Test
+    public void getWifiConfigByAccessPoint_shouldReturnCorrectConfig() {
+        String testSSID = "WifiUtilsTest";
+        Bundle bundle = new Bundle();
+        bundle.putString("key_ssid", testSSID);
+        Context context = spy(RuntimeEnvironment.application);
+        AccessPoint accessPoint = new AccessPoint(context, bundle);
+
+        WifiConfiguration config = WifiUtils.getWifiConfig(accessPoint, null, null);
+
+        assertThat(config).isNotNull();
+        assertThat(config.SSID).isEqualTo(AccessPoint.convertToQuotedString(testSSID));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void getWifiConfigWithNullInput_ThrowIllegalArgumentException() {
+        WifiConfiguration config = WifiUtils.getWifiConfig(null, null, null);
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java b/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
index e32ac6b..0ef0273 100644
--- a/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
@@ -22,9 +22,11 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
 import android.util.Size;
-import android.view.SurfaceHolder;
 
 import com.android.settings.R;
 
@@ -48,7 +50,7 @@
 public class QrCameraTest {
 
     @Mock
-    private SurfaceHolder mSurfaceHolder;
+    private SurfaceTexture mSurfaceTexture;
 
     private QrCamera mCamera;
     private Context mContext;
@@ -78,6 +80,11 @@
             mCameraCallbacked = true;
             mCallbackSignal.countDown();
         }
+
+        @Override
+        public void setTransform(Matrix transform) {
+            // Do nothing
+        }
     }
 
     private ScannerTestCallback mScannerCallback;
@@ -87,7 +94,7 @@
         mContext = RuntimeEnvironment.application;
         mScannerCallback = new ScannerTestCallback();
         mCamera = new QrCamera(mContext, mScannerCallback);
-        mSurfaceHolder = mock(SurfaceHolder.class);
+        mSurfaceTexture = mock(SurfaceTexture.class);
         mQrCode = "";
         mCameraCallbacked = false;
         mCallbackSignal = null;
@@ -96,7 +103,7 @@
     @Test
     public void testCamera_Init_Callback() throws InterruptedException {
         mCallbackSignal = new CountDownLatch(1);
-        mCamera.start(mSurfaceHolder);
+        mCamera.start(mSurfaceTexture);
         mCallbackSignal.await(5000, TimeUnit.MILLISECONDS);
         assertThat(mCameraCallbacked).isTrue();
     }
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
new file mode 100644
index 0000000..bf5fba8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.slice;
+
+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 android.content.ContentResolver;
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+
+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.core.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SliceTester;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class ContextualWifiSliceTest {
+
+    private Context mContext;
+    private ContentResolver mResolver;
+    private WifiManager mWifiManager;
+    private ContextualWifiSlice mWifiSlice;
+
+    @Before
+    public void setUp() {
+        mContext = spy(RuntimeEnvironment.application);
+        mResolver = mock(ContentResolver.class);
+        doReturn(mResolver).when(mContext).getContentResolver();
+        mWifiManager = mContext.getSystemService(WifiManager.class);
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+        mWifiManager.setWifiEnabled(true);
+
+        mWifiSlice = new ContextualWifiSlice(mContext);
+    }
+
+    @Test
+    public void getWifiSlice_hasActiveConnection_shouldReturnNull() {
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "123";
+        mWifiManager.connect(config, null /* listener */);
+
+        final Slice wifiSlice = mWifiSlice.getSlice();
+
+        assertThat(wifiSlice).isNull();
+    }
+
+    @Test
+    public void getWifiSlice_previousDisplayed_hasActiveConnection_shouldHaveTitleAndToggle() {
+        mWifiSlice.mPreviouslyDisplayed = true;
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "123";
+        mWifiManager.connect(config, null /* listener */);
+
+        final Slice wifiSlice = mWifiSlice.getSlice();
+        final SliceMetadata metadata = SliceMetadata.from(mContext, wifiSlice);
+
+        final List<SliceAction> toggles = metadata.getToggles();
+        assertThat(toggles).hasSize(1);
+
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+        final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_settings_wireless);
+        assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString());
+
+        final List<SliceItem> sliceItems = wifiSlice.getItems();
+        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.wifi_settings));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
similarity index 96%
rename from tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
rename to tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
index 2d4dd04..3c78749 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
@@ -12,16 +12,15 @@
  * 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;
+package com.android.settings.wifi.slice;
 
 import static android.app.slice.Slice.HINT_LIST_ITEM;
 import static android.app.slice.SliceItem.FORMAT_SLICE;
 
 import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
-import static com.android.settings.wifi.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
+import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -29,7 +28,6 @@
 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.ContentResolver;
 import android.content.Context;
diff --git a/tests/uitests/Android.mk b/tests/uitests/Android.mk
index 89f9133..fb7258c 100644
--- a/tests/uitests/Android.mk
+++ b/tests/uitests/Android.mk
@@ -27,7 +27,7 @@
     android.test.base
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
+    androidx.test.rules \
     app-helpers-core \
     launcher-helper-lib \
     metrics-helper-lib \
diff --git a/tests/uitests/AndroidManifest.xml b/tests/uitests/AndroidManifest.xml
index 49a2fd1..dc6fc15 100644
--- a/tests/uitests/AndroidManifest.xml
+++ b/tests/uitests/AndroidManifest.xml
@@ -31,7 +31,7 @@
     <uses-permission android:name="android.permission.READ_SEARCH_INDEXABLES"/>
 
     <instrumentation
-            android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:name="androidx.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.settings.ui"
             android:label="Android Settings Functional UI Tests" />
 </manifest>
diff --git a/tests/uitests/AndroidTest.xml b/tests/uitests/AndroidTest.xml
index 4162207..50c6a75 100644
--- a/tests/uitests/AndroidTest.xml
+++ b/tests/uitests/AndroidTest.xml
@@ -24,7 +24,7 @@
     <option name="test-tag" value="SettingsUITests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.settings.ui" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/uitests/src/com/android/settings/ui/AboutPhoneSettingsTests.java b/tests/uitests/src/com/android/settings/ui/AboutPhoneSettingsTests.java
index 738d710..a73a5a8 100644
--- a/tests/uitests/src/com/android/settings/ui/AboutPhoneSettingsTests.java
+++ b/tests/uitests/src/com/android/settings/ui/AboutPhoneSettingsTests.java
@@ -24,9 +24,6 @@
 import android.content.Intent;
 import android.os.RemoteException;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.Direction;
 import android.support.test.uiautomator.UiDevice;
@@ -34,6 +31,10 @@
 import android.support.test.uiautomator.Until;
 import android.text.TextUtils;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/uitests/src/com/android/settings/ui/AppsSettingsRetainFilterTests.java b/tests/uitests/src/com/android/settings/ui/AppsSettingsRetainFilterTests.java
index 84d528b..4698b9a 100644
--- a/tests/uitests/src/com/android/settings/ui/AppsSettingsRetainFilterTests.java
+++ b/tests/uitests/src/com/android/settings/ui/AppsSettingsRetainFilterTests.java
@@ -21,14 +21,15 @@
 import android.content.Intent;
 import android.os.RemoteException;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 import android.system.helpers.ActivityHelper;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/uitests/src/com/android/settings/ui/BatterySettingsUITest.java b/tests/uitests/src/com/android/settings/ui/BatterySettingsUITest.java
index 8b34fff..3cf1e96 100644
--- a/tests/uitests/src/com/android/settings/ui/BatterySettingsUITest.java
+++ b/tests/uitests/src/com/android/settings/ui/BatterySettingsUITest.java
@@ -18,12 +18,13 @@
 
 import android.content.Intent;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.system.helpers.SettingsHelper;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.ui.testutils.SettingsTestUtils;
 
 import org.junit.After;
diff --git a/tests/uitests/src/com/android/settings/ui/ConnectedDeviceTests.java b/tests/uitests/src/com/android/settings/ui/ConnectedDeviceTests.java
index ca19a3f..ef0dacc 100644
--- a/tests/uitests/src/com/android/settings/ui/ConnectedDeviceTests.java
+++ b/tests/uitests/src/com/android/settings/ui/ConnectedDeviceTests.java
@@ -24,14 +24,15 @@
 import android.nfc.NfcAdapter;
 import android.nfc.NfcManager;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java b/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java
index 4eccd8b..4c72b34 100644
--- a/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java
+++ b/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java
@@ -22,9 +22,6 @@
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.Direction;
 import android.support.test.uiautomator.UiDevice;
@@ -32,6 +29,10 @@
 import android.support.test.uiautomator.Until;
 import android.system.helpers.SettingsHelper;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.ui.testutils.SettingsTestUtils;
 
 import org.junit.After;
diff --git a/tests/uitests/src/com/android/settings/ui/SecuritySettingsLaunchTest.java b/tests/uitests/src/com/android/settings/ui/SecuritySettingsLaunchTest.java
index 6803c7e..5efb7e8 100644
--- a/tests/uitests/src/com/android/settings/ui/SecuritySettingsLaunchTest.java
+++ b/tests/uitests/src/com/android/settings/ui/SecuritySettingsLaunchTest.java
@@ -18,12 +18,13 @@
 
 import android.os.RemoteException;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.system.helpers.SettingsHelper;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.ui.testutils.SettingsTestUtils;
 
 import org.junit.After;
diff --git a/tests/uitests/src/com/android/settings/ui/StorageSettingsUITest.java b/tests/uitests/src/com/android/settings/ui/StorageSettingsUITest.java
index a301cc3..b21da71 100644
--- a/tests/uitests/src/com/android/settings/ui/StorageSettingsUITest.java
+++ b/tests/uitests/src/com/android/settings/ui/StorageSettingsUITest.java
@@ -18,12 +18,13 @@
 
 import android.os.RemoteException;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.system.helpers.SettingsHelper;
 import android.test.suitebuilder.annotation.MediumTest;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.ui.testutils.SettingsTestUtils;
 
 import org.junit.After;
diff --git a/tests/uitests/src/com/android/settings/ui/StorageWizardTest.java b/tests/uitests/src/com/android/settings/ui/StorageWizardTest.java
index 4b923f5..d47cd0d 100644
--- a/tests/uitests/src/com/android/settings/ui/StorageWizardTest.java
+++ b/tests/uitests/src/com/android/settings/ui/StorageWizardTest.java
@@ -20,8 +20,6 @@
 import android.os.SystemClock;
 import android.os.storage.DiskInfo;
 import android.os.storage.VolumeInfo;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.UiDevice;
@@ -29,6 +27,9 @@
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.Until;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/uitests/src/com/android/settings/ui/SyncSettingsTest.java b/tests/uitests/src/com/android/settings/ui/SyncSettingsTest.java
index 848147f..58a2fd3 100644
--- a/tests/uitests/src/com/android/settings/ui/SyncSettingsTest.java
+++ b/tests/uitests/src/com/android/settings/ui/SyncSettingsTest.java
@@ -20,15 +20,16 @@
 
 import android.os.RemoteException;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 import android.system.helpers.SettingsHelper;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/uitests/src/com/android/settings/ui/WirelessNetworkSettingsTests.java b/tests/uitests/src/com/android/settings/ui/WirelessNetworkSettingsTests.java
index dd700ac..d637c53 100644
--- a/tests/uitests/src/com/android/settings/ui/WirelessNetworkSettingsTests.java
+++ b/tests/uitests/src/com/android/settings/ui/WirelessNetworkSettingsTests.java
@@ -24,8 +24,6 @@
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.Until;
@@ -34,6 +32,9 @@
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java b/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java
index 864b7a9..4cb7ad9 100644
--- a/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java
+++ b/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java
@@ -17,6 +17,7 @@
 
 import static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE;
 import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -24,9 +25,6 @@
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.UiDevice;
@@ -39,6 +37,10 @@
 import android.system.helpers.SettingsHelper;
 import android.system.helpers.SettingsHelper.SettingsType;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/uitests/src/com/android/settings/ui/inputmethods/DataSaverSummaryUITest.java b/tests/uitests/src/com/android/settings/ui/inputmethods/DataSaverSummaryUITest.java
index 45f757c..fd8c054 100644
--- a/tests/uitests/src/com/android/settings/ui/inputmethods/DataSaverSummaryUITest.java
+++ b/tests/uitests/src/com/android/settings/ui/inputmethods/DataSaverSummaryUITest.java
@@ -21,13 +21,14 @@
 
 import android.app.Instrumentation;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/uitests/src/com/android/settings/ui/inputmethods/SpellCheckerSettingsUITest.java b/tests/uitests/src/com/android/settings/ui/inputmethods/SpellCheckerSettingsUITest.java
index 78c6f8c..9c18da5 100644
--- a/tests/uitests/src/com/android/settings/ui/inputmethods/SpellCheckerSettingsUITest.java
+++ b/tests/uitests/src/com/android/settings/ui/inputmethods/SpellCheckerSettingsUITest.java
@@ -21,13 +21,14 @@
 
 import android.app.Instrumentation;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/uitests/src/com/android/settings/ui/search/SettingsSearchResultRegressionTest.java b/tests/uitests/src/com/android/settings/ui/search/SettingsSearchResultRegressionTest.java
index 73cfb3e..298428c 100644
--- a/tests/uitests/src/com/android/settings/ui/search/SettingsSearchResultRegressionTest.java
+++ b/tests/uitests/src/com/android/settings/ui/search/SettingsSearchResultRegressionTest.java
@@ -27,12 +27,13 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk
index 1981a63..35d2205 100644
--- a/tests/unit/Android.mk
+++ b/tests/unit/Android.mk
@@ -14,10 +14,10 @@
 
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
-    espresso-core \
-    espresso-contrib-nodep \
-    espresso-intents-nodep \
+    androidx.test.rules \
+    androidx.test.espresso.core \
+    androidx.test.espresso.contrib-nodeps \
+    androidx.test.espresso.intents-nodeps \
     mockito-target-minus-junit4 \
     platform-test-annotations \
     truth-prebuilt \
diff --git a/tests/unit/AndroidManifest.xml b/tests/unit/AndroidManifest.xml
index 3eacab8..c387067 100644
--- a/tests/unit/AndroidManifest.xml
+++ b/tests/unit/AndroidManifest.xml
@@ -65,7 +65,7 @@
 
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.settings"
         android:label="Settings Test Cases">
     </instrumentation>
diff --git a/tests/unit/AndroidTest.xml b/tests/unit/AndroidTest.xml
index 0c4b1dd..b9321a3 100644
--- a/tests/unit/AndroidTest.xml
+++ b/tests/unit/AndroidTest.xml
@@ -24,7 +24,7 @@
     <option name="test-tag" value="SettingsUnitTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.settings.tests.unit" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/unit/README b/tests/unit/README
index 5184b07..881602a 100644
--- a/tests/unit/README
+++ b/tests/unit/README
@@ -5,13 +5,13 @@
 $ adb install -r out/target/product/shamu/data/app/SettingsUnitTests/SettingsUnitTests.apk
 
 To run all tests:
-$ adb shell am instrument -w com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
+$ adb shell am instrument -w com.android.settings.tests.unit/androidx.test.runner.AndroidJUnitRunner
 
 To run all tests in a specific class:
-$ adb shell am instrument -w -e class com.android.settings.<class> com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
+$ adb shell am instrument -w -e class com.android.settings.<class> com.android.settings.tests.unit/androidx.test.runner.AndroidJUnitRunner
 
 To run a specific test:
-$ adb shell am instrument -w -e class com.android.settings.<class>#<test> com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
+$ adb shell am instrument -w -e class com.android.settings.<class>#<test> com.android.settings.tests.unit/androidx.test.runner.AndroidJUnitRunner
 
 More general information can be found at
 http://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html
diff --git a/tests/unit/src/com/android/settings/DisplaySettingsTest.java b/tests/unit/src/com/android/settings/DisplaySettingsTest.java
index b5cd7cf..cc9cd81 100644
--- a/tests/unit/src/com/android/settings/DisplaySettingsTest.java
+++ b/tests/unit/src/com/android/settings/DisplaySettingsTest.java
@@ -16,18 +16,19 @@
 
 package com.android.settings;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/EncryptionInterstitialTest.java b/tests/unit/src/com/android/settings/EncryptionInterstitialTest.java
index 12610cc..9a6b754 100644
--- a/tests/unit/src/com/android/settings/EncryptionInterstitialTest.java
+++ b/tests/unit/src/com/android/settings/EncryptionInterstitialTest.java
@@ -16,9 +16,10 @@
 
 package com.android.settings;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -29,9 +30,10 @@
 import android.app.Instrumentation.ActivityResult;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/tests/unit/src/com/android/settings/ManagedAccessSettingsLowRamTest.java b/tests/unit/src/com/android/settings/ManagedAccessSettingsLowRamTest.java
index 6a63e05..426b8a4 100644
--- a/tests/unit/src/com/android/settings/ManagedAccessSettingsLowRamTest.java
+++ b/tests/unit/src/com/android/settings/ManagedAccessSettingsLowRamTest.java
@@ -16,21 +16,22 @@
 
 package com.android.settings;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/RegulatoryInfoDisplayActivityTest.java b/tests/unit/src/com/android/settings/RegulatoryInfoDisplayActivityTest.java
index a8a6b74..48f9f5d 100644
--- a/tests/unit/src/com/android/settings/RegulatoryInfoDisplayActivityTest.java
+++ b/tests/unit/src/com/android/settings/RegulatoryInfoDisplayActivityTest.java
@@ -16,11 +16,12 @@
 
 package com.android.settings;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.RootMatchers.isDialog;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.RootMatchers.isDialog;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
 import static junit.framework.Assert.fail;
 
 import android.app.Instrumentation;
@@ -29,11 +30,12 @@
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.graphics.Bitmap;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/UserCredentialsTest.java b/tests/unit/src/com/android/settings/UserCredentialsTest.java
index ad10e44..a182416 100644
--- a/tests/unit/src/com/android/settings/UserCredentialsTest.java
+++ b/tests/unit/src/com/android/settings/UserCredentialsTest.java
@@ -28,7 +28,7 @@
  *
  * To run the test, use command:
  * adb shell am instrument -e class com.android.settings.UserCredentialsTest
- * -w com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
+ * -w com.android.settings.tests.unit/androidx.test.runner.AndroidJUnitRunner
  *
  */
 public class UserCredentialsTest extends InstrumentationTestCase {
diff --git a/tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java b/tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
index 76d173d..f8d06a8 100644
--- a/tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
+++ b/tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
@@ -16,13 +16,14 @@
 
 package com.android.settings.accessibility;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
-import static android.support.test.espresso.matcher.ViewMatchers.isChecked;
-import static android.support.test.espresso.matcher.ViewMatchers.isNotChecked;
-import static android.support.test.espresso.matcher.ViewMatchers.withParent;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.withParent;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.Matchers.allOf;
@@ -30,11 +31,12 @@
 import android.app.Instrumentation;
 import android.os.Bundle;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.widget.CompoundButton;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.R;
 import com.android.settings.Settings.AccessibilitySettingsActivity;
 import com.android.settings.core.InstrumentedPreferenceFragment;
diff --git a/tests/unit/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/unit/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index 86b0964..9a3b526 100644
--- a/tests/unit/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/unit/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -16,17 +16,18 @@
 
 package com.android.settings.accessibility;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.app.Instrumentation;
 import android.os.Bundle;
 import android.os.Looper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.Settings.AccessibilitySettingsActivity;
 import com.android.settings.core.InstrumentedPreferenceFragment;
diff --git a/tests/unit/src/com/android/settings/accounts/AccountsSettingsTest.java b/tests/unit/src/com/android/settings/accounts/AccountsSettingsTest.java
index 5ee0408..84902fd 100644
--- a/tests/unit/src/com/android/settings/accounts/AccountsSettingsTest.java
+++ b/tests/unit/src/com/android/settings/accounts/AccountsSettingsTest.java
@@ -21,15 +21,16 @@
 import android.accounts.AccountManager;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/applications/AppOpsSettingsTest.java b/tests/unit/src/com/android/settings/applications/AppOpsSettingsTest.java
index 2ba855b..fbbc01a 100644
--- a/tests/unit/src/com/android/settings/applications/AppOpsSettingsTest.java
+++ b/tests/unit/src/com/android/settings/applications/AppOpsSettingsTest.java
@@ -20,6 +20,7 @@
 import static android.app.AppOpsManager.MODE_ERRORED;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -33,7 +34,6 @@
 import android.net.Uri;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.Direction;
@@ -43,14 +43,15 @@
 import android.widget.Switch;
 import android.widget.TextView;
 
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.InstrumentationRegistry;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.List;
 
-import androidx.recyclerview.widget.RecyclerView;
-
 /**
  * An abstract parent for testing settings activities that manage an AppOps permission.
  */
diff --git a/tests/unit/src/com/android/settings/applications/DefaultAppSettingsTest.java b/tests/unit/src/com/android/settings/applications/DefaultAppSettingsTest.java
index eafe32a..1dd899e 100644
--- a/tests/unit/src/com/android/settings/applications/DefaultAppSettingsTest.java
+++ b/tests/unit/src/com/android/settings/applications/DefaultAppSettingsTest.java
@@ -17,13 +17,14 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.filters.SmallTest;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiSelector;
 import android.test.InstrumentationTestCase;
 import android.widget.TextView;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.settings.R;
 
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/applications/DrawOverlaySettingsTest.java b/tests/unit/src/com/android/settings/applications/DrawOverlaySettingsTest.java
index 24760ae..b6d51ff 100644
--- a/tests/unit/src/com/android/settings/applications/DrawOverlaySettingsTest.java
+++ b/tests/unit/src/com/android/settings/applications/DrawOverlaySettingsTest.java
@@ -18,8 +18,9 @@
 
 import android.app.AppOpsManager;
 import android.provider.Settings;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.runner.RunWith;
 
diff --git a/tests/unit/src/com/android/settings/applications/ExternalSourcesSettingsTest.java b/tests/unit/src/com/android/settings/applications/ExternalSourcesSettingsTest.java
index 6ac21af..b35d6cb 100644
--- a/tests/unit/src/com/android/settings/applications/ExternalSourcesSettingsTest.java
+++ b/tests/unit/src/com/android/settings/applications/ExternalSourcesSettingsTest.java
@@ -18,8 +18,9 @@
 
 import android.app.AppOpsManager;
 import android.provider.Settings;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.runner.RunWith;
 
diff --git a/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java b/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java
index a751890..c98a43d 100644
--- a/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java
+++ b/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java
@@ -16,18 +16,20 @@
 
 package com.android.settings.applications;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static org.hamcrest.Matchers.allOf;
 
 import android.app.Instrumentation;
 import android.content.Intent;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/applications/SpecialAppAccessSettingsTest.java b/tests/unit/src/com/android/settings/applications/SpecialAppAccessSettingsTest.java
index 4165d06..4738d59 100644
--- a/tests/unit/src/com/android/settings/applications/SpecialAppAccessSettingsTest.java
+++ b/tests/unit/src/com/android/settings/applications/SpecialAppAccessSettingsTest.java
@@ -17,7 +17,6 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.filters.SmallTest;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
@@ -26,6 +25,8 @@
 import android.test.InstrumentationTestCase;
 import android.widget.TextView;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.settings.R;
 
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/applications/manageapplications/ManageApplicationsUnitTest.java b/tests/unit/src/com/android/settings/applications/manageapplications/ManageApplicationsUnitTest.java
index 87a24d6..4a08471 100644
--- a/tests/unit/src/com/android/settings/applications/manageapplications/ManageApplicationsUnitTest.java
+++ b/tests/unit/src/com/android/settings/applications/manageapplications/ManageApplicationsUnitTest.java
@@ -17,11 +17,13 @@
 package com.android.settings.applications.manageapplications;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 
 import android.content.pm.ApplicationInfo;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
diff --git a/tests/unit/src/com/android/settings/backup/BackupIntentTest.java b/tests/unit/src/com/android/settings/backup/BackupIntentTest.java
index ce611d0..18fb17a 100644
--- a/tests/unit/src/com/android/settings/backup/BackupIntentTest.java
+++ b/tests/unit/src/com/android/settings/backup/BackupIntentTest.java
@@ -23,9 +23,10 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
index e93135d..3a88873 100644
--- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
@@ -15,22 +15,24 @@
  */
 package com.android.settings.biometrics.fingerprint;
 
-import static android.support.test.InstrumentationRegistry.getTargetContext;
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.intent.Intents.intended;
-import static android.support.test.espresso.intent.Intents.intending;
-import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.InstrumentationRegistry.getTargetContext;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.intent.Intents.intended;
+import static androidx.test.espresso.intent.Intents.intending;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
 import android.app.Instrumentation.ActivityResult;
 import android.content.ComponentName;
-import android.support.test.espresso.intent.rule.IntentsTestRule;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.espresso.intent.rule.IntentsTestRule;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.R;
 
diff --git a/tests/unit/src/com/android/settings/bluetooth/BluetoothDeviceDetailsRotationTest.java b/tests/unit/src/com/android/settings/bluetooth/BluetoothDeviceDetailsRotationTest.java
index 06187f7..4ed04f0 100644
--- a/tests/unit/src/com/android/settings/bluetooth/BluetoothDeviceDetailsRotationTest.java
+++ b/tests/unit/src/com/android/settings/bluetooth/BluetoothDeviceDetailsRotationTest.java
@@ -23,11 +23,12 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.SettingsActivity;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
diff --git a/tests/unit/src/com/android/settings/bluetooth/DevicePickerActivityTest.java b/tests/unit/src/com/android/settings/bluetooth/DevicePickerActivityTest.java
index 1b855c9..e531e0a 100644
--- a/tests/unit/src/com/android/settings/bluetooth/DevicePickerActivityTest.java
+++ b/tests/unit/src/com/android/settings/bluetooth/DevicePickerActivityTest.java
@@ -18,9 +18,10 @@
 
 import android.app.Instrumentation;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/connecteddevice/ConnectedDeviceActivityTest.java b/tests/unit/src/com/android/settings/connecteddevice/ConnectedDeviceActivityTest.java
index 4be8a39..2957c4c 100644
--- a/tests/unit/src/com/android/settings/connecteddevice/ConnectedDeviceActivityTest.java
+++ b/tests/unit/src/com/android/settings/connecteddevice/ConnectedDeviceActivityTest.java
@@ -22,11 +22,12 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/core/LifecycleEventHandlingTest.java b/tests/unit/src/com/android/settings/core/LifecycleEventHandlingTest.java
index 9a2684b..e601171 100644
--- a/tests/unit/src/com/android/settings/core/LifecycleEventHandlingTest.java
+++ b/tests/unit/src/com/android/settings/core/LifecycleEventHandlingTest.java
@@ -17,19 +17,21 @@
 package com.android.settings.core;
 
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.Direction;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.development.featureflags.FeatureFlagsDashboard;
 import com.android.settingslib.core.instrumentation.Instrumentable;
 
diff --git a/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java b/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
index 59f22db..ad6be04 100644
--- a/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
+++ b/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
@@ -21,11 +21,12 @@
 import android.content.Context;
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settings.search.Indexable;
diff --git a/tests/unit/src/com/android/settings/core/SettingsGatewayTest.java b/tests/unit/src/com/android/settings/core/SettingsGatewayTest.java
index ed49b2e..7d03bba 100644
--- a/tests/unit/src/com/android/settings/core/SettingsGatewayTest.java
+++ b/tests/unit/src/com/android/settings/core/SettingsGatewayTest.java
@@ -19,9 +19,12 @@
 import static android.content.pm.PackageManager.GET_ACTIVITIES;
 import static android.content.pm.PackageManager.GET_META_DATA;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+
 import static com.android.settings.SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS;
 import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.fail;
+
 import static org.junit.Assert.assertFalse;
 
 import android.content.ComponentName;
@@ -33,12 +36,13 @@
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.core.gateway.SettingsGateway;
 
 import org.junit.Before;
diff --git a/tests/unit/src/com/android/settings/core/UniquePreferenceTest.java b/tests/unit/src/com/android/settings/core/UniquePreferenceTest.java
index 5853331..0998494 100644
--- a/tests/unit/src/com/android/settings/core/UniquePreferenceTest.java
+++ b/tests/unit/src/com/android/settings/core/UniquePreferenceTest.java
@@ -23,12 +23,13 @@
 import android.os.Bundle;
 import android.platform.test.annotations.Presubmit;
 import android.provider.SearchIndexableResource;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
diff --git a/tests/unit/src/com/android/settings/core/UserRestrictionTest.java b/tests/unit/src/com/android/settings/core/UserRestrictionTest.java
index 4fa7b08..20f8765 100644
--- a/tests/unit/src/com/android/settings/core/UserRestrictionTest.java
+++ b/tests/unit/src/com/android/settings/core/UserRestrictionTest.java
@@ -24,13 +24,14 @@
 import android.content.res.XmlResourceParser;
 import android.os.UserManager;
 import android.provider.SearchIndexableResource;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settings.search.Indexable;
diff --git a/tests/unit/src/com/android/settings/dashboard/PreferenceThemeTest.java b/tests/unit/src/com/android/settings/dashboard/PreferenceThemeTest.java
index 7cf76c6..18a5e70 100644
--- a/tests/unit/src/com/android/settings/dashboard/PreferenceThemeTest.java
+++ b/tests/unit/src/com/android/settings/dashboard/PreferenceThemeTest.java
@@ -16,22 +16,25 @@
 
 package com.android.settings.dashboard;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
 import static com.android.settings.dashboard.FirstIdViewMatcher.withFirstId;
+
 import static org.hamcrest.Matchers.allOf;
 
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.espresso.matcher.ViewMatchers.Visibility;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.espresso.matcher.ViewMatchers.Visibility;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.R;
 
diff --git a/tests/unit/src/com/android/settings/datausage/MobileDataUsageActivityTest.java b/tests/unit/src/com/android/settings/datausage/MobileDataUsageActivityTest.java
index 135ad9d..066d199 100644
--- a/tests/unit/src/com/android/settings/datausage/MobileDataUsageActivityTest.java
+++ b/tests/unit/src/com/android/settings/datausage/MobileDataUsageActivityTest.java
@@ -22,12 +22,13 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.net.NetworkTemplate;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/unit/src/com/android/settings/datetime/timezone/model/TimeZoneDataTest.java b/tests/unit/src/com/android/settings/datetime/timezone/model/TimeZoneDataTest.java
index 444be93..2659529 100644
--- a/tests/unit/src/com/android/settings/datetime/timezone/model/TimeZoneDataTest.java
+++ b/tests/unit/src/com/android/settings/datetime/timezone/model/TimeZoneDataTest.java
@@ -17,8 +17,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerInstrumentationTest.java b/tests/unit/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerInstrumentationTest.java
index ce81667..dbb73c0 100644
--- a/tests/unit/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerInstrumentationTest.java
+++ b/tests/unit/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerInstrumentationTest.java
@@ -17,9 +17,10 @@
 package com.android.settings.development;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.R;
 
diff --git a/tests/unit/src/com/android/settings/deviceinfo/PrivateVolumeForgetTest.java b/tests/unit/src/com/android/settings/deviceinfo/PrivateVolumeForgetTest.java
index 5c8f8b5..1edfa93 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/PrivateVolumeForgetTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/PrivateVolumeForgetTest.java
@@ -20,10 +20,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.storage.VolumeRecord;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.Settings;
 
@@ -31,7 +32,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PrivateVolumeForgetTest {
diff --git a/tests/unit/src/com/android/settings/deviceinfo/PublicVolumeSettingsTest.java b/tests/unit/src/com/android/settings/deviceinfo/PublicVolumeSettingsTest.java
index 4903b86..03d2d5a 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/PublicVolumeSettingsTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/PublicVolumeSettingsTest.java
@@ -18,10 +18,11 @@
 package com.android.settings.deviceinfo;
 
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.Settings;
 
@@ -29,7 +30,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PublicVolumeSettingsTest {
diff --git a/tests/unit/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java b/tests/unit/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
index e0fb1af..a0053be 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
@@ -1,15 +1,16 @@
 package com.android.settings.deviceinfo;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.intent.Intents.intended;
-import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtra;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.intent.Intents.intended;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
 
-import android.support.test.espresso.intent.rule.IntentsTestRule;
-import android.support.test.filters.SmallTest;
+import androidx.test.espresso.intent.rule.IntentsTestRule;
+import androidx.test.filters.SmallTest;
 
 import com.android.settings.R;
 import com.android.settings.Settings.StorageDashboardActivity;
diff --git a/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java b/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java
index 1862bba..f2349bb 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/storage/StorageAsyncLoaderTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.deviceinfo.storage;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
@@ -32,10 +33,11 @@
 import android.net.TrafficStats;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settingslib.applications.StorageStatsSource;
 
 import org.junit.Before;
diff --git a/tests/unit/src/com/android/settings/display/NightDisplaySettingsActivityTest.java b/tests/unit/src/com/android/settings/display/NightDisplaySettingsActivityTest.java
index 4011d9a..0ae6b62 100644
--- a/tests/unit/src/com/android/settings/display/NightDisplaySettingsActivityTest.java
+++ b/tests/unit/src/com/android/settings/display/NightDisplaySettingsActivityTest.java
@@ -22,9 +22,10 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.Settings.NightDisplaySettingsActivity;
 
diff --git a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
index 96ffe23..3cdfb7c 100644
--- a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.display;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
@@ -31,9 +32,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.preference.ListPreference;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -42,8 +45,6 @@
 
 import java.util.ArrayList;
 
-import androidx.preference.ListPreference;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class ThemePreferenceControllerTest {
diff --git a/tests/unit/src/com/android/settings/dream/DreamSettingsLaunchTest.java b/tests/unit/src/com/android/settings/dream/DreamSettingsLaunchTest.java
index 0993564..6a2abd5 100644
--- a/tests/unit/src/com/android/settings/dream/DreamSettingsLaunchTest.java
+++ b/tests/unit/src/com/android/settings/dream/DreamSettingsLaunchTest.java
@@ -19,9 +19,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/unit/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 9cbd742..2c80a82 100644
--- a/tests/unit/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/unit/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -16,15 +16,16 @@
 
 package com.android.settings.fuelgauge;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.app.Instrumentation;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.R;
 
diff --git a/tests/unit/src/com/android/settings/fuelgauge/batterytip/RestrictAppTest.java b/tests/unit/src/com/android/settings/fuelgauge/batterytip/RestrictAppTest.java
index 788b3ba..d9874f4 100644
--- a/tests/unit/src/com/android/settings/fuelgauge/batterytip/RestrictAppTest.java
+++ b/tests/unit/src/com/android/settings/fuelgauge/batterytip/RestrictAppTest.java
@@ -16,19 +16,21 @@
 
 package com.android.settings.fuelgauge.batterytip;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/unit/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index 5bdeb8d..82fcd7d 100644
--- a/tests/unit/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/unit/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -20,8 +20,9 @@
 
 import android.content.Context;
 import android.net.Uri;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/notification/AppNotificationSettingsTest.java b/tests/unit/src/com/android/settings/notification/AppNotificationSettingsTest.java
index 4d5278a..ede4631 100644
--- a/tests/unit/src/com/android/settings/notification/AppNotificationSettingsTest.java
+++ b/tests/unit/src/com/android/settings/notification/AppNotificationSettingsTest.java
@@ -17,17 +17,20 @@
 package com.android.settings.notification;
 
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.intent.Intents.intended;
-import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtra;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.intent.Intents.intended;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT;
+
 import static org.hamcrest.Matchers.allOf;
 import static org.junit.Assert.fail;
 
@@ -38,11 +41,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.espresso.intent.Intents;
-import android.support.test.espresso.matcher.ViewMatchers;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.espresso.intent.Intents;
+import androidx.test.espresso.matcher.ViewMatchers;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/notification/ChannelNotificationSettingsTest.java b/tests/unit/src/com/android/settings/notification/ChannelNotificationSettingsTest.java
index f27bfd4..f7a5a82 100644
--- a/tests/unit/src/com/android/settings/notification/ChannelNotificationSettingsTest.java
+++ b/tests/unit/src/com/android/settings/notification/ChannelNotificationSettingsTest.java
@@ -18,10 +18,12 @@
 
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static org.hamcrest.Matchers.allOf;
 import static org.junit.Assert.fail;
 
@@ -34,9 +36,10 @@
 import android.os.Process;
 import android.os.ServiceManager;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java b/tests/unit/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java
index e7a057c..2fe4074 100644
--- a/tests/unit/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java
+++ b/tests/unit/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java
@@ -1,18 +1,19 @@
 package com.android.settings;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/password/ChooseLockGenericTest.java b/tests/unit/src/com/android/settings/password/ChooseLockGenericTest.java
index 32b47df..582afd2 100644
--- a/tests/unit/src/com/android/settings/password/ChooseLockGenericTest.java
+++ b/tests/unit/src/com/android/settings/password/ChooseLockGenericTest.java
@@ -16,9 +16,11 @@
 
 package com.android.settings.password;
 
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
-import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.InstrumentationRegistry.getTargetContext;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
@@ -28,17 +30,18 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
-import android.support.test.runner.lifecycle.Stage;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiSelector;
 import android.text.format.DateUtils;
 import android.view.WindowManager;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
+import androidx.test.runner.lifecycle.Stage;
+
 import com.android.internal.widget.LockPatternUtils;
 
 import org.junit.Before;
@@ -56,7 +59,7 @@
  * adb install \
  * -r -g  ${ANDROID_PRODUCT_OUT}/data/app/SettingsTests/SettingsTests.apk &&
  * adb shell am instrument -e class com.android.settings.password.ChooseLockGenericTest \
- * -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner
+ * -w com.android.settings.tests/androidx.test.runner.AndroidJUnitRunner
  */
 @RunWith(AndroidJUnit4.class)
 @MediumTest
diff --git a/tests/unit/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/unit/src/com/android/settings/password/ChooseLockPasswordTest.java
index 87a8af8..57a4965 100644
--- a/tests/unit/src/com/android/settings/password/ChooseLockPasswordTest.java
+++ b/tests/unit/src/com/android/settings/password/ChooseLockPasswordTest.java
@@ -16,24 +16,26 @@
 
 package com.android.settings.password;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.pressKey;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
-import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.pressKey;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
+import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
 import static org.hamcrest.CoreMatchers.not;
 
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.espresso.action.ViewActions;
-import android.support.test.espresso.matcher.ViewMatchers;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.KeyEvent;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.espresso.action.ViewActions;
+import androidx.test.espresso.matcher.ViewMatchers;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.R;
 
 import org.junit.Before;
diff --git a/tests/unit/src/com/android/settings/password/ConfirmLockPasswordTest.java b/tests/unit/src/com/android/settings/password/ConfirmLockPasswordTest.java
index 25e7da0..321284f 100644
--- a/tests/unit/src/com/android/settings/password/ConfirmLockPasswordTest.java
+++ b/tests/unit/src/com/android/settings/password/ConfirmLockPasswordTest.java
@@ -16,20 +16,21 @@
 
 package com.android.settings.password;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.pressKey;
-import static android.support.test.espresso.action.ViewActions.typeText;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.pressKey;
+import static androidx.test.espresso.action.ViewActions.typeText;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.KeyEvent;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.R;
 
 import org.junit.Before;
diff --git a/tests/unit/src/com/android/settings/password/SetupChooseLockGenericTest.java b/tests/unit/src/com/android/settings/password/SetupChooseLockGenericTest.java
index ce3d08f..b0ca636 100644
--- a/tests/unit/src/com/android/settings/password/SetupChooseLockGenericTest.java
+++ b/tests/unit/src/com/android/settings/password/SetupChooseLockGenericTest.java
@@ -17,8 +17,9 @@
 package com.android.settings.password;
 
 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
-import static android.support.test.InstrumentationRegistry.getTargetContext;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.InstrumentationRegistry.getTargetContext;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -26,13 +27,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
-import android.support.test.runner.lifecycle.Stage;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiSelector;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
+import androidx.test.runner.lifecycle.Stage;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java b/tests/unit/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java
index 6cf812d..1b12c54 100644
--- a/tests/unit/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java
+++ b/tests/unit/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java
@@ -16,25 +16,28 @@
 
 package com.android.settings.password;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.action.ViewActions.pressKey;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
-import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.pressKey;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
+import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.hamcrest.CoreMatchers.not;
 
-import android.support.test.espresso.action.ViewActions;
-import android.support.test.espresso.matcher.ViewMatchers;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.KeyEvent;
 
+import androidx.test.espresso.action.ViewActions;
+import androidx.test.espresso.matcher.ViewMatchers;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.R;
 
 import org.junit.Rule;
diff --git a/tests/unit/src/com/android/settings/print/PrintJobSettingsActivityTest.java b/tests/unit/src/com/android/settings/print/PrintJobSettingsActivityTest.java
index f5381d4..56a4945 100644
--- a/tests/unit/src/com/android/settings/print/PrintJobSettingsActivityTest.java
+++ b/tests/unit/src/com/android/settings/print/PrintJobSettingsActivityTest.java
@@ -32,16 +32,18 @@
 import android.print.PrintDocumentInfo;
 import android.print.PrintJob;
 import android.print.PrintManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.Settings;
 
 import org.junit.Before;
@@ -53,8 +55,6 @@
 import java.io.IOException;
 import java.util.UUID;
 
-import androidx.annotation.NonNull;
-
 @RunWith(AndroidJUnit4.class)
 public class PrintJobSettingsActivityTest {
     private static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID";
diff --git a/tests/unit/src/com/android/settings/search/SearchIndexablesContractTest.java b/tests/unit/src/com/android/settings/search/SearchIndexablesContractTest.java
index 2e779e8..b63a8b3 100644
--- a/tests/unit/src/com/android/settings/search/SearchIndexablesContractTest.java
+++ b/tests/unit/src/com/android/settings/search/SearchIndexablesContractTest.java
@@ -20,8 +20,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.provider.SearchIndexablesContract;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/search/SearchResultTrampolineTest.java b/tests/unit/src/com/android/settings/search/SearchResultTrampolineTest.java
index 974518f..b9eff64 100644
--- a/tests/unit/src/com/android/settings/search/SearchResultTrampolineTest.java
+++ b/tests/unit/src/com/android/settings/search/SearchResultTrampolineTest.java
@@ -22,9 +22,10 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java b/tests/unit/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
index 3659fdb..9fcca46 100644
--- a/tests/unit/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
+++ b/tests/unit/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
@@ -23,9 +23,10 @@
 import android.net.Uri;
 import android.platform.test.annotations.Presubmit;
 import android.provider.SearchIndexablesContract;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/tests/unit/src/com/android/settings/slices/SliceDataContractTest.java b/tests/unit/src/com/android/settings/slices/SliceDataContractTest.java
index 9301555..a914c1c9 100644
--- a/tests/unit/src/com/android/settings/slices/SliceDataContractTest.java
+++ b/tests/unit/src/com/android/settings/slices/SliceDataContractTest.java
@@ -22,12 +22,13 @@
 import android.os.Bundle;
 import android.platform.test.annotations.Presubmit;
 import android.provider.SearchIndexableResource;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.core.PreferenceXmlParserUtils;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
diff --git a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
index bd8649d..0c5f501 100644
--- a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
+++ b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
@@ -22,9 +22,10 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/tests/DrawOverlayDetailsTest.java b/tests/unit/src/com/android/settings/tests/DrawOverlayDetailsTest.java
index 9bf9ac4..d450bf0 100644
--- a/tests/unit/src/com/android/settings/tests/DrawOverlayDetailsTest.java
+++ b/tests/unit/src/com/android/settings/tests/DrawOverlayDetailsTest.java
@@ -16,25 +16,27 @@
 
 package com.android.settings.tests;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static org.hamcrest.core.IsNot.not;
 
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.R;
 
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/tests/KeepOnScreenTest.java b/tests/unit/src/com/android/settings/tests/KeepOnScreenTest.java
index 64eee42..b930ffb 100644
--- a/tests/unit/src/com/android/settings/tests/KeepOnScreenTest.java
+++ b/tests/unit/src/com/android/settings/tests/KeepOnScreenTest.java
@@ -16,9 +16,10 @@
 
 package com.android.settings.tests;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static junit.framework.Assert.assertEquals;
 
 import android.app.Instrumentation;
@@ -26,9 +27,10 @@
 import android.content.Intent;
 import android.os.BatteryManager;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.R;
 
diff --git a/tests/unit/src/com/android/settings/tests/PrivateVolumeSettingsTest.java b/tests/unit/src/com/android/settings/tests/PrivateVolumeSettingsTest.java
index d10b20b..2760a07 100644
--- a/tests/unit/src/com/android/settings/tests/PrivateVolumeSettingsTest.java
+++ b/tests/unit/src/com/android/settings/tests/PrivateVolumeSettingsTest.java
@@ -15,15 +15,16 @@
  */
 package com.android.settings.tests;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.app.Instrumentation;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/tests/SettingsRestoreAfterCloseTest.java b/tests/unit/src/com/android/settings/tests/SettingsRestoreAfterCloseTest.java
index cd9ac97..3c6caf7 100644
--- a/tests/unit/src/com/android/settings/tests/SettingsRestoreAfterCloseTest.java
+++ b/tests/unit/src/com/android/settings/tests/SettingsRestoreAfterCloseTest.java
@@ -19,13 +19,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.Until;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/users/UserSettingsTest.java b/tests/unit/src/com/android/settings/users/UserSettingsTest.java
index 6d0021a..93f62f3 100644
--- a/tests/unit/src/com/android/settings/users/UserSettingsTest.java
+++ b/tests/unit/src/com/android/settings/users/UserSettingsTest.java
@@ -19,15 +19,16 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/utils/FileSizeFormatterTest.java b/tests/unit/src/com/android/settings/utils/FileSizeFormatterTest.java
index d2be760..a255d0b 100644
--- a/tests/unit/src/com/android/settings/utils/FileSizeFormatterTest.java
+++ b/tests/unit/src/com/android/settings/utils/FileSizeFormatterTest.java
@@ -21,9 +21,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java b/tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java
index 79eccc4..1a5f923 100644
--- a/tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java
+++ b/tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java
@@ -15,17 +15,18 @@
  */
 package com.android.settings.wifi;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.Settings;
 
@@ -34,7 +35,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 @RunWith(AndroidJUnit4.class)
 public class SavedNetworkSettingsTest {
 
diff --git a/tests/unit/src/com/android/settings/wifi/WifiCallingSettingUiTest.java b/tests/unit/src/com/android/settings/wifi/WifiCallingSettingUiTest.java
index 1a7252f..3198914 100644
--- a/tests/unit/src/com/android/settings/wifi/WifiCallingSettingUiTest.java
+++ b/tests/unit/src/com/android/settings/wifi/WifiCallingSettingUiTest.java
@@ -15,14 +15,15 @@
  */
 package com.android.settings.wifi;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.isSelected;
-import static android.support.test.espresso.matcher.ViewMatchers.withResourceName;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isSelected;
+import static androidx.test.espresso.matcher.ViewMatchers.withResourceName;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static org.hamcrest.CoreMatchers.allOf;
 import static org.hamcrest.CoreMatchers.anything;
 import static org.junit.Assert.assertEquals;
@@ -35,13 +36,14 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.espresso.NoMatchingViewException;
-import android.support.test.espresso.ViewInteraction;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.telephony.SubscriptionInfo;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.espresso.NoMatchingViewException;
+import androidx.test.espresso.ViewInteraction;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
 import com.android.internal.telephony.SubscriptionController;
diff --git a/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java b/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
index 54fdcc3..be593a9 100644
--- a/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
+++ b/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
@@ -15,16 +15,18 @@
  */
 package com.android.settings.wifi;
 
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.startsWith;
@@ -41,9 +43,11 @@
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiSsid;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.fragment.app.Fragment;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settings.Settings.WifiSettingsActivity;
 import com.android.settingslib.utils.ThreadUtils;
@@ -65,8 +69,6 @@
 
 import java.util.List;
 
-import androidx.fragment.app.Fragment;
-
 @RunWith(AndroidJUnit4.class)
 public class WifiSettingsUiTest {
     private static final String TEST_SSID = "\"Test Ssid\"";
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 2f95fa5..235f182 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -18,12 +18,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.app.Activity;
 import android.content.Intent;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 
-import org.junit.Before;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java
index d3f667f..239f525 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java
@@ -16,13 +16,11 @@
 
 package com.android.settings.wifi.dpp;
 
-import android.app.Activity;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 
-import com.android.settings.R;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Rule;
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 70cfc2d..16be216 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
@@ -16,13 +16,11 @@
 
 package com.android.settings.wifi.dpp;
 
-import android.app.Activity;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 
-import com.android.settings.R;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
index 96e6c4e..cb586e4 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
@@ -16,21 +16,22 @@
 
 package com.android.settings.wifi.tether;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.app.Instrumentation;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settings.Settings;
 
 import org.junit.After;