Merge "Update notification history text styles"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d2bdc9f..4996aeb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -384,12 +384,10 @@
                 android:value="true" />
         </activity>
 
-        <!-- Runs in the phone process since it needs access to UiccController -->
         <activity android:name="Settings$ApnSettingsActivity"
                 android:label="@string/apn_settings"
                 android:launchMode="singleTask"
-                android:configChanges="orientation|keyboardHidden|screenSize"
-                android:process="com.android.phone">
+                android:configChanges="orientation|keyboardHidden|screenSize">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.APN_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -1199,6 +1197,10 @@
         <activity
             android:name=".notification.history.NotificationHistoryActivity"
             android:label="@string/notification_history_title">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.NOTIFICATION_HISTORY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -1418,8 +1420,7 @@
         </activity>
 
         <activity android:name="Settings$IccLockSettingsActivity"
-                android:label="@string/sim_lock_settings"
-                android:process="com.android.phone">
+                android:label="@string/sim_lock_settings">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/res/layout/accessibility_autoclick_custom_seekbar.xml b/res/layout/accessibility_autoclick_custom_seekbar.xml
index 7483759..0a60cff 100644
--- a/res/layout/accessibility_autoclick_custom_seekbar.xml
+++ b/res/layout/accessibility_autoclick_custom_seekbar.xml
@@ -50,7 +50,8 @@
         <SeekBar
             android:id="@+id/autoclick_delay"
             android:layout_width="260dp"
-            android:layout_height="48dp" />
+            android:layout_height="48dp"
+            android:contentDescription="@string/accessibility_autoclick_seekbar_desc" />
 
         <ImageView
             android:id="@+id/larger"
diff --git a/res/layout/conditional_card_full_tile.xml b/res/layout/conditional_card_full_tile.xml
index 81889fb..4c0da17 100644
--- a/res/layout/conditional_card_full_tile.xml
+++ b/res/layout/conditional_card_full_tile.xml
@@ -57,7 +57,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_marginBottom="@dimen/contextual_condition_card_title_margin_bottom"
-                    android:textAppearance="@style/TextAppearance.ConditionCardTitle"/>
+                    android:textAppearance="@style/TextAppearance.HomepageCardTitle"/>
 
                 <TextView
                     android:id="@android:id/summary"
diff --git a/res/layout/conditional_card_half_tile.xml b/res/layout/conditional_card_half_tile.xml
index 9bbaf86..6f83ef3 100644
--- a/res/layout/conditional_card_half_tile.xml
+++ b/res/layout/conditional_card_half_tile.xml
@@ -51,7 +51,7 @@
                 android:layout_marginStart="@dimen/contextual_card_text_padding_start"
                 android:layout_marginTop="@dimen/contextual_condition_half_card_title_margin_top"
                 android:layout_marginBottom="@dimen/contextual_condition_card_title_margin_bottom"
-                android:textAppearance="@style/TextAppearance.ConditionCardTitle"/>
+                android:textAppearance="@style/TextAppearance.HomepageCardTitle"/>
 
             <TextView
                 android:id="@android:id/summary"
diff --git a/res/layout/contextual_slice_full_tile.xml b/res/layout/contextual_slice_full_tile.xml
index b67b777..1438cfb 100644
--- a/res/layout/contextual_slice_full_tile.xml
+++ b/res/layout/contextual_slice_full_tile.xml
@@ -29,6 +29,7 @@
 
         <androidx.slice.widget.SliceView
             android:id="@+id/slice_view"
+            android:theme="@style/Theme.Settings.ContextualCard"
             style="@style/ContextualCardSliceViewStyle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/res/layout/contextual_slice_half_tile.xml b/res/layout/contextual_slice_half_tile.xml
index 490b0ac..d2011ad 100644
--- a/res/layout/contextual_slice_half_tile.xml
+++ b/res/layout/contextual_slice_half_tile.xml
@@ -52,7 +52,7 @@
                 android:ellipsize="end"
                 android:layout_marginStart="@dimen/contextual_card_text_padding_start"
                 android:layout_marginTop="@dimen/contextual_half_card_title_margin_top"
-                android:textAppearance="@style/TextAppearance.ConditionCardTitle"/>
+                android:textAppearance="@style/TextAppearance.HomepageCardTitle"/>
 
         </LinearLayout>
 
diff --git a/res/layout/contextual_slice_sticky_tile.xml b/res/layout/contextual_slice_sticky_tile.xml
index 8e82f53..117732d 100644
--- a/res/layout/contextual_slice_sticky_tile.xml
+++ b/res/layout/contextual_slice_sticky_tile.xml
@@ -23,6 +23,7 @@
 
     <androidx.slice.widget.SliceView
         android:id="@+id/slice_view"
+        android:theme="@style/Theme.Settings.ContextualCard"
         style="@style/ContextualCardSliceViewStyle"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 750cd53..c32d557 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3750,6 +3750,14 @@
     <!-- Tethering controls, footer note displayed when tethering is disabled because Data Saver mode is on [CHAR LIMIT=none]-->
     <string name="tether_settings_disabled_on_data_saver">"Can\u2019t tether or use portable hotspots while Data Saver is on"</string>
 
+    <!-- Disable Wifi Hotspot option-->
+    <!-- Don't use Wi-Fi hotspot summary when USB tethering is chosen [CHAR LIMIT=NONE]-->
+    <string name="disable_wifi_hotspot_when_usb_on">Only share internet via USB</string>
+    <!-- Don't use Wi-Fi hotspot summary when Bluetooth tethering is chosen [CHAR LIMIT=NONE]-->
+    <string name="disable_wifi_hotspot_when_bluetooth_on">Only share internet via Bluetooth</string>
+    <!-- Don't use Wi-Fi hotspot summary when USB tethering and Bluetooth tethering are chosen [CHAR LIMIT=NONE]-->
+    <string name="disable_wifi_hotspot_when_usb_and_bluetooth_on">Only share internet via USB and Bluetooth</string>
+
     <!-- USB Tethering options -->
     <string name="usb_title">USB</string>
     <string name="usb_tethering_button_text">USB tethering</string>
@@ -4953,10 +4961,12 @@
     <string name="accessibility_autoclick_long_summary">1 second</string>
     <!-- Option heading to leave the auto click requirement for accessibility users at its custom level. [CHAR LIMIT=35] -->
     <string name="accessibility_autoclick_custom_title">Custom</string>
-    <!-- Description for the button that shorter delay time. [CHAR_LIMIT=NONE] -->
+    <!-- Description for the button that shorter auto click time. [CHAR_LIMIT=NONE] -->
     <string name="accessibility_autoclick_shorter_desc">Shorter</string>
-    <!-- Description for the button that longer time. [CHAR_LIMIT=NONE] -->
+    <!-- Description for the button that longer auto click time. [CHAR_LIMIT=NONE] -->
     <string name="accessibility_autoclick_longer_desc">Longer</string>
+    <!-- Description for the seekbar that adjust auto click time. [CHAR_LIMIT=NONE] -->
+    <string name="accessibility_autoclick_seekbar_desc">auto click time</string>
     <!-- Title for accessibility preference screen for configuring vibrations. -->
     <string name="accessibility_vibration_settings_title">Vibration &amp; haptic strength</string>
     <!-- Title for accessibility preference for configuring notification vibrations. -->
@@ -8055,6 +8065,9 @@
     <!-- Notification history screen; summary when history is off [CHAR LIMIT=200] -->
     <string name="notification_history_off_title_extended">Notification history is turned off</string>
 
+    <!-- Notification history screen; content description describing what happens when you tap on a notification history entry [CHAR LIMIT=NONE] -->
+    <string name="notification_history_view_settings">view notification settings</string>
+
     <!-- Configure Notifications: setting title, whether the snooze menu is shown on notifications [CHAR LIMIT=80] -->
     <string name="snooze_options_title">Allow notification snoozing</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a4c82b2..02998ae 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -274,7 +274,7 @@
         <item name="android:textSize">@dimen/search_bar_text_size</item>
     </style>
 
-    <style name="TextAppearance.ConditionCardTitle"
+    <style name="TextAppearance.HomepageCardTitle"
            parent="@*android:style/TextAppearance.DeviceDefault.Subhead">
         <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
         <item name="android:textSize">16sp</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 76d6e38..172a89a 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -210,6 +210,10 @@
         <item name="android:windowBackground">@android:color/white</item>
     </style>
 
+    <style name="Theme.Settings.ContextualCard" parent="Theme.Settings.Home">
+        <item name="android:textAppearanceListItem">@style/TextAppearance.HomepageCardTitle</item>
+    </style>
+
     <!-- Note that Dialog themes do not set list dividers -->
     <style name="Theme.Panel" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog">
         <item name="android:windowBackground">@null</item>
diff --git a/res/xml/all_tether_prefs.xml b/res/xml/all_tether_prefs.xml
index bc3471b..d16adc5 100644
--- a/res/xml/all_tether_prefs.xml
+++ b/res/xml/all_tether_prefs.xml
@@ -74,6 +74,7 @@
         <SwitchPreference
             android:key="disable_wifi_tethering"
             android:title="Don't use Wi-Fi hotspot"
+            android:summary="@string/summary_placeholder"
             settings:controller="com.android.settings.network.WifiTetherDisablePreferenceController"
             settings:keywords="@string/keywords_hotspot_tethering" />
     </PreferenceCategory>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index ba62380..bd8f1dd 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -21,7 +21,7 @@
 
     <Preference
         android:fragment="com.android.settings.connecteddevice.BluetoothDashboardFragment"
-        android:key="bluetooth_settings"
+        android:key="bluetooth_switchbar_screen"
         android:title="@string/bluetooth_settings_title"
         android:icon="@*android:drawable/ic_settings_bluetooth"
         android:order="-9"/>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index a49d85b..940cb59 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -218,7 +218,7 @@
             android:key="graphics_driver_dashboard"
             android:title="@string/graphics_driver_dashboard_title"
             android:summary="@string/graphics_driver_dashboard_summary"
-            android:fragment="com.android.settings.development.gamedriver.GameDriverDashboard" />
+            android:fragment="com.android.settings.development.graphicsdriver.GraphicsDriverDashboard" />
 
         <Preference
             android:key="platform_compat_dashboard"
diff --git a/res/xml/development_tile_settings.xml b/res/xml/development_tile_settings.xml
index e5bfbbf..558535fe 100644
--- a/res/xml/development_tile_settings.xml
+++ b/res/xml/development_tile_settings.xml
@@ -18,5 +18,7 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="development_tile_settings"
     android:title="@string/quick_settings_developer_tiles"
+    settings:searchable="false"
     settings:controller="com.android.settings.development.qstile.DevelopmentTilePreferenceController" />
diff --git a/res/xml/device_admin_settings.xml b/res/xml/device_admin_settings.xml
index 9a48761..6fbc139 100644
--- a/res/xml/device_admin_settings.xml
+++ b/res/xml/device_admin_settings.xml
@@ -19,6 +19,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/manage_device_admin"
+    android:key="device_admin_settings"
+    settings:searchable="false"
     settings:controller="com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminListPreferenceController">
 
     <com.android.settingslib.widget.FooterPreference
diff --git a/res/xml/graphics_driver_settings.xml b/res/xml/graphics_driver_settings.xml
index bc2759f..c72c8fb 100644
--- a/res/xml/graphics_driver_settings.xml
+++ b/res/xml/graphics_driver_settings.xml
@@ -26,20 +26,20 @@
         android:dialogTitle="@string/graphics_driver_all_apps_preference_title"
         android:entries="@array/graphics_driver_all_apps_preference_values"
         android:entryValues="@array/graphics_driver_all_apps_preference_values"
-        settings:controller="com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController">
+        settings:controller="com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController">
     </ListPreference>
 
     <PreferenceCategory
         android:key="graphics_driver_category"
         android:title="@string/graphics_driver_app_preference_title"
-        settings:controller="com.android.settings.development.gamedriver.GameDriverAppPreferenceController">
+        settings:controller="com.android.settings.development.graphicsdriver.GraphicsDriverAppPreferenceController">
     </PreferenceCategory>
 
     <com.android.settingslib.widget.FooterPreference
         android:key="graphics_driver_footer"
         android:title="@string/graphics_driver_footer_text"
         android:selectable="false"
-        settings:controller="com.android.settings.development.gamedriver.GameDriverFooterPreferenceController">
+        settings:controller="com.android.settings.development.graphicsdriver.GraphicsDriverFooterPreferenceController">
     </com.android.settingslib.widget.FooterPreference>
 
 </PreferenceScreen>
diff --git a/res/xml/network_and_internet.xml b/res/xml/network_and_internet.xml
index c57c5b0..7653746 100644
--- a/res/xml/network_and_internet.xml
+++ b/res/xml/network_and_internet.xml
@@ -30,7 +30,7 @@
 
     <com.android.settings.widget.MasterSwitchPreference
         android:fragment="com.android.settings.wifi.WifiSettings"
-        android:key="toggle_wifi"
+        android:key="main_toggle_wifi"
         android:title="@string/wifi_settings"
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_settings_wireless"
diff --git a/res/xml/notification_access_settings.xml b/res/xml/notification_access_settings.xml
index ca84f1b..43f7c49 100644
--- a/res/xml/notification_access_settings.xml
+++ b/res/xml/notification_access_settings.xml
@@ -18,5 +18,7 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="notification_access_screen"
     android:title="@string/manage_notification_access_title"
+    settings:searchable="false"
     settings:controller="com.android.settings.applications.specialaccess.notificationaccess.NotificationAccessScreenPreferenceController" />
diff --git a/res/xml/picture_in_picture_settings.xml b/res/xml/picture_in_picture_settings.xml
index 1f08246..c9e3a3f 100644
--- a/res/xml/picture_in_picture_settings.xml
+++ b/res/xml/picture_in_picture_settings.xml
@@ -18,5 +18,7 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="picture_in_picture_screen"
     android:title="@string/picture_in_picture_title"
+    settings:searchable="false"
     settings:controller="com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureScreenPreferenceController" />
diff --git a/res/xml/premium_sms_settings.xml b/res/xml/premium_sms_settings.xml
index 82aece3..ede6057 100644
--- a/res/xml/premium_sms_settings.xml
+++ b/res/xml/premium_sms_settings.xml
@@ -18,5 +18,7 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="premium_sms_screen"
     android:title="@string/premium_sms_access"
+    settings:searchable="false"
     settings:controller="com.android.settings.applications.specialaccess.premiumsms.PremiumSmsScreenPreferenceController" />
diff --git a/res/xml/trust_agent_settings.xml b/res/xml/trust_agent_settings.xml
index 88837b8..25b3139 100644
--- a/res/xml/trust_agent_settings.xml
+++ b/res/xml/trust_agent_settings.xml
@@ -17,6 +17,8 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="trust_agents"
     android:title="@string/manage_trust_agents"
+    settings:searchable="false"
     settings:controller="com.android.settings.security.trustagent.TrustAgentsPreferenceController">
 </PreferenceScreen>
diff --git a/res/xml/unrestricted_data_access_settings.xml b/res/xml/unrestricted_data_access_settings.xml
index baefa65..d0d33b8 100644
--- a/res/xml/unrestricted_data_access_settings.xml
+++ b/res/xml/unrestricted_data_access_settings.xml
@@ -18,6 +18,8 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="unrestricted_data_screen"
     android:title="@string/unrestricted_data_saver"
-    settings:controller="com.android.settings.datausage.UnrestrictedDataAccessPreferenceController">
+    settings:controller="com.android.settings.datausage.UnrestrictedDataAccessPreferenceController"
+    settings:searchable="false">
 </PreferenceScreen>
diff --git a/res/xml/user_dictionary_list_fragment.xml b/res/xml/user_dictionary_list_fragment.xml
index 2f921a0..2565a1a 100644
--- a/res/xml/user_dictionary_list_fragment.xml
+++ b/res/xml/user_dictionary_list_fragment.xml
@@ -17,7 +17,9 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="user_dict_list"
     android:title="@string/user_dict_settings_title"
+    settings:searchable="false"
     settings:controller="com.android.settings.inputmethod.UserDictionaryListPreferenceController">
 
 </PreferenceScreen>
diff --git a/res/xml/vr_listeners_settings.xml b/res/xml/vr_listeners_settings.xml
index a35b987..d9b364c 100644
--- a/res/xml/vr_listeners_settings.xml
+++ b/res/xml/vr_listeners_settings.xml
@@ -18,5 +18,7 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="vr_listener_settings"
     android:title="@string/vr_listeners_title"
+    settings:searchable="false"
     settings:controller="com.android.settings.applications.specialaccess.vrlistener.VrListenerScreenPreferenceController" />
diff --git a/src/com/android/settings/AllInOneTetherSettings.java b/src/com/android/settings/AllInOneTetherSettings.java
index f2a0f52..4576fb7 100644
--- a/src/com/android/settings/AllInOneTetherSettings.java
+++ b/src/com/android/settings/AllInOneTetherSettings.java
@@ -46,7 +46,10 @@
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.datausage.DataSaverBackend;
+import com.android.settings.network.BluetoothTetherPreferenceController;
 import com.android.settings.network.TetherEnabler;
+import com.android.settings.network.UsbTetherPreferenceController;
+import com.android.settings.network.WifiTetherDisablePreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.SwitchBar;
 import com.android.settings.widget.SwitchBarController;
@@ -66,7 +69,6 @@
 
 /**
  * Displays preferences for all Tethering options.
- * TODO(b/147323306): Add tether option preferences into this fragment after controllers created.
  */
 @SearchIndexable
 public final class AllInOneTetherSettings extends RestrictedDashboardFragment
@@ -172,6 +174,9 @@
         mSecurityPreferenceController = use(WifiTetherSecurityPreferenceController.class);
         mPasswordPreferenceController = use(WifiTetherPasswordPreferenceController.class);
         mApBandPreferenceController = use(WifiTetherApBandPreferenceController.class);
+        getSettingsLifecycle().addObserver(use(UsbTetherPreferenceController.class));
+        getSettingsLifecycle().addObserver(use(BluetoothTetherPreferenceController.class));
+        getSettingsLifecycle().addObserver(use(WifiTetherDisablePreferenceController.class));
     }
 
     @Override
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 07ba28f..80e5706 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -258,6 +258,18 @@
         return 0;
     }
 
+    /**
+     * Whether preference is allowing to be displayed to the user.
+     *
+     * @param preference to check if it can be displayed to the user (not hidding in expand area).
+     * @return {@code true} when preference is allowing to be displayed to the user.
+     * {@code false} when preference is hidden in expand area and not been displayed to the user.
+     */
+    protected boolean isPreferenceExpanded(Preference preference) {
+        return ((mAdapter == null)
+                || (mAdapter.getPreferenceAdapterPosition(preference) != RecyclerView.NO_POSITION));
+    }
+
     protected void onDataSetChanged() {
         highlightPreferenceIfNeeded();
         updateEmptyView();
diff --git a/src/com/android/settings/accessibility/ShortcutPreference.java b/src/com/android/settings/accessibility/ShortcutPreference.java
index 84ced68..2a62439 100644
--- a/src/com/android/settings/accessibility/ShortcutPreference.java
+++ b/src/com/android/settings/accessibility/ShortcutPreference.java
@@ -53,7 +53,7 @@
     }
     private OnClickListener mListener = null;
 
-    private static final float DISABLED_ALPHA = 0.5f;
+    private static final float DISABLED_ALPHA = 0.77f;
     private static final float ENABLED_ALPHA = 1.0f;
     private int mSettingsVisibility = View.VISIBLE;
     private boolean mAutoEnabledSettings;
diff --git a/src/com/android/settings/applications/AppStateAppOpsBridge.java b/src/com/android/settings/applications/AppStateAppOpsBridge.java
index 3dbdbe9..8c001d8 100755
--- a/src/com/android/settings/applications/AppStateAppOpsBridge.java
+++ b/src/com/android/settings/applications/AppStateAppOpsBridge.java
@@ -61,17 +61,27 @@
         this(context, appState, callback, appOpsOpCode, permissions,
                 AppGlobals.getPackageManager());
     }
+    AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
+            int[] appOpsOpCodes, String[] permissions) {
+        this(context, appState, callback, appOpsOpCodes, permissions,
+                AppGlobals.getPackageManager());
+    }
 
     @VisibleForTesting
     AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
             int appOpsOpCode, String[] permissions, IPackageManager packageManager) {
+        this(context, appState, callback, new int[] {appOpsOpCode}, permissions,
+                packageManager);
+    }
+    AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
+            int[] appOpsOpCodes, String[] permissions, IPackageManager packageManager) {
         super(appState, callback);
         mContext = context;
         mIPackageManager = packageManager;
         mUserManager = UserManager.get(context);
         mProfiles = mUserManager.getUserProfiles();
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
-        mAppOpsOpCodes = new int[] {appOpsOpCode};
+        mAppOpsOpCodes = appOpsOpCodes;
         mPermissions = permissions;
     }
 
diff --git a/src/com/android/settings/applications/AppStateUsageBridge.java b/src/com/android/settings/applications/AppStateUsageBridge.java
index f84ef3e..c1c861f 100644
--- a/src/com/android/settings/applications/AppStateUsageBridge.java
+++ b/src/com/android/settings/applications/AppStateUsageBridge.java
@@ -33,13 +33,20 @@
     private static final String TAG = "AppStateUsageBridge";
 
     private static final String PM_USAGE_STATS = Manifest.permission.PACKAGE_USAGE_STATS;
-    private static final int APP_OPS_OP_CODE = AppOpsManager.OP_GET_USAGE_STATS;
-    private static final String[] PM_PERMISSION = {
-            PM_USAGE_STATS
+    private static final String PM_LOADER_STATS = Manifest.permission.LOADER_USAGE_STATS;
+    private static final int APP_OPS_USAGE_STATS = AppOpsManager.OP_GET_USAGE_STATS;
+    private static final int APP_OPS_LOADER_STATS = AppOpsManager.OP_LOADER_USAGE_STATS;
+    private static final int[] APP_OPS_OP_CODES = {
+            APP_OPS_USAGE_STATS,
+            APP_OPS_LOADER_STATS,
+    };
+    private static final String[] PM_PERMISSIONS = {
+            PM_USAGE_STATS,
+            PM_LOADER_STATS,
     };
 
     public AppStateUsageBridge(Context context, ApplicationsState appState, Callback callback) {
-        super(context, appState, callback, APP_OPS_OP_CODE, PM_PERMISSION);
+        super(context, appState, callback, APP_OPS_OP_CODES, PM_PERMISSIONS);
     }
 
     @Override
diff --git a/src/com/android/settings/applications/UsageAccessDetails.java b/src/com/android/settings/applications/UsageAccessDetails.java
index 58dff7c..cddacb3 100644
--- a/src/com/android/settings/applications/UsageAccessDetails.java
+++ b/src/com/android/settings/applications/UsageAccessDetails.java
@@ -15,6 +15,10 @@
  */
 package com.android.settings.applications;
 
+import static android.app.AppOpsManager.OP_GET_USAGE_STATS;
+import static android.app.AppOpsManager.OP_LOADER_USAGE_STATS;
+
+import android.Manifest;
 import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.settings.SettingsEnums;
@@ -104,10 +108,28 @@
         return false;
     }
 
+    private static boolean doesAnyPermissionMatch(String permissionToMatch, String[] permissions) {
+        for (String permission : permissions) {
+            if (permissionToMatch.equals(permission)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void setHasAccess(boolean newState) {
         logSpecialPermissionChange(newState, mPackageName);
-        mAppOpsManager.setMode(AppOpsManager.OP_GET_USAGE_STATS, mPackageInfo.applicationInfo.uid,
-                mPackageName, newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
+
+        final int newAppOpMode = newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
+        final int uid = mPackageInfo.applicationInfo.uid;
+        if (doesAnyPermissionMatch(Manifest.permission.PACKAGE_USAGE_STATS,
+                mUsageState.packageInfo.requestedPermissions)) {
+            mAppOpsManager.setMode(OP_GET_USAGE_STATS, uid, mPackageName, newAppOpMode);
+        }
+        if (doesAnyPermissionMatch(Manifest.permission.LOADER_USAGE_STATS,
+                mUsageState.packageInfo.requestedPermissions)) {
+            mAppOpsManager.setMode(OP_LOADER_USAGE_STATS, uid, mPackageName, newAppOpMode);
+        }
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 0d3d5b0..d121195 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -320,6 +320,13 @@
     }
 
     /**
+     * Get current PreferenceController(s)
+     */
+    protected Collection<List<AbstractPreferenceController>> getPreferenceControllers() {
+        return mPreferenceControllers.values();
+    }
+
+    /**
      * Update state of each preference managed by PreferenceController.
      */
     protected void updatePreferenceStates() {
diff --git a/src/com/android/settings/development/MockLocationAppPreferenceController.java b/src/com/android/settings/development/MockLocationAppPreferenceController.java
index 45d6be8..4803843 100644
--- a/src/com/android/settings/development/MockLocationAppPreferenceController.java
+++ b/src/com/android/settings/development/MockLocationAppPreferenceController.java
@@ -27,6 +27,7 @@
 import android.content.pm.PackageManager;
 import android.text.TextUtils;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
 import com.android.settings.R;
@@ -86,6 +87,12 @@
         return true;
     }
 
+    @Override
+    public void onDeveloperOptionsDisabled() {
+        super.onDeveloperOptionsDisabled();
+        removeAllMockLocations();
+    }
+
     private void updateMockLocation() {
         final String mockLocationApp = getCurrentMockLocationApp();
 
@@ -151,7 +158,8 @@
         }
     }
 
-    private String getCurrentMockLocationApp() {
+    @VisibleForTesting
+    String getCurrentMockLocationApp() {
         final List<AppOpsManager.PackageOps> packageOps = mAppsOpsManager.getPackagesForOps(
                 MOCK_LOCATION_APP_OPS);
         if (packageOps != null) {
diff --git a/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceController.java
similarity index 88%
rename from src/com/android/settings/development/gamedriver/GameDriverAppPreferenceController.java
rename to src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceController.java
index d6bdb54..c1376a8 100644
--- a/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceController.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
 
 import android.content.ContentResolver;
 import android.content.Context;
@@ -53,9 +53,9 @@
 /**
  * Controller of all the per App based list preferences.
  */
-public class GameDriverAppPreferenceController extends BasePreferenceController
+public class GraphicsDriverAppPreferenceController extends BasePreferenceController
         implements Preference.OnPreferenceChangeListener,
-        GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
+        GraphicsDriverContentObserver.OnGraphicsDriverContentChangedListener, LifecycleObserver,
         OnStart, OnStop {
 
     private final Context mContext;
@@ -67,7 +67,7 @@
     private final String mPreferencePrereleaseDriver;
     private final String mPreferenceSystem;
     @VisibleForTesting
-    GameDriverContentObserver mGameDriverContentObserver;
+    GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     private final List<AppInfo> mAppInfos;
     private final Set<String> mDevOptInApps;
@@ -76,13 +76,13 @@
 
     private PreferenceGroup mPreferenceGroup;
 
-    public GameDriverAppPreferenceController(Context context, String key) {
+    public GraphicsDriverAppPreferenceController(Context context, String key) {
         super(context, key);
 
         mContext = context;
         mContentResolver = context.getContentResolver();
-        mGameDriverContentObserver =
-                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
+        mGraphicsDriverContentObserver =
+                new GraphicsDriverContentObserver(new Handler(Looper.getMainLooper()), this);
 
         final Resources resources = context.getResources();
         mEntryList = resources.getStringArray(R.array.graphics_driver_app_preference_values);
@@ -130,12 +130,12 @@
 
     @Override
     public void onStart() {
-        mGameDriverContentObserver.register(mContentResolver);
+        mGraphicsDriverContentObserver.register(mContentResolver);
     }
 
     @Override
     public void onStop() {
-        mGameDriverContentObserver.unregister(mContentResolver);
+        mGraphicsDriverContentObserver.unregister(mContentResolver);
     }
 
     @Override
@@ -185,7 +185,7 @@
     }
 
     @Override
-    public void onGameDriverContentChanged() {
+    public void onGraphicsDriverContentChanged() {
         updateState(mPreferenceGroup);
     }
 
@@ -196,8 +196,8 @@
             label = packageManager.getApplicationLabel(applicationInfo).toString();
         }
 
-        final ApplicationInfo info;
-        final String label;
+        public final ApplicationInfo info;
+        public final String label;
     }
 
     // List of non-system packages that are installed for the current user.
@@ -213,7 +213,7 @@
             }
         }
 
-        Collections.sort(appInfos, appInfoComparator);
+        Collections.sort(appInfos, mAppInfoComparator);
 
         return appInfos;
     }
@@ -231,8 +231,8 @@
         return valueSet;
     }
 
-    private final Comparator<AppInfo> appInfoComparator = new Comparator<AppInfo>() {
-        public final int compare(AppInfo a, AppInfo b) {
+    private final Comparator<AppInfo> mAppInfoComparator = new Comparator<AppInfo>() {
+        public int compare(AppInfo a, AppInfo b) {
             return Collator.getInstance().compare(a.label, b.label);
         }
     };
diff --git a/src/com/android/settings/development/gamedriver/GameDriverContentObserver.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverContentObserver.java
similarity index 66%
rename from src/com/android/settings/development/gamedriver/GameDriverContentObserver.java
rename to src/com/android/settings/development/graphicsdriver/GraphicsDriverContentObserver.java
index e31e046..8317800 100644
--- a/src/com/android/settings/development/gamedriver/GameDriverContentObserver.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverContentObserver.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
 import android.content.ContentResolver;
 import android.database.ContentObserver;
@@ -24,18 +24,19 @@
 import androidx.annotation.VisibleForTesting;
 
 /**
- * Helper class to observe Game Driver settings global change.
+ * Helper class to observe Graphics Driver settings global change.
  */
-public class GameDriverContentObserver extends ContentObserver {
+public class GraphicsDriverContentObserver extends ContentObserver {
 
-    interface OnGameDriverContentChangedListener {
-        void onGameDriverContentChanged();
+    interface OnGraphicsDriverContentChangedListener {
+        void onGraphicsDriverContentChanged();
     }
 
     @VisibleForTesting
-    OnGameDriverContentChangedListener mListener;
+    OnGraphicsDriverContentChangedListener mListener;
 
-    public GameDriverContentObserver(Handler handler, OnGameDriverContentChangedListener listener) {
+    public GraphicsDriverContentObserver(Handler handler,
+            OnGraphicsDriverContentChangedListener listener) {
         super(handler);
         mListener = listener;
     }
@@ -43,14 +44,20 @@
     @Override
     public void onChange(boolean selfChange) {
         super.onChange(selfChange);
-        mListener.onGameDriverContentChanged();
+        mListener.onGraphicsDriverContentChanged();
     }
 
+    /**
+     * Register GraphicsDriverContentObserver to ContentResolver.
+     */
     public void register(ContentResolver contentResolver) {
         contentResolver.registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_ALL_APPS), false, this);
     }
 
+    /**
+     * Unregister GraphicsDriverContentObserver.
+     */
     public void unregister(ContentResolver contentResolver) {
         contentResolver.unregisterContentObserver(this);
     }
diff --git a/src/com/android/settings/development/gamedriver/GameDriverDashboard.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverDashboard.java
similarity index 87%
rename from src/com/android/settings/development/gamedriver/GameDriverDashboard.java
rename to src/com/android/settings/development/graphicsdriver/GraphicsDriverDashboard.java
index 4ef0a87..2801689 100644
--- a/src/com/android/settings/development/gamedriver/GameDriverDashboard.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverDashboard.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
@@ -33,9 +33,9 @@
  * Dashboard for Game Driver preferences.
  */
 @SearchIndexable
-public class GameDriverDashboard extends DashboardFragment {
+public class GraphicsDriverDashboard extends DashboardFragment {
 
-    private static final String TAG = "GameDriverDashboard";
+    private static final String TAG = "GraphicsDriverDashboard";
 
     @Override
     public int getMetricsCategory() {
@@ -63,8 +63,8 @@
 
         final SettingsActivity activity = (SettingsActivity) getActivity();
         final SwitchBar switchBar = activity.getSwitchBar();
-        final GameDriverGlobalSwitchBarController switchBarController =
-                new GameDriverGlobalSwitchBarController(
+        final GraphicsDriverGlobalSwitchBarController switchBarController =
+                new GraphicsDriverGlobalSwitchBarController(
                         activity, new SwitchBarController(switchBar));
         getSettingsLifecycle().addObserver(switchBarController);
         switchBar.show();
diff --git a/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceController.java
similarity index 86%
rename from src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceController.java
rename to src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceController.java
index 9c816c5..4baa993 100644
--- a/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
 import android.content.ContentResolver;
 import android.content.Context;
@@ -38,10 +38,10 @@
 /**
  * Controller of global switch to enable Game Driver for all Apps.
  */
-public class GameDriverEnableForAllAppsPreferenceController extends BasePreferenceController
+public class GraphicsDriverEnableForAllAppsPreferenceController extends BasePreferenceController
         implements Preference.OnPreferenceChangeListener,
-                   GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
-                   OnStart, OnStop {
+                   GraphicsDriverContentObserver.OnGraphicsDriverContentChangedListener,
+                   LifecycleObserver, OnStart, OnStop {
 
     public static final int GAME_DRIVER_DEFAULT = 0;
     public static final int GAME_DRIVER_ALL_APPS = 1;
@@ -54,11 +54,11 @@
     private final String mPreferenceGameDriver;
     private final String mPreferencePrereleaseDriver;
     @VisibleForTesting
-    GameDriverContentObserver mGameDriverContentObserver;
+    GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     private ListPreference mPreference;
 
-    public GameDriverEnableForAllAppsPreferenceController(Context context, String key) {
+    public GraphicsDriverEnableForAllAppsPreferenceController(Context context, String key) {
         super(context, key);
         mContext = context;
         mContentResolver = context.getContentResolver();
@@ -69,8 +69,8 @@
                 resources.getString(R.string.graphics_driver_app_preference_game_driver);
         mPreferencePrereleaseDriver =
                 resources.getString(R.string.graphics_driver_app_preference_prerelease_driver);
-        mGameDriverContentObserver =
-                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
+        mGraphicsDriverContentObserver =
+                new GraphicsDriverContentObserver(new Handler(Looper.getMainLooper()), this);
     }
 
     @Override
@@ -92,12 +92,12 @@
 
     @Override
     public void onStart() {
-        mGameDriverContentObserver.register(mContentResolver);
+        mGraphicsDriverContentObserver.register(mContentResolver);
     }
 
     @Override
     public void onStop() {
-        mGameDriverContentObserver.unregister(mContentResolver);
+        mGraphicsDriverContentObserver.unregister(mContentResolver);
     }
 
     @Override
@@ -144,7 +144,7 @@
     }
 
     @Override
-    public void onGameDriverContentChanged() {
+    public void onGraphicsDriverContentChanged() {
         updateState(mPreference);
     }
 }
diff --git a/src/com/android/settings/development/gamedriver/GameDriverFooterPreferenceController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverFooterPreferenceController.java
similarity index 65%
rename from src/com/android/settings/development/gamedriver/GameDriverFooterPreferenceController.java
rename to src/com/android/settings/development/graphicsdriver/GraphicsDriverFooterPreferenceController.java
index 1ad476b..e368aab 100644
--- a/src/com/android/settings/development/gamedriver/GameDriverFooterPreferenceController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverFooterPreferenceController.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
 
 import android.content.ContentResolver;
 import android.content.Context;
@@ -35,23 +35,23 @@
 import com.android.settingslib.widget.FooterPreference;
 
 /**
- * Controller of footer preference for Game Driver.
+ * Controller of footer preference for Graphics Driver Preferences dashboard.
  */
-public class GameDriverFooterPreferenceController extends BasePreferenceController
-        implements GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
-        OnStart, OnStop {
+public class GraphicsDriverFooterPreferenceController extends BasePreferenceController
+        implements GraphicsDriverContentObserver.OnGraphicsDriverContentChangedListener,
+        LifecycleObserver, OnStart, OnStop {
 
     private final ContentResolver mContentResolver;
     @VisibleForTesting
-    GameDriverContentObserver mGameDriverContentObserver;
+    GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     private FooterPreference mPreference;
 
-    public GameDriverFooterPreferenceController(Context context, String key) {
+    public GraphicsDriverFooterPreferenceController(Context context, String key) {
         super(context, key);
         mContentResolver = context.getContentResolver();
-        mGameDriverContentObserver =
-                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
+        mGraphicsDriverContentObserver =
+                new GraphicsDriverContentObserver(new Handler(Looper.getMainLooper()), this);
     }
 
     @Override
@@ -71,16 +71,16 @@
 
     @Override
     public void onStart() {
-        mGameDriverContentObserver.register(mContentResolver);
+        mGraphicsDriverContentObserver.register(mContentResolver);
     }
 
     @Override
     public void onStop() {
-        mGameDriverContentObserver.unregister(mContentResolver);
+        mGraphicsDriverContentObserver.unregister(mContentResolver);
     }
 
     @Override
-    public void onGameDriverContentChanged() {
+    public void onGraphicsDriverContentChanged() {
         updateState(mPreference);
     }
 }
diff --git a/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverGlobalSwitchBarController.java
similarity index 64%
rename from src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarController.java
rename to src/com/android/settings/development/graphicsdriver/GraphicsDriverGlobalSwitchBarController.java
index 15f71e0..86c56b7 100644
--- a/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverGlobalSwitchBarController.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_ALL_APPS;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_PRERELEASE_ALL_APPS;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_ALL_APPS;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_PRERELEASE_ALL_APPS;
 
 import android.content.ContentResolver;
 import android.content.Context;
@@ -38,24 +38,24 @@
 /**
  * Controller of global switch bar used to fully turn off Game Driver.
  */
-public class GameDriverGlobalSwitchBarController
+public class GraphicsDriverGlobalSwitchBarController
         implements SwitchWidgetController.OnSwitchChangeListener,
-                   GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
-                   OnStart, OnStop {
+                   GraphicsDriverContentObserver.OnGraphicsDriverContentChangedListener,
+                   LifecycleObserver, OnStart, OnStop {
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
     @VisibleForTesting
     SwitchWidgetController mSwitchWidgetController;
     @VisibleForTesting
-    GameDriverContentObserver mGameDriverContentObserver;
+    GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
-    GameDriverGlobalSwitchBarController(
+    GraphicsDriverGlobalSwitchBarController(
             Context context, SwitchWidgetController switchWidgetController) {
         mContext = context;
         mContentResolver = context.getContentResolver();
-        mGameDriverContentObserver =
-                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
+        mGraphicsDriverContentObserver =
+                new GraphicsDriverContentObserver(new Handler(Looper.getMainLooper()), this);
         mSwitchWidgetController = switchWidgetController;
         mSwitchWidgetController.setEnabled(
                 DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context));
@@ -69,27 +69,28 @@
     @Override
     public void onStart() {
         mSwitchWidgetController.startListening();
-        mGameDriverContentObserver.register(mContentResolver);
+        mGraphicsDriverContentObserver.register(mContentResolver);
     }
 
     @Override
     public void onStop() {
         mSwitchWidgetController.stopListening();
-        mGameDriverContentObserver.unregister(mContentResolver);
+        mGraphicsDriverContentObserver.unregister(mContentResolver);
     }
 
     @Override
     public boolean onSwitchToggled(boolean isChecked) {
-        final int gameDriver = Settings.Global.getInt(
+        final int graphicsDriverGlobalOption = Settings.Global.getInt(
                 mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT);
 
         if (isChecked
-                && (gameDriver == GAME_DRIVER_DEFAULT || gameDriver == GAME_DRIVER_ALL_APPS
-                        || gameDriver == GAME_DRIVER_PRERELEASE_ALL_APPS)) {
+                && (graphicsDriverGlobalOption == GAME_DRIVER_DEFAULT
+                        || graphicsDriverGlobalOption == GAME_DRIVER_ALL_APPS
+                        || graphicsDriverGlobalOption == GAME_DRIVER_PRERELEASE_ALL_APPS)) {
             return true;
         }
 
-        if (!isChecked && gameDriver == GAME_DRIVER_OFF) {
+        if (!isChecked && graphicsDriverGlobalOption == GAME_DRIVER_OFF) {
             return true;
         }
 
@@ -100,7 +101,7 @@
     }
 
     @Override
-    public void onGameDriverContentChanged() {
+    public void onGraphicsDriverContentChanged() {
         mSwitchWidgetController.setChecked(
                 Settings.Global.getInt(
                         mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT)
diff --git a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
index b736b79..7f85f7d 100644
--- a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
+++ b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
@@ -13,7 +13,7 @@
  */
 package com.android.settings.display;
 
-import static android.provider.Settings.System.ADAPTIVE_SLEEP;
+import static android.provider.Settings.Secure.ADAPTIVE_SLEEP;
 
 import android.Manifest;
 import android.content.Context;
diff --git a/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java b/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java
index c477abc..c94469a 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java
@@ -129,7 +129,7 @@
      */
     private boolean isTurnedOn() {
         return Settings.System.getInt(
-                mContext.getContentResolver(), Settings.System.ADAPTIVE_SLEEP, 0) != 0;
+                mContext.getContentResolver(), Settings.Secure.ADAPTIVE_SLEEP, 0) != 0;
     }
 
     /**
diff --git a/src/com/android/settings/media/MediaDeviceUpdateWorker.java b/src/com/android/settings/media/MediaDeviceUpdateWorker.java
index 2d9a736..20f1150 100644
--- a/src/com/android/settings/media/MediaDeviceUpdateWorker.java
+++ b/src/com/android/settings/media/MediaDeviceUpdateWorker.java
@@ -147,6 +147,17 @@
     }
 
     /**
+     * Find the active MediaDevice.
+     *
+     * @param type the media device type.
+     * @return MediaDevice list
+     *
+     */
+    public List<MediaDevice> getActiveMediaDevice(@MediaDevice.MediaDeviceType int type) {
+        return mLocalMediaManager.getActiveMediaDevice(type);
+    }
+
+    /**
      * Request to set volume.
      *
      * @param device for the targeted device.
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index 8e6da80..3c9999e 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -104,7 +104,7 @@
     }
 
     private void addRow(MediaDevice device, MediaDevice connectedDevice, ListBuilder listBuilder) {
-        if (TextUtils.equals(device.getId(), connectedDevice.getId())) {
+        if (connectedDevice != null && TextUtils.equals(device.getId(), connectedDevice.getId())) {
             listBuilder.addInputRange(getActiveDeviceHeaderRow(device));
         } else {
             listBuilder.addRow(getMediaDeviceRow(device));
diff --git a/src/com/android/settings/media/RemoteMediaSlice.java b/src/com/android/settings/media/RemoteMediaSlice.java
new file mode 100644
index 0000000..55b3e2c
--- /dev/null
+++ b/src/com/android/settings/media/RemoteMediaSlice.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.media;
+
+import static android.app.slice.Slice.EXTRA_RANGE_VALUE;
+
+import static com.android.settings.slices.CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.ListBuilder.InputRangeBuilder;
+import androidx.slice.builders.SliceAction;
+
+import com.android.settings.R;
+import com.android.settings.SubSettings;
+import com.android.settings.notification.SoundSettings;
+import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settings.slices.SliceBroadcastReceiver;
+import com.android.settings.slices.SliceBuilderUtils;
+import com.android.settingslib.media.MediaDevice;
+import com.android.settingslib.media.MediaOutputSliceConstants;
+
+import java.util.List;
+
+/**
+ * Display the Remote Media device information.
+ */
+public class RemoteMediaSlice implements CustomSliceable {
+
+    private static final String TAG = "RemoteMediaSlice";
+    private static final String MEDIA_ID = "media_id";
+
+    private final Context mContext;
+
+    private MediaDeviceUpdateWorker mWorker;
+
+    public RemoteMediaSlice(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public void onNotifyChange(Intent intent) {
+        final int newPosition = intent.getIntExtra(EXTRA_RANGE_VALUE, -1);
+        final String id = intent.getStringExtra(MEDIA_ID);
+        if (!TextUtils.isEmpty(id)) {
+            getWorker().adjustVolume(getWorker().getMediaDeviceById(id), newPosition);
+        }
+    }
+
+    @Override
+    public Slice getSlice() {
+        final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
+                .setAccentColor(COLOR_NOT_TINTED);
+        if (getWorker() == null) {
+            Log.e(TAG, "Unable to get the slice worker.");
+            return listBuilder.build();
+        }
+        // Only displaying remote devices
+        final List<MediaDevice> mediaDevices = getWorker().getActiveMediaDevice(
+                MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE);
+        if (mediaDevices.isEmpty()) {
+            Log.d(TAG, "No active remote media device");
+            return listBuilder.build();
+        }
+        final CharSequence castVolume = mContext.getText(R.string.remote_media_volume_option_title);
+        final CharSequence outputTitle = mContext.getText(R.string.media_output_title);
+        final IconCompat icon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_volume_remote);
+        // To create an empty icon to indent the row
+        final IconCompat emptyIcon = createEmptyIcon();
+        int requestCode = 0;
+        for (MediaDevice mediaDevice : mediaDevices) {
+            final int maxVolume = mediaDevice.getMaxVolume();
+            if (maxVolume <= 0) {
+                Log.d(TAG, "Unable to add Slice. " + mediaDevice.getName() + ": max volume is "
+                        + maxVolume);
+                continue;
+            }
+            final String title = castVolume + " (" + mediaDevice.getClientAppLabel() + ")";
+            listBuilder.addInputRange(new InputRangeBuilder()
+                    .setTitleItem(icon, ListBuilder.ICON_IMAGE)
+                    .setTitle(title)
+                    .setInputAction(getSliderInputAction(requestCode++, mediaDevice.getId()))
+                    .setPrimaryAction(getSoundSettingAction(title, icon, mediaDevice.getId()))
+                    .setMax(maxVolume)
+                    .setValue(mediaDevice.getCurrentVolume()));
+            listBuilder.addRow(new ListBuilder.RowBuilder()
+                    .setTitle(outputTitle)
+                    .setSubtitle(mediaDevice.getName())
+                    .setTitleItem(emptyIcon, ListBuilder.ICON_IMAGE)
+                    .setPrimaryAction(getMediaOutputSliceAction()));
+        }
+        return listBuilder.build();
+    }
+
+    private IconCompat createEmptyIcon() {
+        final Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+        return IconCompat.createWithBitmap(bitmap);
+    }
+
+    private PendingIntent getSliderInputAction(int requestCode, String id) {
+        final Intent intent = new Intent(getUri().toString())
+                .setData(getUri())
+                .putExtra(MEDIA_ID, id)
+                .setClass(mContext, SliceBroadcastReceiver.class);
+        return PendingIntent.getBroadcast(mContext, requestCode, intent, 0);
+    }
+
+    private SliceAction getSoundSettingAction(String actionTitle, IconCompat icon, String id) {
+        final Uri contentUri = new Uri.Builder().appendPath(id).build();
+        final Intent intent = SliceBuilderUtils.buildSearchResultPageIntent(mContext,
+                SoundSettings.class.getName(),
+                id,
+                mContext.getText(R.string.sound_settings).toString(), 0);
+        intent.setClassName(mContext.getPackageName(), SubSettings.class.getName());
+        intent.setData(contentUri);
+        final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(pendingIntent, icon,
+                ListBuilder.ICON_IMAGE, actionTitle);
+        return primarySliceAction;
+    }
+
+    private SliceAction getMediaOutputSliceAction() {
+        final Intent intent = new Intent()
+                .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        final IconCompat icon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_volume_remote);
+        final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext,
+                0 /* requestCode */, intent, 0 /* flags */);
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(
+                primaryActionIntent, icon, ListBuilder.ICON_IMAGE,
+                mContext.getText(R.string.media_output_title));
+        return primarySliceAction;
+    }
+
+    @Override
+    public Uri getUri() {
+        return REMOTE_MEDIA_SLICE_URI;
+    }
+
+    @Override
+    public Intent getIntent() {
+        return null;
+    }
+
+    @Override
+    public Class getBackgroundWorkerClass() {
+        return MediaDeviceUpdateWorker.class;
+    }
+
+    private MediaDeviceUpdateWorker getWorker() {
+        if (mWorker == null) {
+            mWorker = SliceBackgroundWorker.getInstance(getUri());
+        }
+        return mWorker;
+    }
+}
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index 2bc97e6..71d7066 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -150,13 +150,5 @@
                             null /* metricsFeatureProvider */, null /* fragment */,
                             null /* mobilePlanHost */);
                 }
-
-                @Override
-                public List<String> getNonIndexableKeys(Context context) {
-                    List<String> keys = super.getNonIndexableKeys(context);
-                    // Remove master switch as a result
-                    keys.add(WifiMasterSwitchPreferenceController.KEY_TOGGLE_WIFI);
-                    return keys;
-                }
             };
 }
diff --git a/src/com/android/settings/network/WifiTetherDisablePreferenceController.java b/src/com/android/settings/network/WifiTetherDisablePreferenceController.java
index a7242cf..32f841d 100644
--- a/src/com/android/settings/network/WifiTetherDisablePreferenceController.java
+++ b/src/com/android/settings/network/WifiTetherDisablePreferenceController.java
@@ -30,6 +30,7 @@
 import androidx.preference.SwitchPreference;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.TetherUtil;
 
@@ -95,8 +96,14 @@
 
     @Override
     public CharSequence getSummary() {
-        // TODO(b/146818850): Update summary accordingly.
-        return super.getSummary();
+        if (mUSBTetherEnabled && mBluetoothTetherEnabled) {
+            return mContext.getString(R.string.disable_wifi_hotspot_when_usb_and_bluetooth_on);
+        } else if (mUSBTetherEnabled) {
+            return mContext.getString(R.string.disable_wifi_hotspot_when_usb_on);
+        } else if (mBluetoothTetherEnabled) {
+            return mContext.getString(R.string.disable_wifi_hotspot_when_bluetooth_on);
+        }
+        return mContext.getString(R.string.summary_placeholder);
     }
 
     @Override
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index a4b32e6..199564d 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -33,6 +33,7 @@
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
@@ -47,7 +48,9 @@
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
@@ -72,6 +75,8 @@
     private UserManager mUserManager;
     private String mClickedPrefKey;
 
+    private List<AbstractPreferenceController> mHiddenControllerList;
+
     public MobileNetworkSettings() {
         super(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
     }
@@ -113,12 +118,12 @@
                 MobileNetworkUtils.getSearchableSubscriptionId(context));
         Log.i(LOG_TAG, "display subId: " + mSubId);
 
-        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            return Arrays.asList(
-                    new DataUsageSummaryPreferenceController(getActivity(), getSettingsLifecycle(),
-                            this, mSubId));
+        if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
+            return Arrays.asList();
         }
-        return Arrays.asList();
+        return Arrays.asList(
+                new DataUsageSummaryPreferenceController(getActivity(), getSettingsLifecycle(),
+                        this, mSubId));
     }
 
     @Override
@@ -187,6 +192,50 @@
         onRestoreInstance(icicle);
     }
 
+    @Override
+    public void onExpandButtonClick() {
+        final PreferenceScreen screen = getPreferenceScreen();
+        mHiddenControllerList.stream()
+                .filter(controller -> controller.isAvailable())
+                .forEach(controller -> {
+                    final String key = controller.getPreferenceKey();
+                    final Preference preference = screen.findPreference(key);
+                    controller.updateState(preference);
+                });
+        super.onExpandButtonClick();
+    }
+
+    /*
+     * Replace design within {@link DashboardFragment#updatePreferenceStates()}
+     */
+    @Override
+    protected void updatePreferenceStates() {
+        mHiddenControllerList = new ArrayList<AbstractPreferenceController>();
+
+        final PreferenceScreen screen = getPreferenceScreen();
+        final Collection<List<AbstractPreferenceController>> controllerLists =
+                getPreferenceControllers();
+        controllerLists.stream().flatMap(Collection::stream)
+                .forEach(controller -> {
+                    final String key = controller.getPreferenceKey();
+                    if (TextUtils.isEmpty(key)) {
+                        return;
+                    }
+                    final Preference preference = screen.findPreference(key);
+                    if (preference == null) {
+                        return;
+                    }
+                    if (!isPreferenceExpanded(preference)) {
+                        mHiddenControllerList.add(controller);
+                        return;
+                    }
+                    if (!controller.isAvailable()) {
+                        return;
+                    }
+                    controller.updateState(preference);
+                });
+    }
+
     @VisibleForTesting
     void onRestoreInstance(Bundle icicle) {
         if (icicle != null) {
@@ -238,7 +287,7 @@
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
             final MenuItem item = menu.add(Menu.NONE, R.id.edit_sim_name, Menu.NONE,
                     R.string.mobile_network_sim_name);
             item.setIcon(com.android.internal.R.drawable.ic_mode_edit);
@@ -249,7 +298,7 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem menuItem) {
-        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
             if (menuItem.getItemId() == R.id.edit_sim_name) {
                 RenameMobileNetworkDialogFragment.newInstance(mSubId).show(
                         getFragmentManager(), RenameMobileNetworkDialogFragment.TAG);
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index 875a804..4f62f7f 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -18,6 +18,15 @@
 
 import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
 
+import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA;
+import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.EVDO;
+import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM;
+import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.LTE;
+import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.NR;
+import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA;
+import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_UNKNOWN;
+import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -54,6 +63,7 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.network.ims.WifiCallingQueryImsState;
 import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.graph.SignalDrawable;
@@ -61,15 +71,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA;
-import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.EVDO;
-import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM;
-import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.LTE;
-import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.NR;
-import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA;
-import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_UNKNOWN;
-import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA;
-
 public class MobileNetworkUtils {
 
     private static final String TAG = "MobileNetworkUtils";
@@ -152,10 +153,10 @@
 
             isWifiCallingEnabled = intent != null;
         } else {
+            final WifiCallingQueryImsState queryState =
+                    new WifiCallingQueryImsState(context, subId);
             final ImsManager imsMgr = ImsManager.getInstance(context, phoneId);
-            isWifiCallingEnabled = imsMgr != null
-                    && imsMgr.isWfcEnabledByPlatform()
-                    && isWfcProvisionedOnDevice(subId)
+            isWifiCallingEnabled = queryState.isWifiCallingProvisioned()
                     && isImsServiceStateReady(imsMgr);
         }
 
diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.java b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
index 08fe323..2e116d8 100644
--- a/src/com/android/settings/network/telephony/RoamingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
@@ -22,7 +22,6 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
@@ -111,20 +110,10 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
-            if (isDialogNeeded()) {
-                showDialog();
-            }
-            return true;
-        }
-
-        return false;
-    }
-
-    @Override
     public boolean setChecked(boolean isChecked) {
-        if (!isDialogNeeded()) {
+        if (isDialogNeeded()) {
+            showDialog();
+        } else {
             // Update data directly if we don't need dialog
             mTelephonyManager.setDataRoamingEnabled(isChecked);
             return true;
diff --git a/src/com/android/settings/notification/history/NotificationHistoryActivity.java b/src/com/android/settings/notification/history/NotificationHistoryActivity.java
index 7bd345f..a02d3aa 100644
--- a/src/com/android/settings/notification/history/NotificationHistoryActivity.java
+++ b/src/com/android/settings/notification/history/NotificationHistoryActivity.java
@@ -77,12 +77,18 @@
             final View container = viewForPackage.findViewById(R.id.list_container);
             container.setVisibility(View.GONE);
             ImageButton expand = viewForPackage.findViewById(R.id.expand);
+            expand.setContentDescription(container.getVisibility() == View.VISIBLE
+                    ? getString(R.string.condition_expand_hide)
+                    : getString(R.string.condition_expand_show));
             expand.setOnClickListener(v -> {
                     container.setVisibility(container.getVisibility() == View.VISIBLE
                             ? View.GONE : View.VISIBLE);
                     expand.setImageResource(container.getVisibility() == View.VISIBLE
                             ? R.drawable.ic_expand_less
                             : com.android.internal.R.drawable.ic_expand_more);
+                    expand.setContentDescription(container.getVisibility() == View.VISIBLE
+                            ? getString(R.string.condition_expand_hide)
+                            : getString(R.string.condition_expand_show));
             });
 
             TextView label = viewForPackage.findViewById(R.id.label);
diff --git a/src/com/android/settings/notification/history/NotificationHistoryViewHolder.java b/src/com/android/settings/notification/history/NotificationHistoryViewHolder.java
index 35f5615..e7caa6a 100644
--- a/src/com/android/settings/notification/history/NotificationHistoryViewHolder.java
+++ b/src/com/android/settings/notification/history/NotificationHistoryViewHolder.java
@@ -26,6 +26,9 @@
 import android.widget.DateTimeView;
 import android.widget.TextView;
 
+import androidx.core.view.AccessibilityDelegateCompat;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settings.R;
@@ -66,5 +69,18 @@
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             itemView.getContext().startActivityAsUser(intent, UserHandle.of(userId));
         });
+        ViewCompat.setAccessibilityDelegate(itemView, new AccessibilityDelegateCompat() {
+            @Override
+            public void onInitializeAccessibilityNodeInfo(View host,
+                    AccessibilityNodeInfoCompat info) {
+                super.onInitializeAccessibilityNodeInfo(host, info);
+                CharSequence description =
+                        host.getResources().getText(R.string.notification_history_view_settings);
+                AccessibilityNodeInfoCompat.AccessibilityActionCompat customClick =
+                        new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
+                                AccessibilityNodeInfoCompat.ACTION_CLICK, description);
+                info.addAction(customClick);
+            }
+        });
     }
 }
diff --git a/src/com/android/settings/notification/history/NotificationSbnAdapter.java b/src/com/android/settings/notification/history/NotificationSbnAdapter.java
index 80ba278..77740d7 100644
--- a/src/com/android/settings/notification/history/NotificationSbnAdapter.java
+++ b/src/com/android/settings/notification/history/NotificationSbnAdapter.java
@@ -28,6 +28,7 @@
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -70,17 +71,21 @@
     public void onBindViewHolder(final @NonNull NotificationSbnViewHolder holder,
             int position) {
         final StatusBarNotification sbn = mValues.get(position);
-        holder.setIcon(loadIcon(sbn));
-        holder.setPackageName(loadPackageName(sbn.getPackageName()).toString());
-        holder.setTitle(getTitleString(sbn.getNotification()));
-        holder.setSummary(getTextString(mContext, sbn.getNotification()));
-        holder.setPostedTime(sbn.getPostTime());
-        if (!mUserBadgeCache.containsKey(sbn.getUserId())) {
-            Drawable profile = mContext.getPackageManager().getUserBadgeForDensity(
-                    UserHandle.of(sbn.getUserId()), -1);
-            mUserBadgeCache.put(sbn.getUserId(), profile);
+        if (sbn != null) {
+            holder.setIcon(loadIcon(sbn));
+            holder.setPackageName(loadPackageName(sbn.getPackageName()).toString());
+            holder.setTitle(getTitleString(sbn.getNotification()));
+            holder.setSummary(getTextString(mContext, sbn.getNotification()));
+            holder.setPostedTime(sbn.getPostTime());
+            if (!mUserBadgeCache.containsKey(sbn.getUserId())) {
+                Drawable profile = mContext.getPackageManager().getUserBadgeForDensity(
+                        UserHandle.of(sbn.getUserId()), -1);
+                mUserBadgeCache.put(sbn.getUserId(), profile);
+            }
+            holder.setProfileBadge(mUserBadgeCache.get(sbn.getUserId()));
+        } else {
+            Slog.w(TAG, "null entry in list at position " + position);
         }
-        holder.setProfileBadge(mUserBadgeCache.get(sbn.getUserId()));
     }
 
     @Override
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
index 1a166ba..61dee15 100644
--- a/src/com/android/settings/panel/VolumePanel.java
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -17,10 +17,10 @@
 package com.android.settings.panel;
 
 import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_ALARM_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_CALL_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI;
-import static com.android.settings.slices.CustomSliceRegistry.VOLUME_REMOTE_MEDIA_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_RINGER_URI;
 
 import android.app.settings.SettingsEnums;
@@ -30,7 +30,6 @@
 import android.provider.Settings;
 
 import com.android.settings.R;
-import com.android.settings.notification.RemoteVolumePreferenceController;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -55,9 +54,8 @@
     @Override
     public List<Uri> getSlices() {
         final List<Uri> uris = new ArrayList<>();
-        if (RemoteVolumePreferenceController.getActiveRemoteToken(mContext) != null) {
-            uris.add(VOLUME_REMOTE_MEDIA_URI);
-        }
+
+        uris.add(REMOTE_MEDIA_SLICE_URI);
         uris.add(VOLUME_MEDIA_URI);
         uris.add(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
         uris.add(VOLUME_CALL_URI);
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index 700fe2e..13b09ce 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -41,6 +41,7 @@
 import com.android.settings.location.LocationSlice;
 import com.android.settings.media.MediaOutputIndicatorSlice;
 import com.android.settings.media.MediaOutputSlice;
+import com.android.settings.media.RemoteMediaSlice;
 import com.android.settings.network.telephony.MobileDataSlice;
 import com.android.settings.notification.zen.ZenModeButtonPreferenceController;
 import com.android.settings.wifi.calling.WifiCallingSliceHelper;
@@ -225,16 +226,6 @@
             .build();
 
     /**
-     * Full {@link Uri} for the Remote Media Volume Slice.
-     */
-    public static final Uri VOLUME_REMOTE_MEDIA_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
-            .appendPath("remote_volume")
-            .build();
-
-    /**
      * Full {@link Uri} for the Ringer volume Slice.
      */
     public static final Uri VOLUME_RINGER_URI = new Uri.Builder()
@@ -312,6 +303,16 @@
             .appendPath("dark_theme")
             .build();
 
+    /**
+     * Backing Uri for the Remote Media Slice.
+     */
+    public static Uri REMOTE_MEDIA_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath(MediaOutputSliceConstants.KEY_REMOTE_MEDIA)
+            .build();
+
     @VisibleForTesting
     static final Map<Uri, Class<? extends CustomSliceable>> sUriToSlice;
 
@@ -335,6 +336,7 @@
         sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
         sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
         sUriToSlice.put(DARK_THEME_SLICE_URI, DarkThemeSlice.class);
+        sUriToSlice.put(REMOTE_MEDIA_SLICE_URI, RemoteMediaSlice.class);
     }
 
     public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
diff --git a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
index f931fa4..34892fa 100644
--- a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
+++ b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
@@ -16,22 +16,29 @@
 package com.android.settings.users;
 
 import android.content.Context;
+import android.os.UserHandle;
 import android.provider.Settings;
 
 import androidx.preference.Preference;
 
+import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.core.TogglePreferenceController;
 import com.android.settingslib.RestrictedSwitchPreference;
 
 public class AddUserWhenLockedPreferenceController extends TogglePreferenceController {
 
     private final UserCapabilities mUserCaps;
+    private LockPatternUtils mLockPatternUtils;
 
     public AddUserWhenLockedPreferenceController(Context context, String key) {
         super(context, key);
         mUserCaps = UserCapabilities.create(context);
     }
 
+    void setLockPatternUtils(LockPatternUtils lockPatternUtils) {
+        mLockPatternUtils = lockPatternUtils;
+    }
+
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
@@ -53,6 +60,8 @@
             return DISABLED_FOR_USER;
         } else if (mUserCaps.disallowAddUser() || mUserCaps.disallowAddUserSetByAdmin()) {
             return DISABLED_FOR_USER;
+        } else if (!mLockPatternUtils.isSecure(UserHandle.myUserId())) {
+            return CONDITIONALLY_UNAVAILABLE;
         } else {
             return mUserCaps.mUserSwitcherEnabled ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
         }
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index cd305e9..51da9d2 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -241,6 +241,9 @@
 
         mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController(
                 activity, KEY_ADD_USER_WHEN_LOCKED);
+        mAddUserWhenLockedPreferenceController.setLockPatternUtils(
+                new LockPatternUtils(getPrefContext()));
+
         mMultiUserFooterPreferenceController = new MultiUserFooterPreferenceController(activity,
                 KEY_MULTIUSER_FOOTER);
 
@@ -1290,8 +1293,11 @@
                         boolean suppressAllPage) {
                     final List<String> niks = super.getNonIndexableKeysFromXml(context, xmlResId,
                             suppressAllPage);
-                    new AddUserWhenLockedPreferenceController(context, KEY_ADD_USER_WHEN_LOCKED)
-                            .updateNonIndexableKeys(niks);
+                    AddUserWhenLockedPreferenceController controller =
+                            new AddUserWhenLockedPreferenceController(
+                                    context, KEY_ADD_USER_WHEN_LOCKED);
+                    controller.setLockPatternUtils(new LockPatternUtils(context));
+                    controller.updateNonIndexableKeys(niks);
                     new AutoSyncDataPreferenceController(context, null /* parent */)
                             .updateNonIndexableKeys(niks);
                     new AutoSyncPersonalDataPreferenceController(context, null /* parent */)
diff --git a/src/com/android/settings/wifi/CaptivePortalNetworkCallback.java b/src/com/android/settings/wifi/CaptivePortalNetworkCallback.java
index 9bcfba0..630476f 100644
--- a/src/com/android/settings/wifi/CaptivePortalNetworkCallback.java
+++ b/src/com/android/settings/wifi/CaptivePortalNetworkCallback.java
@@ -22,7 +22,7 @@
 import com.android.internal.util.Preconditions;
 
 /** Listens for changes to NetworkCapabilities to update the ConnectedAccessPointPreference. */
-final class CaptivePortalNetworkCallback extends NetworkCallback {
+class CaptivePortalNetworkCallback extends NetworkCallback {
 
     private final ConnectedAccessPointPreference mConnectedApPreference;
     private final Network mNetwork;
@@ -36,25 +36,42 @@
     }
 
     @Override
-    public void onLost(Network network) {
+    public final void onLost(Network network) {
         if (mNetwork.equals(network)) {
-            mIsCaptivePortal = false;
+            setIsCaptivePortal(false);
         }
     }
 
     @Override
-    public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
+    public final void onCapabilitiesChanged(Network network,
+            NetworkCapabilities networkCapabilities) {
         if (mNetwork.equals(network)) {
-            mIsCaptivePortal = WifiUtils.canSignIntoNetwork(networkCapabilities);
-            mConnectedApPreference.setCaptivePortal(mIsCaptivePortal);
+            boolean isCaptivePortal = WifiUtils.canSignIntoNetwork(networkCapabilities);
+            setIsCaptivePortal(isCaptivePortal);
+            mConnectedApPreference.setCaptivePortal(isCaptivePortal);
         }
     }
 
     /**
+     * Called when captive portal capability changes for the current network. Default implementation
+     * is a no-op. Use {@link CaptivePortalNetworkCallback#isCaptivePortal()} to read new
+     * capability.
+     */
+    public void onCaptivePortalCapabilityChanged() {}
+
+    private void setIsCaptivePortal(boolean isCaptivePortal) {
+        if (isCaptivePortal == mIsCaptivePortal) {
+            return;
+        }
+        mIsCaptivePortal = isCaptivePortal;
+        onCaptivePortalCapabilityChanged();
+    }
+
+    /**
      * Returns true if the supplied network and preference are not null and are the same as the
      * originally supplied values.
      */
-    public boolean isSameNetworkAndPreference(
+    public final boolean isSameNetworkAndPreference(
             Network network, ConnectedAccessPointPreference connectedApPreference) {
         return mNetwork.equals(network) && mConnectedApPreference == connectedApPreference;
     }
@@ -63,12 +80,12 @@
      * Returns true if the most recent update to the NetworkCapabilities indicates a captive portal
      * network and the Network was not lost in the interim.
      */
-    public boolean isCaptivePortal() {
+    public final boolean isCaptivePortal() {
         return mIsCaptivePortal;
     }
 
     /** Returns the currently associated network. */
-    public Network getNetwork() {
+    public final Network getNetwork() {
         return mNetwork;
     }
 }
diff --git a/src/com/android/settings/wifi/WifiMasterSwitchPreferenceController.java b/src/com/android/settings/wifi/WifiMasterSwitchPreferenceController.java
index 6a4774b..2f57249 100644
--- a/src/com/android/settings/wifi/WifiMasterSwitchPreferenceController.java
+++ b/src/com/android/settings/wifi/WifiMasterSwitchPreferenceController.java
@@ -36,7 +36,7 @@
         implements PreferenceControllerMixin, SummaryUpdater.OnSummaryChangeListener,
         LifecycleObserver, OnResume, OnPause, OnStart, OnStop {
 
-    public static final String KEY_TOGGLE_WIFI = "toggle_wifi";
+    public static final String KEY_TOGGLE_WIFI = "main_toggle_wifi";
 
     private MasterSwitchPreference mWifiPreference;
     private WifiEnabler mWifiEnabler;
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 9d075a7..f563e32 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -50,6 +50,7 @@
 import android.view.View;
 import android.widget.Toast;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
@@ -135,12 +136,16 @@
         setProgressBarVisible(false);
     };
 
-    protected WifiManager mWifiManager;
-    private ConnectivityManager mConnectivityManager;
+    @VisibleForTesting
+    WifiManager mWifiManager;
+    @VisibleForTesting
+    ConnectivityManager mConnectivityManager;
     private WifiManager.ActionListener mConnectListener;
     private WifiManager.ActionListener mSaveListener;
     private WifiManager.ActionListener mForgetListener;
-    private CaptivePortalNetworkCallback mCaptivePortalNetworkCallback;
+    @VisibleForTesting
+    CaptivePortalNetworkCallback mCaptivePortalNetworkCallback;
+    private Network mLastNetworkCaptivePortalAppStarted;
 
     /**
      * The state of {@link #isUiRestricted()} at {@link #onCreate(Bundle)}}. This is neccesary to
@@ -196,6 +201,15 @@
      * network once connected.
      */
     private boolean mClickedConnect;
+    @ConnectSource int mConnectSource = CONNECT_SOURCE_UNSPECIFIED;
+
+    private static final int CONNECT_SOURCE_UNSPECIFIED = 0;
+    private static final int CONNECT_SOURCE_NETWORK_MENU_ITEM_CLICK = 1;
+    private static final int CONNECT_SOURCE_NETWORK_LIST_ITEM_CLICK = 2;
+
+    @IntDef({CONNECT_SOURCE_UNSPECIFIED, CONNECT_SOURCE_NETWORK_MENU_ITEM_CLICK,
+        CONNECT_SOURCE_NETWORK_LIST_ITEM_CLICK})
+    private @interface ConnectSource {}
 
     /* End of "used in Wifi Setup context" */
 
@@ -512,12 +526,14 @@
             case MENU_ID_CONNECT: {
                 boolean isSavedNetwork = mSelectedAccessPoint.isSaved();
                 if (isSavedNetwork) {
-                    connect(mSelectedAccessPoint.getConfig(), isSavedNetwork);
+                    connect(mSelectedAccessPoint.getConfig(), isSavedNetwork,
+                            CONNECT_SOURCE_NETWORK_MENU_ITEM_CLICK);
                 } else if ((mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) ||
                         (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_OWE)) {
                     /** Bypass dialog for unsecured networks */
                     mSelectedAccessPoint.generateOpenNetworkConfig();
-                    connect(mSelectedAccessPoint.getConfig(), isSavedNetwork);
+                    connect(mSelectedAccessPoint.getConfig(), isSavedNetwork,
+                            CONNECT_SOURCE_NETWORK_MENU_ITEM_CLICK);
                 } else {
                     showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
                 }
@@ -563,11 +579,15 @@
 
                 case WifiUtils.CONNECT_TYPE_OPEN_NETWORK:
                     mSelectedAccessPoint.generateOpenNetworkConfig();
-                    connect(mSelectedAccessPoint.getConfig(), mSelectedAccessPoint.isSaved());
+                    connect(mSelectedAccessPoint.getConfig(),
+                            mSelectedAccessPoint.isSaved(),
+                            CONNECT_SOURCE_NETWORK_LIST_ITEM_CLICK);
                     break;
 
                 case WifiUtils.CONNECT_TYPE_SAVED_NETWORK:
-                    connect(mSelectedAccessPoint.getConfig(), true /* isSavedNetwork */);
+                    connect(mSelectedAccessPoint.getConfig(),
+                            true /* isSavedNetwork */,
+                            CONNECT_SOURCE_NETWORK_LIST_ITEM_CLICK);
                     break;
 
                 default:
@@ -705,6 +725,8 @@
                 setOffMessage();
                 setAdditionalSettingsSummaries();
                 setProgressBarVisible(false);
+                mConnectSource = CONNECT_SOURCE_UNSPECIFIED;
+                mClickedConnect = false;
                 break;
         }
     }
@@ -876,7 +898,7 @@
                     pref.getAccessPoint().saveWifiState(pref.getExtras());
                     if (mCaptivePortalNetworkCallback != null
                             && mCaptivePortalNetworkCallback.isCaptivePortal()) {
-                        mConnectivityManager.startCaptivePortalApp(
+                        startCaptivePortalApp(
                                 mCaptivePortalNetworkCallback.getNetwork());
                     } else {
                         launchNetworkDetailsFragment(pref);
@@ -914,7 +936,12 @@
 
         unregisterCaptivePortalNetworkCallback();
 
-        mCaptivePortalNetworkCallback = new CaptivePortalNetworkCallback(wifiNetwork, pref);
+        mCaptivePortalNetworkCallback = new CaptivePortalNetworkCallback(wifiNetwork, pref) {
+            @Override
+            public void onCaptivePortalCapabilityChanged() {
+                checkStartCaptivePortalApp();
+            }
+        };
         mConnectivityManager.registerNetworkCallback(
                 new NetworkRequest.Builder()
                         .clearCapabilities()
@@ -1099,14 +1126,17 @@
         if (config == null) {
             if (mSelectedAccessPoint != null
                     && mSelectedAccessPoint.isSaved()) {
-                connect(mSelectedAccessPoint.getConfig(), true /* isSavedNetwork */);
+                connect(mSelectedAccessPoint.getConfig(),
+                        true /* isSavedNetwork */,
+                        CONNECT_SOURCE_UNSPECIFIED);
             }
         } else if (configController.getMode() == WifiConfigUiBase.MODE_MODIFY) {
             mWifiManager.save(config, mSaveListener);
         } else {
             mWifiManager.save(config, mSaveListener);
             if (mSelectedAccessPoint != null) { // Not an "Add network"
-                connect(config, false /* isSavedNetwork */);
+                connect(config, false /* isSavedNetwork */,
+                        CONNECT_SOURCE_UNSPECIFIED);
             }
         }
 
@@ -1143,21 +1173,16 @@
         changeNextButtonState(false);
     }
 
-    protected void connect(final WifiConfiguration config, boolean isSavedNetwork) {
+    protected void connect(final WifiConfiguration config,
+            boolean isSavedNetwork, @ConnectSource int connectSource) {
         // Log subtype if configuration is a saved network.
         mMetricsFeatureProvider.action(getContext(), SettingsEnums.ACTION_WIFI_CONNECT,
                 isSavedNetwork);
+        mConnectSource = connectSource;
         mWifiManager.connect(config, mConnectListener);
         mClickedConnect = true;
     }
 
-    protected void connect(final int networkId, boolean isSavedNetwork) {
-        // Log subtype if configuration is a saved network.
-        mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_WIFI_CONNECT,
-                isSavedNetwork);
-        mWifiManager.connect(networkId, mConnectListener);
-    }
-
     @VisibleForTesting
     void handleAddNetworkRequest(int result, Intent data) {
         if (result == Activity.RESULT_OK) {
@@ -1217,7 +1242,8 @@
             mWifiManager.save(wifiConfiguration, mSaveListener);
 
             if (mSelectedAccessPoint != null) {
-                connect(wifiConfiguration, false /*isSavedNetwork*/);
+                connect(wifiConfiguration, false /*isSavedNetwork*/,
+                        CONNECT_SOURCE_UNSPECIFIED);
             }
             mWifiTracker.resumeScanning();
         }
@@ -1236,6 +1262,42 @@
                 .launch();
     }
 
+    /**
+     * Starts the captive portal for current network if it's been clicked from the available
+     * networks (or contextual menu). We only do it *once* for a picked network, to avoid connecting
+     * again on bg/fg or if user dismisses Captive Portal before connecting (otherwise, coming back
+     * to this screen while connected to the same network but not signed in would open CP again).
+     */
+    private void checkStartCaptivePortalApp() {
+        Network currentNetwork = getCurrentWifiNetwork();
+        if (mCaptivePortalNetworkCallback == null || currentNetwork == null
+                || !currentNetwork.equals(mCaptivePortalNetworkCallback.getNetwork())
+                || !mCaptivePortalNetworkCallback.isCaptivePortal()) {
+            return;
+        }
+
+        if (mConnectSource != CONNECT_SOURCE_NETWORK_LIST_ITEM_CLICK
+                && mConnectSource != CONNECT_SOURCE_NETWORK_MENU_ITEM_CLICK) {
+            return;
+        }
+
+        if (mLastNetworkCaptivePortalAppStarted != null
+                && mLastNetworkCaptivePortalAppStarted.equals(currentNetwork)) {
+            // We already auto-opened CP for same network
+            return;
+        }
+
+        startCaptivePortalApp(currentNetwork);
+    }
+
+    private void startCaptivePortalApp(Network network) {
+        if (mConnectivityManager == null || network == null) {
+            return;
+        }
+        mLastNetworkCaptivePortalAppStarted = network;
+        mConnectivityManager.startCaptivePortalApp(network);
+    }
+
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider(R.xml.wifi_settings) {
                 @Override
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
index 895bdba..69adf55 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
@@ -43,12 +43,9 @@
 import androidx.slice.builders.SliceAction;
 
 import com.android.ims.ImsConfig;
-import com.android.ims.ImsManager;
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.network.ims.WifiCallingQueryImsState;
-import com.android.settings.network.telephony.MobileNetworkUtils;
 import com.android.settings.slices.SliceBroadcastReceiver;
 
 import java.util.concurrent.Callable;
@@ -140,10 +137,7 @@
             return null;
         }
 
-        final ImsManager imsManager = getImsManager(subId);
-
-        if (!imsManager.isWfcEnabledByPlatform()
-                || !isWfcProvisionedOnDevice(subId)) {
+        if (!queryImsState(subId).isWifiCallingProvisioned()) {
             Log.d(TAG, "Wifi calling is either not provisioned or not enabled by Platform");
             return null;
         }
@@ -168,9 +162,8 @@
     }
 
     private boolean isWifiCallingEnabled() {
-        final int subId = getDefaultVoiceSubId();
-        return queryImsState(subId).isEnabledByUser()
-                && queryImsState(subId).isAllowUserControl();
+        final WifiCallingQueryImsState queryState = queryImsState(getDefaultVoiceSubId());
+        return queryState.isEnabledByUser() && queryState.isAllowUserControl();
     }
 
     /**
@@ -224,23 +217,21 @@
                 CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false);
         final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
                 CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
-        final ImsManager imsManager = getImsManager(subId);
-        final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId);
-
-        if (!imsManager.isWfcEnabledByPlatform()
-                || !isWfcProvisionedOnDevice(subId)) {
-            Log.d(TAG, "Wifi calling is either not provisioned or not enabled by platform");
-            return null;
-        }
 
         if (!isWifiCallingPrefEditable) {
             Log.d(TAG, "Wifi calling preference is not editable");
             return null;
         }
 
+        if (!queryImsState(subId).isWifiCallingProvisioned()) {
+            Log.d(TAG, "Wifi calling is either not provisioned or not enabled by platform");
+            return null;
+        }
+
         boolean isWifiCallingEnabled = false;
         int wfcMode = -1;
         try {
+            final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId);
             isWifiCallingEnabled = isWifiCallingEnabled();
             wfcMode = getWfcMode(imsMmTelManager);
         } catch (InterruptedException | ExecutionException | TimeoutException e) {
@@ -351,10 +342,6 @@
         }
     }
 
-    protected ImsManager getImsManager(int subId) {
-        return ImsManager.getInstance(mContext, SubscriptionUtil.getPhoneId(mContext, subId));
-    }
-
     protected ImsMmTelManager getImsMmTelManager(int subId) {
         return ImsMmTelManager.createForSubscriptionId(subId);
     }
@@ -382,11 +369,10 @@
         final int subId = getDefaultVoiceSubId();
 
         if (SubscriptionManager.isValidSubscriptionId(subId)) {
-            final ImsManager imsManager = getImsManager(subId);
-            if (imsManager.isWfcEnabledByPlatform()
-                    && isWfcProvisionedOnDevice(subId)) {
-                final boolean currentValue = queryImsState(subId).isEnabledByUser()
-                        && queryImsState(subId).isAllowUserControl();
+            final WifiCallingQueryImsState queryState = queryImsState(subId);
+            if (queryState.isWifiCallingProvisioned()) {
+                final boolean currentValue = queryState.isEnabledByUser()
+                        && queryState.isAllowUserControl();
                 final boolean newValue = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
                         currentValue);
                 final Intent activationAppIntent =
@@ -425,12 +411,11 @@
             final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
                     CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
 
-            final ImsManager imsManager = getImsManager(subId);
+            final WifiCallingQueryImsState queryState = queryImsState(subId);
             if (isWifiCallingPrefEditable
-                    && imsManager.isWfcEnabledByPlatform()
-                    && isWfcProvisionedOnDevice(subId)
-                    && queryImsState(subId).isEnabledByUser()
-                    && queryImsState(subId).isAllowUserControl()) {
+                    && queryState.isWifiCallingProvisioned()
+                    && queryState.isEnabledByUser()
+                    && queryState.isAllowUserControl()) {
                 // Change the preference only when wifi calling is enabled
                 // And when wifi calling preference is editable for the current carrier
                 final ImsMmTelManager imsMmTelManager = getImsMmTelManager(subId);
@@ -511,11 +496,6 @@
         return SubscriptionManager.getDefaultVoiceSubscriptionId();
     }
 
-    @VisibleForTesting
-    boolean isWfcProvisionedOnDevice(int subId) {
-        return MobileNetworkUtils.isWfcProvisionedOnDevice(subId);
-    }
-
     /**
      * Returns Intent of the activation app required to activate wifi calling or null if there is no
      * need for activation.
diff --git a/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
index 0a8f7d6..504909e 100644
--- a/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
@@ -1,7 +1,6 @@
 package com.android.settings.development;
 
-import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes
-        .REQUEST_MOCK_LOCATION_APP;
+import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_MOCK_LOCATION_APP;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -20,7 +19,6 @@
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.util.Pair;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
@@ -145,6 +143,15 @@
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
     }
 
+    @Test
+    public void onDeveloperOptionsDisabled_currentMockLocationApp_shouldBeNull() {
+        mController.onDeveloperOptionsDisabled();
+
+        final String appName = mController.getCurrentMockLocationApp();
+
+        assertThat(appName).isNull();
+    }
+
     private AppOpsManager.OpEntry createOpEntry(int opMode) {
         return new OpEntry(0, opMode, Collections.emptyMap());
     }
diff --git a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceControllerTest.java
similarity index 92%
rename from tests/robotests/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceControllerTest.java
index de4be1d..522dc8a 100644
--- a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceControllerTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
 import static com.android.settings.testutils.ApplicationTestUtils.buildInfo;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -53,7 +53,7 @@
 import java.util.Arrays;
 
 @RunWith(RobolectricTestRunner.class)
-public class GameDriverAppPreferenceControllerTest {
+public class GraphicsDriverAppPreferenceControllerTest {
 
     private static final int DEFAULT = 0;
     private static final int GAME_DRIVER = 1;
@@ -71,13 +71,13 @@
     @Mock
     private PreferenceScreen mScreen;
     @Mock
-    private GameDriverContentObserver mGameDriverContentObserver;
+    private GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     private Context mContext;
     private PreferenceGroup mGroup;
     private PreferenceManager mPreferenceManager;
     private ContentResolver mResolver;
-    private GameDriverAppPreferenceController mController;
+    private GraphicsDriverAppPreferenceController mController;
     private CharSequence[] mValueList;
     private String mDialogTitle;
     private String mPreferencePrereleaseDriver;
@@ -137,19 +137,19 @@
     @Test
     public void onStart_shouldRegister() {
         loadDefaultConfig();
-        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.mGraphicsDriverContentObserver = mGraphicsDriverContentObserver;
         mController.onStart();
 
-        verify(mGameDriverContentObserver).register(mResolver);
+        verify(mGraphicsDriverContentObserver).register(mResolver);
     }
 
     @Test
     public void onStop_shouldUnregister() {
         loadDefaultConfig();
-        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.mGraphicsDriverContentObserver = mGraphicsDriverContentObserver;
         mController.onStop();
 
-        verify(mGameDriverContentObserver).unregister(mResolver);
+        verify(mGraphicsDriverContentObserver).unregister(mResolver);
     }
 
     @Test
@@ -295,7 +295,9 @@
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
     }
 
-    private void loadDefaultConfig() { loadConfig("", "", ""); }
+    private void loadDefaultConfig() {
+        loadConfig("", "", "");
+    }
 
     private void loadConfig(String optIn, String prereleaseOptIn, String optOut) {
         Settings.Global.putString(mResolver, Settings.Global.GAME_DRIVER_OPT_IN_APPS, optIn);
@@ -303,7 +305,7 @@
                 mResolver, Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, prereleaseOptIn);
         Settings.Global.putString(mResolver, Settings.Global.GAME_DRIVER_OPT_OUT_APPS, optOut);
 
-        mController = new GameDriverAppPreferenceController(mContext, "testKey");
+        mController = new GraphicsDriverAppPreferenceController(mContext, "testKey");
         mGroup = spy(new PreferenceCategory(mContext));
         final PreferenceManager preferenceManager = new PreferenceManager(mContext);
         when(mGroup.getContext()).thenReturn(mContext);
diff --git a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverContentObserverTest.java b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverContentObserverTest.java
similarity index 65%
rename from tests/robotests/src/com/android/settings/development/gamedriver/GameDriverContentObserverTest.java
rename to tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverContentObserverTest.java
index caaf896..b6bf4a7 100644
--- a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverContentObserverTest.java
+++ b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverContentObserverTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -28,45 +28,44 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
-public class GameDriverContentObserverTest {
+public class GraphicsDriverContentObserverTest {
 
     @Mock
     private ContentResolver mResolver;
     @Mock
-    private GameDriverContentObserver.OnGameDriverContentChangedListener mListener;
+    private GraphicsDriverContentObserver.OnGraphicsDriverContentChangedListener mListener;
 
-    private GameDriverContentObserver mGameDriverContentObserver;
+    private GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mGameDriverContentObserver = spy(new GameDriverContentObserver(null, null));
+        mGraphicsDriverContentObserver = spy(new GraphicsDriverContentObserver(null, null));
     }
 
     @Test
     public void onChange_shouldCallListener() {
-        mGameDriverContentObserver.mListener = mListener;
-        mGameDriverContentObserver.onChange(true);
+        mGraphicsDriverContentObserver.mListener = mListener;
+        mGraphicsDriverContentObserver.onChange(true);
 
-        verify(mListener).onGameDriverContentChanged();
+        verify(mListener).onGraphicsDriverContentChanged();
     }
 
     @Test
     public void register_shouldRegisterContentObserver() {
-        mGameDriverContentObserver.register(mResolver);
+        mGraphicsDriverContentObserver.register(mResolver);
 
         verify(mResolver).registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_ALL_APPS), false,
-                mGameDriverContentObserver);
+                mGraphicsDriverContentObserver);
     }
 
     @Test
     public void unregister_shouldUnregisterContentObserver() {
-        mGameDriverContentObserver.unregister(mResolver);
+        mGraphicsDriverContentObserver.unregister(mResolver);
 
-        verify(mResolver).unregisterContentObserver(mGameDriverContentObserver);
+        verify(mResolver).unregisterContentObserver(mGraphicsDriverContentObserver);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverDashboardTest.java b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverDashboardTest.java
similarity index 79%
rename from tests/robotests/src/com/android/settings/development/gamedriver/GameDriverDashboardTest.java
rename to tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverDashboardTest.java
index eb5c3b3..838f47b 100644
--- a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverDashboardTest.java
+++ b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverDashboardTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -28,13 +28,13 @@
 import org.robolectric.RobolectricTestRunner;
 
 @RunWith(RobolectricTestRunner.class)
-public class GameDriverDashboardTest {
+public class GraphicsDriverDashboardTest {
 
-    private GameDriverDashboard mDashboard;
+    private GraphicsDriverDashboard mDashboard;
 
     @Before
     public void setUp() {
-        mDashboard = new GameDriverDashboard();
+        mDashboard = new GraphicsDriverDashboard();
     }
 
     @Test
@@ -43,13 +43,13 @@
     }
 
     @Test
-    public void getMetricesCategory_shouldReturnGameDriverDashboard() {
+    public void getMetricesCategory_shouldReturnGraphicsDriverDashboard() {
         assertThat(mDashboard.getMetricsCategory())
                 .isEqualTo(SettingsEnums.SETTINGS_GAME_DRIVER_DASHBOARD);
     }
 
     @Test
-    public void getPreferenceScreen_shouldReturnGameDriverSettings() {
+    public void getPreferenceScreen_shouldReturnGraphicsDriverSettings() {
         assertThat(mDashboard.getPreferenceScreenResId()).isEqualTo(R.xml.graphics_driver_settings);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceControllerTest.java
similarity index 85%
rename from tests/robotests/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceControllerTest.java
index 8495f60..366a18d 100644
--- a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceControllerTest.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_ALL_APPS;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_PRERELEASE_ALL_APPS;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_ALL_APPS;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_PRERELEASE_ALL_APPS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -48,18 +48,18 @@
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
-public class GameDriverEnableForAllAppsPreferenceControllerTest {
+public class GraphicsDriverEnableForAllAppsPreferenceControllerTest {
 
     @Mock
     private PreferenceScreen mScreen;
     @Mock
     private ListPreference mPreference;
     @Mock
-    private GameDriverContentObserver mGameDriverContentObserver;
+    private GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     private Context mContext;
     private ContentResolver mResolver;
-    private GameDriverEnableForAllAppsPreferenceController mController;
+    private GraphicsDriverEnableForAllAppsPreferenceController mController;
     private String mPreferenceDefault;
     private String mPreferenceGameDriver;
     private String mPreferencePrereleaseDriver;
@@ -81,7 +81,7 @@
         Settings.Global.putInt(
                 mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT);
 
-        mController = new GameDriverEnableForAllAppsPreferenceController(mContext, "testKey");
+        mController = new GraphicsDriverEnableForAllAppsPreferenceController(mContext, "testKey");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
         mController.displayPreference(mScreen);
     }
@@ -120,18 +120,18 @@
 
     @Test
     public void onStart_shouldRegister() {
-        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.mGraphicsDriverContentObserver = mGraphicsDriverContentObserver;
         mController.onStart();
 
-        verify(mGameDriverContentObserver).register(mResolver);
+        verify(mGraphicsDriverContentObserver).register(mResolver);
     }
 
     @Test
     public void onStop_shouldUnregister() {
-        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.mGraphicsDriverContentObserver = mGraphicsDriverContentObserver;
         mController.onStop();
 
-        verify(mGameDriverContentObserver).unregister(mResolver);
+        verify(mGraphicsDriverContentObserver).unregister(mResolver);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverFooterPreferenceControllerTest.java
similarity index 74%
rename from tests/robotests/src/com/android/settings/development/gamedriver/GameDriverFooterPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverFooterPreferenceControllerTest.java
index 17b7b36..1dac131 100644
--- a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverFooterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverFooterPreferenceControllerTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_ALL_APPS;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_ALL_APPS;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -45,25 +45,25 @@
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
-public class GameDriverFooterPreferenceControllerTest {
+public class GraphicsDriverFooterPreferenceControllerTest {
 
     @Mock
     private PreferenceScreen mScreen;
     @Mock
     private FooterPreference mPreference;
     @Mock
-    private GameDriverContentObserver mGameDriverContentObserver;
+    private GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     private Context mContext;
     private ContentResolver mResolver;
-    private GameDriverFooterPreferenceController mController;
+    private GraphicsDriverFooterPreferenceController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         mResolver = mContext.getContentResolver();
-        mController = spy(new GameDriverFooterPreferenceController(mContext, "key"));
+        mController = spy(new GraphicsDriverFooterPreferenceController(mContext, "key"));
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
     }
 
@@ -92,17 +92,17 @@
 
     @Test
     public void onStart_shouldRegister() {
-        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.mGraphicsDriverContentObserver = mGraphicsDriverContentObserver;
         mController.onStart();
 
-        verify(mGameDriverContentObserver).register(mResolver);
+        verify(mGraphicsDriverContentObserver).register(mResolver);
     }
 
     @Test
     public void onStop_shouldUnregister() {
-        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.mGraphicsDriverContentObserver = mGraphicsDriverContentObserver;
         mController.onStop();
 
-        verify(mGameDriverContentObserver).unregister(mResolver);
+        verify(mGraphicsDriverContentObserver).unregister(mResolver);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverGlobalSwitchBarControllerTest.java
similarity index 76%
rename from tests/robotests/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarControllerTest.java
rename to tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverGlobalSwitchBarControllerTest.java
index f546c36..7d4ee45 100644
--- a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverGlobalSwitchBarControllerTest.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.settings.development.gamedriver;
+package com.android.settings.development.graphicsdriver;
 
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
-import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.verify;
@@ -39,18 +40,18 @@
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
-public class GameDriverGlobalSwitchBarControllerTest {
+public class GraphicsDriverGlobalSwitchBarControllerTest {
 
     @Mock
     private SwitchBar mSwitchBar;
     @Mock
     private SwitchWidgetController mSwitchWidgetController;
     @Mock
-    private GameDriverContentObserver mGameDriverContentObserver;
+    private GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     private Context mContext;
     private ContentResolver mResolver;
-    private GameDriverGlobalSwitchBarController mController;
+    private GraphicsDriverGlobalSwitchBarController mController;
 
     @Before
     public void setUp() {
@@ -63,7 +64,7 @@
     public void constructor_gameDriverOn_shouldCheckSwitchBar() {
         Settings.Global.putInt(
                 mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT);
-        mController = new GameDriverGlobalSwitchBarController(
+        mController = new GraphicsDriverGlobalSwitchBarController(
                 mContext, new SwitchBarController(mSwitchBar));
 
         verify(mSwitchBar).setChecked(true);
@@ -72,7 +73,7 @@
     @Test
     public void constructor_gameDriverOff_shouldUncheckSwitchBar() {
         Settings.Global.putInt(mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_OFF);
-        mController = new GameDriverGlobalSwitchBarController(
+        mController = new GraphicsDriverGlobalSwitchBarController(
                 mContext, new SwitchBarController(mSwitchBar));
 
         verify(mSwitchBar).setChecked(false);
@@ -81,7 +82,7 @@
     @Test
     public void constructor_developmentSettingsEnabled_shouldEnableSwitchBar() {
         Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
-        mController = new GameDriverGlobalSwitchBarController(
+        mController = new GraphicsDriverGlobalSwitchBarController(
                 mContext, new SwitchBarController(mSwitchBar));
 
         verify(mSwitchBar).setEnabled(true);
@@ -90,7 +91,7 @@
     @Test
     public void constructor_developmentSettingsDisabled_shouldDisableSwitchBar() {
         Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
-        mController = new GameDriverGlobalSwitchBarController(
+        mController = new GraphicsDriverGlobalSwitchBarController(
                 mContext, new SwitchBarController(mSwitchBar));
 
         verify(mSwitchBar).setEnabled(false);
@@ -98,32 +99,32 @@
 
     @Test
     public void onStart_shouldStartListeningAndRegister() {
-        mController = new GameDriverGlobalSwitchBarController(
+        mController = new GraphicsDriverGlobalSwitchBarController(
                 mContext, new SwitchBarController(mSwitchBar));
         mController.mSwitchWidgetController = mSwitchWidgetController;
-        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.mGraphicsDriverContentObserver = mGraphicsDriverContentObserver;
         mController.onStart();
 
         verify(mSwitchWidgetController).startListening();
-        verify(mGameDriverContentObserver).register(mResolver);
+        verify(mGraphicsDriverContentObserver).register(mResolver);
     }
 
     @Test
     public void onStop_shouldStopListeningAndUnregister() {
-        mController = new GameDriverGlobalSwitchBarController(
+        mController = new GraphicsDriverGlobalSwitchBarController(
                 mContext, new SwitchBarController(mSwitchBar));
         mController.mSwitchWidgetController = mSwitchWidgetController;
-        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.mGraphicsDriverContentObserver = mGraphicsDriverContentObserver;
         mController.onStop();
 
         verify(mSwitchWidgetController).stopListening();
-        verify(mGameDriverContentObserver).unregister(mResolver);
+        verify(mGraphicsDriverContentObserver).unregister(mResolver);
     }
 
     @Test
     public void onSwitchToggled_checked_shouldTurnOnGameDriver() {
         Settings.Global.putInt(mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_OFF);
-        mController = new GameDriverGlobalSwitchBarController(
+        mController = new GraphicsDriverGlobalSwitchBarController(
                 mContext, new SwitchBarController(mSwitchBar));
         mController.onSwitchToggled(true);
 
@@ -136,7 +137,7 @@
     public void onSwitchToggled_unchecked_shouldTurnOffGameDriver() {
         Settings.Global.putInt(
                 mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT);
-        mController = new GameDriverGlobalSwitchBarController(
+        mController = new GraphicsDriverGlobalSwitchBarController(
                 mContext, new SwitchBarController(mSwitchBar));
         mController.onSwitchToggled(false);
 
diff --git a/tests/robotests/src/com/android/settings/media/RemoteMediaSliceTest.java b/tests/robotests/src/com/android/settings/media/RemoteMediaSliceTest.java
new file mode 100644
index 0000000..b719a9e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/media/RemoteMediaSliceTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.media;
+
+import static android.app.slice.Slice.EXTRA_RANGE_VALUE;
+import static android.app.slice.Slice.HINT_LIST_ITEM;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+
+import static com.android.settings.slices.CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+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.net.Uri;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.core.SliceQuery;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settingslib.media.LocalMediaManager;
+import com.android.settingslib.media.MediaDevice;
+
+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.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = RemoteMediaSliceTest.ShadowSliceBackgroundWorker.class)
+public class RemoteMediaSliceTest {
+
+    private static final String MEDIA_ID = "media_id";
+    private static final String TEST_PACKAGE_LABEL = "music";
+    private static final String TEST_DEVICE_1_ID = "test_device_1_id";
+    private static final String TEST_DEVICE_1_NAME = "test_device_1_name";
+    private static final int TEST_VOLUME = 3;
+
+    private static MediaDeviceUpdateWorker sMediaDeviceUpdateWorker;
+
+    @Mock
+    private LocalMediaManager mLocalMediaManager;
+    @Mock
+    private MediaDevice mDevice;
+
+    private final List<MediaDevice> mDevices = new ArrayList<>();
+
+    private Context mContext;
+    private RemoteMediaSlice mRemoteMediaSlice;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+
+        mRemoteMediaSlice = new RemoteMediaSlice(mContext);
+        sMediaDeviceUpdateWorker = spy(new MediaDeviceUpdateWorker(mContext,
+                REMOTE_MEDIA_SLICE_URI));
+        sMediaDeviceUpdateWorker.mLocalMediaManager = mLocalMediaManager;
+        when(sMediaDeviceUpdateWorker.getActiveMediaDevice(
+                MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE)).thenReturn(mDevices);
+        when(mDevice.getId()).thenReturn(TEST_DEVICE_1_ID);
+        when(mDevice.getName()).thenReturn(TEST_DEVICE_1_NAME);
+        when(mDevice.getMaxVolume()).thenReturn(100);
+        when(mDevice.getCurrentVolume()).thenReturn(10);
+        when(mDevice.getClientAppLabel()).thenReturn(TEST_PACKAGE_LABEL);
+    }
+
+    @Test
+    public void onNotifyChange_noId_doNothing() {
+        mDevices.add(mDevice);
+        when(mLocalMediaManager.getMediaDeviceById(mDevices, TEST_DEVICE_1_ID)).thenReturn(mDevice);
+        sMediaDeviceUpdateWorker.onDeviceListUpdate(mDevices);
+        final Intent intent = new Intent();
+        intent.putExtra(EXTRA_RANGE_VALUE, TEST_VOLUME);
+
+        mRemoteMediaSlice.onNotifyChange(intent);
+
+        verify(mDevice, never()).requestSetVolume(anyInt());
+    }
+
+    @Test
+    public void onNotifyChange_verifyAdjustVolume() {
+        mDevices.add(mDevice);
+        when(mLocalMediaManager.getMediaDeviceById(mDevices, TEST_DEVICE_1_ID)).thenReturn(mDevice);
+        sMediaDeviceUpdateWorker.onDeviceListUpdate(mDevices);
+        final Intent intent = new Intent();
+        intent.putExtra(MEDIA_ID, TEST_DEVICE_1_ID);
+        intent.putExtra(EXTRA_RANGE_VALUE, TEST_VOLUME);
+
+        mRemoteMediaSlice.onNotifyChange(intent);
+
+        verify(mDevice).requestSetVolume(TEST_VOLUME);
+    }
+
+    @Test
+    public void getSlice_noActiveDevice_checkRowNumber() {
+        final Slice slice = mRemoteMediaSlice.getSlice();
+        final int rows = SliceQuery.findAll(slice, FORMAT_SLICE, HINT_LIST_ITEM, null).size();
+
+        assertThat(rows).isEqualTo(0);
+    }
+
+    @Test
+    public void getSlice_withActiveDevice_checkRowNumber() {
+        mDevices.add(mDevice);
+        final Slice slice = mRemoteMediaSlice.getSlice();
+        final int rows = SliceQuery.findAll(slice, FORMAT_SLICE, HINT_LIST_ITEM, null).size();
+
+        // InputRange and Row
+        assertThat(rows).isEqualTo(2);
+    }
+
+    @Test
+    public void getSlice_withActiveDevice_checkTitle() {
+        mDevices.add(mDevice);
+        final Slice slice = mRemoteMediaSlice.getSlice();
+        final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+
+        assertThat(primaryAction.getTitle().toString()).isEqualTo(mContext.getText(
+                com.android.settings.R.string.remote_media_volume_option_title)
+                + " (" + TEST_PACKAGE_LABEL + ")");
+    }
+
+    @Implements(SliceBackgroundWorker.class)
+    public static class ShadowSliceBackgroundWorker {
+
+        @Implementation
+        public static SliceBackgroundWorker getInstance(Uri uri) {
+            return sMediaDeviceUpdateWorker;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
index 0abd6d5..092b9b7 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
@@ -117,10 +117,10 @@
     }
 
     @Test
-    public void handlePreferenceTreeClick_needDialog_showDialog() {
+    public void setChecked_needDialog_showDialog() {
         doReturn(true).when(mController).isDialogNeeded();
 
-        mController.handlePreferenceTreeClick(mPreference);
+        mController.setChecked(true);
 
         verify(mFragmentManager).beginTransaction();
     }
diff --git a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
index 8dd04ce..4edc2c7 100644
--- a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
+++ b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
@@ -22,38 +22,22 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.media.session.ISessionController;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
 import android.net.Uri;
 
-import com.android.settings.notification.RemoteVolumePreferenceController;
 import com.android.settings.slices.CustomSliceRegistry;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
-import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
 public class VolumePanelTest {
 
-    @Mock
-    private MediaSessionManager mMediaSessionManager;
-    @Mock
-    private MediaController mMediaController;
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private ISessionController mStub;
-
-
     private VolumePanel mPanel;
     private Context mContext;
 
@@ -65,28 +49,16 @@
         mContext = spy(RuntimeEnvironment.application);
 
         when(mContext.getApplicationContext()).thenReturn(mContext);
-        when(mContext.getSystemService(MediaSessionManager.class)).thenReturn(mMediaSessionManager);
 
         mPanel = VolumePanel.create(mContext);
     }
 
     @Test
-    public void getSlices_hasActiveRemoteToken_containsRemoteMediaUri() {
-        List<MediaController> activeSessions = new ArrayList<>();
-        MediaSession.Token token = new MediaSession.Token(mStub);
-        activeSessions.add(mMediaController);
-
-        when(mMediaSessionManager.getActiveSessions(null)).thenReturn(
-                activeSessions);
-        when(mMediaController.getPlaybackInfo()).thenReturn(new MediaController.PlaybackInfo(
-                MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE, 0, 10, 5, null));
-        when(mMediaController.getSessionToken()).thenReturn(new MediaSession.Token(mStub));
-        when(RemoteVolumePreferenceController.getActiveRemoteToken(mContext)).thenReturn(token);
-
+    public void getSlices_checkUri() {
         final List<Uri> uris = mPanel.getSlices();
 
         assertThat(uris).containsExactly(
-                CustomSliceRegistry.VOLUME_REMOTE_MEDIA_URI,
+                CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI,
                 CustomSliceRegistry.VOLUME_CALL_URI,
                 CustomSliceRegistry.VOLUME_MEDIA_URI,
                 CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI,
@@ -95,22 +67,6 @@
     }
 
     @Test
-    public void getSlices_doesNotHaveActiveRemoteToken_doesNotcontainRemoteMediaUri() {
-        final List<Uri> uris = mPanel.getSlices();
-
-        when(RemoteVolumePreferenceController.getActiveRemoteToken(mContext))
-            .thenReturn(null);
-
-        assertThat(uris).doesNotContain(CustomSliceRegistry.VOLUME_REMOTE_MEDIA_URI);
-        assertThat(uris).containsExactly(
-            CustomSliceRegistry.VOLUME_CALL_URI,
-            CustomSliceRegistry.VOLUME_MEDIA_URI,
-            CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI,
-            CustomSliceRegistry.VOLUME_RINGER_URI,
-            CustomSliceRegistry.VOLUME_ALARM_URI);
-    }
-
-    @Test
     public void getSeeMoreIntent_notNull() {
         assertThat(mPanel.getSeeMoreIntent()).isNotNull();
     }
diff --git a/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
index b27b636..9e0f2cc 100644
--- a/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
@@ -18,6 +18,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -27,6 +28,8 @@
 
 import androidx.preference.PreferenceScreen;
 
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settingslib.RestrictedSwitchPreference;
 
@@ -51,13 +54,16 @@
     private Context mContext;
     private ShadowUserManager mUserManager;
     private AddUserWhenLockedPreferenceController mController;
+    private LockPatternUtils mLockPatternUtils;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
+        mLockPatternUtils = mock(LockPatternUtils.class);
         mUserManager = ShadowUserManager.getShadow();
         mController = new AddUserWhenLockedPreferenceController(mContext, "fake_key");
+        mController.setLockPatternUtils(mLockPatternUtils);
         mUserManager.setSupportsMultipleUsers(true);
     }
 
@@ -69,6 +75,7 @@
     @Test
     public void displayPref_NotAdmin_shouldNotDisplay() {
         mUserManager.setIsAdminUser(false);
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
         final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
         when(preference.getKey()).thenReturn(mController.getPreferenceKey());
         when(mScreen.findPreference(preference.getKey())).thenReturn(preference);
@@ -81,6 +88,7 @@
     @Test
     public void updateState_NotAdmin_shouldNotDisplayPreference() {
         mUserManager.setIsAdminUser(false);
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
         final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
 
         mController.updateState(preference);
@@ -93,8 +101,10 @@
         mUserManager.setIsAdminUser(true);
         mUserManager.setUserSwitcherEnabled(true);
         mUserManager.setSupportsMultipleUsers(true);
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
         final AddUserWhenLockedPreferenceController controller =
                 new AddUserWhenLockedPreferenceController(mContext, "fake_key");
+        controller.setLockPatternUtils(mLockPatternUtils);
         final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
 
         controller.updateState(preference);
@@ -143,4 +153,40 @@
         assertThat(Global.getInt(mContext.getContentResolver(), Global.ADD_USERS_WHEN_LOCKED, 0))
                 .isEqualTo(0);
     }
+
+    @Test
+    public void updateState_insecureLockScreen_shouldNotDisplayPreference() {
+        mUserManager.setIsAdminUser(true);
+        mUserManager.setUserSwitcherEnabled(true);
+        mUserManager.setSupportsMultipleUsers(true);
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
+        final AddUserWhenLockedPreferenceController controller =
+                new AddUserWhenLockedPreferenceController(mContext, "fake_key");
+        controller.setLockPatternUtils(mLockPatternUtils);
+        final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
+
+        controller.updateState(preference);
+
+        verify(preference).setVisible(false);
+        assertThat(controller.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
+    public void updateState_secureLockScreen_shouldDisplayPreference() {
+        mUserManager.setIsAdminUser(true);
+        mUserManager.setUserSwitcherEnabled(true);
+        mUserManager.setSupportsMultipleUsers(true);
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+        final AddUserWhenLockedPreferenceController controller =
+                new AddUserWhenLockedPreferenceController(mContext, "fake_key");
+        controller.setLockPatternUtils(mLockPatternUtils);
+        final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
+
+        controller.updateState(preference);
+
+        verify(preference).setVisible(true);
+        assertThat(controller.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
index 0ae3465..3dd0da9 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.settings.wifi;
 
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -31,9 +33,14 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
 import android.net.wifi.EAPConstants;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.pps.Credential;
@@ -51,22 +58,30 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 import com.android.settings.datausage.DataUsagePreference;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
 import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settings.widget.SwitchBar;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.wifi.AccessPoint;
 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 org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
@@ -81,9 +96,27 @@
     @Mock
     private DataUsagePreference mDataUsagePreference;
     @Mock
+    private RecyclerView mRecyclerView;
+    @Mock
+    private RecyclerView.Adapter mRecyclerViewAdapter;
+    @Mock
+    private View mHeaderView;
+    @Mock
     private WifiManager mWifiManager;
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+    @Mock
+    private Intent mActivityIntent;
+    @Mock
+    private SwitchBar mSwitchBar;
+    @Mock
+    private WifiInfo mWifiInfo;
+    @Mock
+    private PackageManager mPackageManager;
     private Context mContext;
     private WifiSettings mWifiSettings;
+    private FakeFeatureFactory mFakeFeatureFactory;
+    private MetricsFeatureProvider mMetricsFeatureProvider;
 
     @Before
     public void setUp() {
@@ -92,12 +125,23 @@
 
         mWifiSettings = spy(new WifiSettings());
         doReturn(mContext).when(mWifiSettings).getContext();
+        doReturn(mRecyclerViewAdapter).when(mRecyclerView).getAdapter();
+        doReturn(mRecyclerView).when(mWifiSettings).getListView();
         doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+        doReturn(mHeaderView).when(mWifiSettings).setPinnedHeaderView(anyInt());
+        doReturn(mWifiInfo).when(mWifiManager).getConnectionInfo();
+        doReturn(mWifiManager).when(mWifiTracker).getManager();
         mWifiSettings.mAddWifiNetworkPreference = new AddWifiNetworkPreference(mContext);
         mWifiSettings.mSavedNetworksPreference = new Preference(mContext);
         mWifiSettings.mConfigureWifiSettingsPreference = new Preference(mContext);
         mWifiSettings.mWifiTracker = mWifiTracker;
         mWifiSettings.mWifiManager = mWifiManager;
+        mWifiSettings.mConnectivityManager = mConnectivityManager;
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mMetricsFeatureProvider = mFakeFeatureFactory.getMetricsFeatureProvider();
+        ReflectionHelpers.setField(mWifiSettings, "mMetricsFeatureProvider",
+                mMetricsFeatureProvider);
+        WifiTrackerFactory.setTestingWifiTracker(mWifiTracker);
     }
 
     @Test
@@ -138,6 +182,14 @@
         return mockConfigs;
     }
 
+    static NetworkCapabilities makeCaptivePortalNetworkCapabilities() {
+        final NetworkCapabilities capabilities = new NetworkCapabilities();
+        capabilities.clearAll();
+        capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+        capabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+        return capabilities;
+    }
+
     @Test
     public void setAdditionalSettingsSummaries_hasSavedNetwork_preferenceVisible() {
         when(mWifiManager.getConfiguredNetworks())
@@ -225,16 +277,20 @@
     }
 
     private void setUpForOnCreate() {
-        final FragmentActivity activity = mock(FragmentActivity.class);
+        final SettingsActivity activity = mock(SettingsActivity.class);
+        when(activity.getSwitchBar()).thenReturn(mSwitchBar);
         when(mWifiSettings.getActivity()).thenReturn(activity);
         final Resources.Theme theme = mContext.getTheme();
         when(activity.getTheme()).thenReturn(theme);
+        when(activity.getIntent()).thenReturn(mActivityIntent);
         UserManager userManager = mock(UserManager.class);
         when(activity.getSystemService(Context.USER_SERVICE))
                 .thenReturn(userManager);
-
         when(mWifiSettings.findPreference(WifiSettings.PREF_KEY_DATA_USAGE))
                 .thenReturn(mDataUsagePreference);
+        when(activity.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
+        when(activity.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
+        when(activity.getPackageManager()).thenReturn(mPackageManager);
     }
 
     @Test
@@ -291,4 +347,58 @@
 
         assertThat(adapter.hasStableIds()).isTrue();
     }
+
+    @Test
+    @Config(shadows = {ShadowDataUsageUtils.class, ShadowFragment.class})
+    public void clickOnWifiNetworkWith_shouldStartCaptivePortalApp() {
+        when(mWifiManager.getConfiguredNetworks()).thenReturn(createMockWifiConfigurations(
+                NUM_NETWORKS));
+        when(mWifiTracker.isConnected()).thenReturn(true);
+
+        final AccessPoint accessPointActive = mock(AccessPoint.class);
+        when(accessPointActive.isActive()).thenReturn(true);
+        when(accessPointActive.isSaved()).thenReturn(false);
+        when(accessPointActive.getConfig()).thenReturn(mock(WifiConfiguration.class));
+
+        final AccessPoint accessPointInactive = mock(AccessPoint.class);
+        when(accessPointInactive.isActive()).thenReturn(false);
+        when(accessPointInactive.isSaved()).thenReturn(false);
+        when(accessPointInactive.getConfig()).thenReturn(mock(WifiConfiguration.class));
+
+        when(mWifiTracker.getAccessPoints()).thenReturn(Arrays.asList(accessPointActive,
+                accessPointInactive));
+        when(mWifiManager.getWifiState()).thenReturn(WIFI_STATE_ENABLED);
+        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+
+        final Network network = mock(Network.class);
+        when(mWifiManager.getCurrentNetwork()).thenReturn(network);
+
+        // Simulate activity creation cycle
+        setUpForOnCreate();
+        ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
+        mWifiSettings.onCreate(Bundle.EMPTY);
+        mWifiSettings.onActivityCreated(null);
+        mWifiSettings.onViewCreated(new View(mContext), new Bundle());
+        mWifiSettings.onStart();
+
+        // Click on open network
+        final Preference openWifiPref = new LongPressAccessPointPreference(accessPointInactive,
+                mContext, null,
+                false /* forSavedNetworks */, R.drawable.ic_wifi_signal_0,
+                null);
+        mWifiSettings.onPreferenceTreeClick(openWifiPref);
+
+        // Ensure connect() was called, and fake success.
+        ArgumentCaptor<WifiManager.ActionListener> wifiCallbackCaptor = ArgumentCaptor.forClass(
+                WifiManager.ActionListener.class);
+        verify(mWifiManager).connect(any(WifiConfiguration.class), wifiCallbackCaptor.capture());
+        wifiCallbackCaptor.getValue().onSuccess();
+
+        // Simulate capability change
+        mWifiSettings.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network,
+                makeCaptivePortalNetworkCapabilities());
+
+        // Ensure CP was called
+        verify(mConnectivityManager).startCaptivePortalApp(eq(network));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
index aaff22a..f537be3 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -107,6 +107,7 @@
 
         mQueryImsState = spy(new WifiCallingQueryImsState(mContext, SUB_ID));
         doReturn(true).when(mQueryImsState).isEnabledByUser();
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
 
         mWfcSliceHelper = spy(new FakeWifiCallingSliceHelper(mContext));
         doReturn(mQueryImsState).when(mWfcSliceHelper).queryImsState(anyInt());
@@ -117,6 +118,8 @@
 
     @Test
     public void test_CreateWifiCallingSlice_invalidSubId() {
+        doReturn(true).when(mQueryImsState).isEnabledByUser();
+        doReturn(false).when(mQueryImsState).isWifiCallingProvisioned();
         mWfcSliceHelper.setDefaultVoiceSubId(-1);
 
         final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
@@ -127,7 +130,7 @@
 
     @Test
     public void test_CreateWifiCallingSlice_wfcNotSupported() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(false);
+        doReturn(false).when(mQueryImsState).isWifiCallingProvisioned();
 
         final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
                 CustomSliceRegistry.WIFI_CALLING_URI);
@@ -143,8 +146,7 @@
         turned off) we need to guide the user to wifi calling settings
         activity so the user can perform the activation there.(PrimaryAction)
          */
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(false).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(false);
         when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
@@ -161,8 +163,7 @@
 
     @Test
     public void test_CreateWifiCallingSlice_success() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(true).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
         when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
@@ -176,8 +177,7 @@
 
     @Test
     public void test_SettingSliceProvider_getsRightSliceWifiCalling() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(true).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
         when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
@@ -192,8 +192,7 @@
 
     @Test
     public void test_SliceBroadcastReceiver_toggleOnWifiCalling() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(false).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
         when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext))
@@ -217,8 +216,7 @@
 
     @Test
     public void test_CreateWifiCallingPreferenceSlice_prefNotEditable() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(true).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
         mWfcSliceHelper.setIsWifiCallingPrefEditable(false);
@@ -232,8 +230,7 @@
 
     @Test
     public void test_CreateWifiCallingPreferenceSlice_wfcOff() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(false).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
         mWfcSliceHelper.setIsWifiCallingPrefEditable(true);
@@ -249,8 +246,7 @@
 
     @Test
     public void test_CreateWifiCallingPreferenceSlice_success() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(true).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
         when(mMockImsMmTelManager.getVoWiFiModeSetting()).thenReturn(
@@ -267,8 +263,7 @@
 
     @Test
     public void test_SettingsSliceProvider_getWfcPreferenceSlice() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(true).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
         when(mMockImsMmTelManager.getVoWiFiModeSetting()).thenReturn(
@@ -286,8 +281,7 @@
     }
     @Test
     public void test_SliceBroadcastReceiver_setWfcPrefCellularPref() {
-        when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(true);
-        when(mWfcSliceHelper.isWfcProvisionedOnDevice(anyInt())).thenReturn(true);
+        doReturn(true).when(mQueryImsState).isWifiCallingProvisioned();
         doReturn(true).when(mQueryImsState).isEnabledByUser();
         when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
         when(mMockImsMmTelManager.getVoWiFiModeSetting()).thenReturn(
@@ -441,12 +435,6 @@
             return mMockCarrierConfigManager;
         }
 
-        @Override
-        protected ImsManager getImsManager(int subId) {
-            return mMockImsManager;
-        }
-
-        @Override
         protected ImsMmTelManager getImsMmTelManager(int subId) {
             return mMockImsMmTelManager;
         }
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
index 32cec68..e639b67 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
@@ -160,7 +160,7 @@
         // Set controller band index to 5GHz and verify is set.
         mController.displayPreference(mScreen);
         mController.onPreferenceChange(mPreference, VAL_5GHZ_STR);
-        assertThat(mController.getBandIndex()).isEqualTo(VAL_5GHZ_INT);
+        assertThat(mController.getBandIndex()).isEqualTo(VAL_2_5_GHZ_INT);
 
         // Disable 5Ghz band
         when(mWifiManager.is5GHzBandSupported()).thenReturn(false);