Merge "Use inline radio buttons for Prevent Ringing"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index aa98c62..efa57de 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1161,7 +1161,7 @@
         <activity
             android:name="Settings$LocationSettingsActivity"
             android:label="@string/location_settings_title"
-            android:icon="@drawable/ic_settings_location"
+            android:icon="@drawable/ic_homepage_location"
             android:configChanges="orientation|keyboardHidden|screenSize"
             android:parentActivityName="Settings">
             <intent-filter android:priority="1">
@@ -1180,7 +1180,7 @@
         <activity
             android:name="Settings$ScanningSettingsActivity"
             android:label="@string/location_scanning_screen_title"
-            android:icon="@drawable/ic_settings_location"
+            android:icon="@drawable/ic_homepage_location"
             android:configChanges="orientation|keyboardHidden|screenSize"
             android:parentActivityName="Settings">
             <intent-filter android:priority="1">
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 62c7915..d28f2d1 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -1221,11 +1221,27 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;homepage_location_background&quot;>#1A73E8&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="128"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="    &lt;color name=&quot;battery_good_color_light&quot;>#43a047&lt;/color> &lt;!-- Material Green 600 -->"
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="132"
+            line="133"
             column="5"/>
     </issue>
 
@@ -1241,7 +1257,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="133"
+            line="134"
             column="5"/>
     </issue>
 
@@ -1257,7 +1273,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="134"
+            line="135"
             column="5"/>
     </issue>
 
@@ -1273,7 +1289,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="135"
+            line="136"
             column="5"/>
     </issue>
 
@@ -1289,7 +1305,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="136"
+            line="137"
             column="5"/>
     </issue>
 
@@ -1305,7 +1321,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="137"
+            line="138"
             column="5"/>
     </issue>
 
@@ -1321,7 +1337,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="140"
+            line="141"
             column="5"/>
     </issue>
 
@@ -1337,7 +1353,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="141"
+            line="142"
             column="5"/>
     </issue>
 
@@ -1353,7 +1369,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="142"
+            line="143"
             column="5"/>
     </issue>
 
@@ -1369,7 +1385,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="143"
+            line="144"
             column="5"/>
     </issue>
 
@@ -1385,7 +1401,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="144"
+            line="145"
             column="5"/>
     </issue>
 
@@ -1861,6 +1877,38 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="                android:color=&quot;@color/homepage_location_background&quot; />"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_homepage_location.xml"
+            line="23"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="                android:color=&quot;@color/homepage_location_background&quot; />"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_preference_location.xml"
+            line="23"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="                android:color=&quot;@color/homepage_support_background&quot; />"
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
diff --git a/proguard.flags b/proguard.flags
index 82e8e58..b66a786 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -60,4 +60,9 @@
 # Keep classes that implements CustomSliceable, which are used by reflection.
 -keepclasseswithmembers class * implements com.android.settings.slices.CustomSliceable {
     public <init>(android.content.Context);
-}
\ No newline at end of file
+}
+
+# Keep classes that extends SliceBackgroundWorker, which are used by reflection.
+-keepclasseswithmembers class * extends com.android.settings.slices.SliceBackgroundWorker {
+    public <init>(android.content.Context, android.net.Uri);
+}
diff --git a/res/drawable/ic_content_copy_grey600_24dp.xml b/res/drawable/ic_content_copy_grey600_24dp.xml
new file mode 100644
index 0000000..827c66e
--- /dev/null
+++ b/res/drawable/ic_content_copy_grey600_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"
+      android:fillColor="#757575"/>
+</vector>
diff --git a/res/drawable/ic_homepage_location.xml b/res/drawable/ic_homepage_location.xml
new file mode 100644
index 0000000..413801b
--- /dev/null
+++ b/res/drawable/ic_homepage_location.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item>
+        <shape android:shape="oval">
+            <solid
+                android:color="@color/homepage_location_background"/>
+            <size
+                android:width="@dimen/dashboard_tile_image_size"
+                android:height="@dimen/dashboard_tile_image_size"/>
+        </shape>
+    </item>
+
+    <item
+        android:width="@dimen/dashboard_tile_foreground_image_size"
+        android:height="@dimen/dashboard_tile_foreground_image_size"
+        android:start="@dimen/dashboard_tile_foreground_image_inset"
+        android:top="@dimen/dashboard_tile_foreground_image_inset"
+        android:drawable="@drawable/ic_settings_location"/>
+</layer-list>
diff --git a/res/drawable/ic_preference_location.xml b/res/drawable/ic_preference_location.xml
new file mode 100644
index 0000000..e37d629
--- /dev/null
+++ b/res/drawable/ic_preference_location.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item>
+        <shape android:shape="oval">
+            <solid
+                android:color="@color/homepage_location_background"/>
+            <size
+                android:width="@android:dimen/app_icon_size"
+                android:height="@android:dimen/app_icon_size"/>
+        </shape>
+    </item>
+
+    <item
+        android:width="@dimen/dashboard_tile_foreground_image_size"
+        android:height="@dimen/dashboard_tile_foreground_image_size"
+        android:start="@dimen/preference_icon_foreground_image_inset"
+        android:top="@dimen/preference_icon_foreground_image_inset"
+        android:drawable="@drawable/ic_settings_location"/>
+</layer-list>
diff --git a/res/drawable/ic_settings_location.xml b/res/drawable/ic_settings_location.xml
index 34bd4f0..b7cfd6f 100644
--- a/res/drawable/ic_settings_location.xml
+++ b/res/drawable/ic_settings_location.xml
@@ -17,8 +17,7 @@
         android:width="24.0dp"
         android:height="24.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index f398d92..a00fd8a 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -125,6 +125,7 @@
     <color name="homepage_system_background">#757575</color>
     <color name="homepage_support_background">#26459C</color>
     <color name="homepage_generic_icon_background">#1A73E8</color>
+    <color name="homepage_location_background">#2EC7DC</color>
     <!-- End of dashboard/homepage icon background colors -->
 
     <color name="glif_error_color">@*android:color/material_red_A700</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e163f7f..18bcc38 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -88,6 +88,9 @@
     <!-- Dashboard foreground image inset (from background edge to foreground edge) -->
     <dimen name="dashboard_tile_foreground_image_inset">6dp</dimen>
 
+    <!-- Preference icon foreground image inset (from background edge to foreground edge) -->
+    <dimen name="preference_icon_foreground_image_inset">12dp</dimen>
+
     <!-- SwitchBar sub settings margin start / end -->
     <dimen name="switchbar_subsettings_margin_start">72dp</dimen>
     <dimen name="switchbar_subsettings_margin_end">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 462f7ff..e14135c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -814,11 +814,13 @@
     <string name="location_settings_title">Location</string>
     <!-- Used in the location settings to control turning on/off the feature entirely -->
     <string name="location_settings_master_switch_title">Use location</string>
+    <!-- Summary for Location settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
+    <string name="location_settings_summary">Scanning, location history</string>
 
     <!-- Main Settings screen setting option title for the item to take you to the accounts screen [CHAR LIMIT=22] -->
     <string name="account_settings_title">Accounts</string>
     <!-- Main Settings screen setting option title for the item to take you to the security screen -->
-    <string name="security_settings_title">Security &amp; location</string>
+    <string name="security_settings_title">Security</string>
     <!-- Security Settings screen setting option title for the item to take you to the encryption and credential screen -->
     <string name="encryption_and_credential_settings_title">Encryption &amp; credentials</string>
     <!-- Security Settings screen Encryption and crendential summary -->
@@ -7278,9 +7280,9 @@
     <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
     <string name="zen_mode_block_effect_peek">Don\'t pop notifications on screen</string>
     <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
-    <string name="zen_mode_block_effect_status">Hide status bar icons</string>
+    <string name="zen_mode_block_effect_status">Hide status bar icons at top of screen</string>
     <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
-    <string name="zen_mode_block_effect_badge">Hide notification dots</string>
+    <string name="zen_mode_block_effect_badge">Hide notification dots on app icons</string>
     <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
     <string name="zen_mode_block_effect_ambient">Don\'t wake for notifications</string>
     <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
@@ -8943,12 +8945,6 @@
     <!-- Summary of payment screen [CHAR LIMIT=NONE] -->
     <string name="payment_summary"><xliff:g id="app_name" example="Payment App">%1$s</xliff:g> is default</string>
 
-    <!-- Summary of location on screen [CHAR LIMIT=NONE] -->
-    <string name="location_on_summary">On</string>
-
-    <!-- Location off [CHAR LIMIT=NONE] -->
-    <string name="location_off_summary">Off</string>
-
     <!-- Backup disabled summary [CHAR LIMIT=NONE] -->
     <string name="backup_disabled">Back up disabled</string>
 
diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml
index e543ad9..ce271cc 100644
--- a/res/xml/security_dashboard_settings.xml
+++ b/res/xml/security_dashboard_settings.xml
@@ -95,12 +95,6 @@
         android:key="security_settings_misc_category"
         android:title="@string/security_passwords_title">
 
-        <Preference
-            android:key="location"
-            android:title="@string/location_settings_title"
-            android:summary="@string/summary_placeholder"
-            android:fragment="com.android.settings.location.LocationSettings" />
-
         <SwitchPreference
             android:key="show_password"
             android:title="@string/show_password"
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index e11d84a..b5930e4 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -26,7 +26,7 @@
         android:title="@string/network_dashboard_title"
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_homepage_network"
-        android:order="-110"
+        android:order="-120"
         android:fragment="com.android.settings.network.NetworkDashboardFragment"
         settings:controller="com.android.settings.network.TopLevelNetworkEntryPreferenceController"/>
 
@@ -35,7 +35,7 @@
         android:title="@string/connected_devices_dashboard_title"
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_homepage_connected_device"
-        android:order="-100"
+        android:order="-110"
         android:fragment="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"
         settings:controller="com.android.settings.connecteddevice.TopLevelConnectedDevicesPreferenceController"/>
 
@@ -44,7 +44,7 @@
         android:title="@string/app_and_notification_dashboard_title"
         android:summary="@string/app_and_notification_dashboard_summary"
         android:icon="@drawable/ic_homepage_apps"
-        android:order="-90"
+        android:order="-100"
         android:fragment="com.android.settings.applications.AppAndNotificationDashboardFragment"/>
 
     <Preference
@@ -53,7 +53,7 @@
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_homepage_battery"
         android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
-        android:order="-80"
+        android:order="-90"
         settings:controller="com.android.settings.fuelgauge.TopLevelBatteryPreferenceController"/>
 
     <Preference
@@ -61,7 +61,7 @@
         android:title="@string/display_settings"
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_homepage_display"
-        android:order="-70"
+        android:order="-80"
         android:fragment="com.android.settings.DisplaySettings"
         settings:controller="com.android.settings.display.TopLevelDisplayPreferenceController"/>
 
@@ -70,7 +70,7 @@
         android:title="@string/sound_settings"
         android:summary="@string/sound_dashboard_summary"
         android:icon="@drawable/ic_homepage_sound"
-        android:order="-60"
+        android:order="-70"
         android:fragment="com.android.settings.notification.SoundSettings"/>
 
     <Preference
@@ -78,11 +78,19 @@
         android:title="@string/storage_settings"
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_homepage_storage"
-        android:order="-50"
+        android:order="-60"
         android:fragment="com.android.settings.deviceinfo.StorageSettings"
         settings:controller="com.android.settings.deviceinfo.TopLevelStoragePreferenceController"/>
 
     <Preference
+        android:key="top_level_location"
+        android:title="@string/location_settings_title"
+        android:summary="@string/location_settings_summary"
+        android:icon="@drawable/ic_homepage_location"
+        android:order="-50"
+        android:fragment="com.android.settings.location.LocationSettings"/>
+
+    <Preference
         android:key="top_level_security"
         android:title="@string/security_settings_title"
         android:summary="@string/summary_placeholder"
diff --git a/res/xml/wifi_settings.xml b/res/xml/wifi_settings.xml
index 4ca9284..516ac0a 100644
--- a/res/xml/wifi_settings.xml
+++ b/res/xml/wifi_settings.xml
@@ -20,6 +20,9 @@
         android:title="@string/wifi_settings"
         settings:keywords="@string/keywords_wifi">
 
+    <com.android.settings.wifi.LinkablePreference
+        android:key="wifi_status_message"/>
+
     <PreferenceCategory
         android:key="connected_access_point"
         android:layout="@layout/preference_category_no_label"/>
@@ -28,17 +31,14 @@
         android:key="access_points"
         android:layout="@layout/preference_category_no_label"/>
 
-    <PreferenceCategory
-        android:key="additional_settings"
-        android:layout="@layout/preference_category_no_label">
-        <Preference
-                android:key="configure_settings"
-                android:title="@string/wifi_configure_settings_preference_title"
-                android:fragment="com.android.settings.wifi.ConfigureWifiSettings" />
+    <Preference
+        android:key="configure_settings"
+        android:title="@string/wifi_configure_settings_preference_title"
+        settings:allowDividerAbove="true"
+        android:fragment="com.android.settings.wifi.ConfigureWifiSettings"/>
 
-        <Preference
-                android:key="saved_networks"
-                android:title="@string/wifi_saved_access_points_label"
-                android:fragment="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings" />
-    </PreferenceCategory>
+    <Preference
+        android:key="saved_networks"
+        android:title="@string/wifi_saved_access_points_label"
+        android:fragment="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings"/>
 </PreferenceScreen>
diff --git a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
index 18e9906..78a8614 100644
--- a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
@@ -92,18 +92,18 @@
 
     @VisibleForTesting
     void finishIfAccountMissing() {
-        AccountManager accountManager = (AccountManager) getContext().getSystemService(
-                Context.ACCOUNT_SERVICE);
-        boolean accountExists = false;
-        for (Account account : accountManager.getAccountsByType(mAccount.type)) {
-            if (account.equals(mAccount)) {
-                accountExists = true;
-                break;
+        final Context context = getContext();
+        final UserManager um = context.getSystemService(UserManager.class);
+        final AccountManager accountManager = (AccountManager) context.getSystemService(
+                AccountManager.class);
+        for (UserHandle userHandle : um.getUserProfiles()) {
+            for (Account account : accountManager.getAccountsAsUser(userHandle.getIdentifier())) {
+                if (account.equals(mAccount)) {
+                    return;
+                }
             }
         }
-        if (!accountExists) {
-            finish();
-        }
+        finish();
     }
 
     @Override
@@ -177,4 +177,4 @@
             accountTypePreferenceLoader.updatePreferenceIntents(prefs, mAccountType, mAccount);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
index a4cfebf..70ffcb3 100644
--- a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
@@ -21,6 +21,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.provider.Settings;
 import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
@@ -34,8 +35,7 @@
 public class TimeSpentInAppPreferenceController extends BasePreferenceController {
 
     @VisibleForTesting
-    static final Intent SEE_TIME_IN_APP_TEMPLATE =
-            new Intent("com.android.settings.action.TIME_SPENT_IN_APP");
+    static final Intent SEE_TIME_IN_APP_TEMPLATE = new Intent(Settings.ACTION_APP_USAGE_SETTINGS);
 
     private final PackageManager mPackageManager;
 
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 2d95c31..65181c4 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -63,7 +63,7 @@
         implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy {
     @VisibleForTesting
     static final boolean USE_FAKE_DATA = false;
-    private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
+    private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 20;
     private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
     private static final int STATS_TYPE = BatteryStats.STATS_SINCE_CHARGED;
 
diff --git a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
index 647d718..0065f5c 100644
--- a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.homepage.contextualcards;
 
+import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
@@ -30,7 +31,7 @@
 public class CardDatabaseHelper extends SQLiteOpenHelper {
     private static final String TAG = "CardDatabaseHelper";
     private static final String DATABASE_NAME = "homepage_cards.db";
-    private static final int DATABASE_VERSION = 4;
+    private static final int DATABASE_VERSION = 5;
 
     public static final String CARD_TABLE = "cards";
 
@@ -119,6 +120,11 @@
          * Decide the card display full-length width or half-width in screen.
          */
         String SUPPORT_HALF_WIDTH = "support_half_width";
+
+        /**
+         * Decide the card is dismissed or not.
+         */
+        String CARD_DISMISSED = "card_dismissed";
     }
 
     private static final String CREATE_CARD_TABLE =
@@ -157,6 +163,8 @@
                     CardColumns.EXPIRE_TIME_MS +
                     " INTEGER, " +
                     CardColumns.SUPPORT_HALF_WIDTH +
+                    " INTEGER DEFAULT 0, " +
+                    CardColumns.CARD_DISMISSED +
                     " INTEGER DEFAULT 0 " +
                     ");";
 
@@ -190,9 +198,27 @@
 
     Cursor getContextualCards() {
         final SQLiteDatabase db = this.getReadableDatabase();
-        Cursor cursor = db.query(CARD_TABLE, null /* columns */, null /* selection */,
+        final String selection = CardColumns.CARD_DISMISSED + "=0";
+        Cursor cursor = db.query(CARD_TABLE, null /* columns */, selection,
                 null /* selectionArgs */, null /* groupBy */, null /* having */,
                 null /* orderBy */);
         return cursor;
     }
+
+    /**
+     * Mark a specific ContextualCard with dismissal flag in the database to indicate that the
+     * card has been dismissed.
+     *
+     * @param cardName the card name of the ContextualCard which is dismissed by user.
+     * @return updated row number
+     */
+    public int markContextualCardAsDismissed(String cardName) {
+        final SQLiteDatabase database = this.getWritableDatabase();
+        final ContentValues values = new ContentValues();
+        values.put(CardColumns.CARD_DISMISSED, 1);
+        final String selection = CardColumns.NAME + "=?";
+        final String[] selectionArgs = {cardName};
+        final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs);
+        return rowsUpdated;
+    }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 51bef87..9bd08c8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -84,7 +84,7 @@
         final CardContentLoaderCallbacks cardContentLoaderCallbacks =
                 new CardContentLoaderCallbacks(mContext);
         cardContentLoaderCallbacks.setListener(this);
-        LoaderManager.getInstance(fragment).initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
+        LoaderManager.getInstance(fragment).restartLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
                 cardContentLoaderCallbacks);
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index d82fdfe..29eea4b 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -43,6 +43,11 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle());
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
         mContextualCardManager.loadContextualCards(this);
     }
 
diff --git a/src/com/android/settings/location/LocationPreferenceController.java b/src/com/android/settings/location/LocationPreferenceController.java
deleted file mode 100644
index 0efc2b1..0000000
--- a/src/com/android/settings/location/LocationPreferenceController.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.location;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.LocationManager;
-import android.provider.Settings.Secure;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-
-public class LocationPreferenceController extends AbstractPreferenceController
-        implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
-
-    private static final String KEY_LOCATION = "location";
-    private Context mContext;
-    private Preference mPreference;
-
-    @VisibleForTesting
-    BroadcastReceiver mLocationProvidersChangedReceiver;
-
-    public LocationPreferenceController(Context context, Lifecycle lifecycle) {
-        super(context);
-        mContext = context;
-        mLocationProvidersChangedReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (intent.getAction().equals(LocationManager.PROVIDERS_CHANGED_ACTION)) {
-                    updateSummary();
-                }
-            }
-        };
-        if (lifecycle != null) {
-            lifecycle.addObserver(this);
-        }
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mPreference = screen.findPreference(KEY_LOCATION);
-    }
-
-    @Override
-    public void onResume() {
-        if (mLocationProvidersChangedReceiver != null) {
-            mContext.registerReceiver(mLocationProvidersChangedReceiver, new IntentFilter(
-                    LocationManager.PROVIDERS_CHANGED_ACTION));
-        }
-    }
-
-    @Override
-    public void onPause() {
-        if (mLocationProvidersChangedReceiver != null) {
-            mContext.unregisterReceiver(mLocationProvidersChangedReceiver);
-        }
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        preference.setSummary(getLocationSummary(mContext));
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_LOCATION;
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return true;
-    }
-
-    public void updateSummary() {
-        updateState(mPreference);
-    }
-
-    public static String getLocationSummary(Context context) {
-        int mode = Secure.getInt(context.getContentResolver(),
-                Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF);
-        if (mode != Secure.LOCATION_MODE_OFF) {
-            return context.getString(R.string.location_on_summary);
-        }
-        return context.getString(R.string.location_off_summary);
-    }
-}
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 758ca57..53076e8 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -133,34 +133,6 @@
         return controllers;
     }
 
-    private static class SummaryProvider implements SummaryLoader.SummaryProvider {
-
-        private final Context mContext;
-        private final SummaryLoader mSummaryLoader;
-
-        public SummaryProvider(Context context, SummaryLoader summaryLoader) {
-            mContext = context;
-            mSummaryLoader = summaryLoader;
-        }
-
-        @Override
-        public void setListening(boolean listening) {
-            if (listening) {
-                mSummaryLoader.setSummary(
-                    this, LocationPreferenceController.getLocationSummary(mContext));
-            }
-        }
-    }
-
-    public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
-            = new SummaryLoader.SummaryProviderFactory() {
-        @Override
-        public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
-                                                                   SummaryLoader summaryLoader) {
-            return new SummaryProvider(activity, summaryLoader);
-        }
-    };
-
     /**
      * For Search.
      */
diff --git a/src/com/android/settings/network/telephony/ApnPreferenceController.java b/src/com/android/settings/network/telephony/ApnPreferenceController.java
index e02d9d4..f5cd140 100644
--- a/src/com/android/settings/network/telephony/ApnPreferenceController.java
+++ b/src/com/android/settings/network/telephony/ApnPreferenceController.java
@@ -62,12 +62,13 @@
     public int getAvailabilityStatus() {
         final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
         final boolean isCdmaApn = MobileNetworkUtils.isCdmaOptions(mContext, mSubId)
+                && carrierConfig != null
                 && carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL);
         final boolean isGsmApn = MobileNetworkUtils.isGsmOptions(mContext, mSubId)
+                && carrierConfig != null
                 && carrierConfig.getBoolean(CarrierConfigManager.KEY_APN_EXPAND_BOOL);
 
-        return carrierConfig != null
-                && (isCdmaApn || isGsmApn)
+        return isCdmaApn || isGsmApn
                 ? AVAILABLE
                 : CONDITIONALLY_UNAVAILABLE;
     }
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
index 18415c7..41eb111 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
@@ -24,13 +24,10 @@
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.service.notification.ZenModeConfig;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.view.View;
 
-import androidx.fragment.app.Fragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceFragmentCompat;
-
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.applications.LayoutPreference;
@@ -38,6 +35,10 @@
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+
 public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModePreferenceController
         implements PreferenceControllerMixin {
 
@@ -128,9 +129,13 @@
 
         @Override
         public void onOk(String ruleName, Fragment parent) {
+            if (TextUtils.equals(ruleName, mRule.getName())) {
+                return;
+            }
             mMetricsFeatureProvider.action(mContext,
                     MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
             mRule.setName(ruleName);
+            mRule.setModified(true);
             mBackend.setZenRule(mId, mRule);
         }
     }
diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java
index eb0d6f1..e00d387 100644
--- a/src/com/android/settings/security/SecuritySettings.java
+++ b/src/com/android/settings/security/SecuritySettings.java
@@ -29,7 +29,6 @@
 import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.enterprise.EnterprisePrivacyPreferenceController;
-import com.android.settings.location.LocationPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.security.trustagent.ManageTrustAgentsPreferenceController;
 import com.android.settings.security.trustagent.TrustAgentListPreferenceController;
@@ -105,7 +104,6 @@
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle, SecuritySettings host) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(new LocationPreferenceController(context, lifecycle));
         controllers.add(new EnterprisePrivacyPreferenceController(context));
         controllers.add(new ManageTrustAgentsPreferenceController(context));
         controllers.add(new ScreenPinningPreferenceController(context));
diff --git a/src/com/android/settings/slices/CopyableSlice.java b/src/com/android/settings/slices/CopyableSlice.java
new file mode 100644
index 0000000..31fc151
--- /dev/null
+++ b/src/com/android/settings/slices/CopyableSlice.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.slices;
+
+/**
+ * Provide the copy ability for preference controller to copy the data to the clipboard.
+ */
+public interface CopyableSlice {
+    /**
+     * Copy the key slice information to the clipboard.
+     * It is highly recommended to show the toast to notify users when implemented this function.
+     */
+    void copy();
+}
diff --git a/src/com/android/settings/slices/CustomSliceable.java b/src/com/android/settings/slices/CustomSliceable.java
index e09cc73..b538b89 100644
--- a/src/com/android/settings/slices/CustomSliceable.java
+++ b/src/com/android/settings/slices/CustomSliceable.java
@@ -91,11 +91,12 @@
 
     /**
      * Settings Slices which can represent component lists that are updatable by the
-     * {@link SliceBackgroundWorker} returned here.
+     * {@link SliceBackgroundWorker} class returned here.
      *
-     * @return a {@link SliceBackgroundWorker} for fetching the list of results in the background.
+     * @return a {@link SliceBackgroundWorker} class for fetching the list of results in the
+     * background.
      */
-    default SliceBackgroundWorker getBackgroundWorker() {
+    default Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
         return null;
     }
 
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 3911603..fa669bb 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -52,7 +52,6 @@
 import com.android.settingslib.SliceBroadcastRelay;
 import com.android.settingslib.utils.ThreadUtils;
 
-import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -108,6 +107,12 @@
             "com.android.settings.slice.action.SLIDER_CHANGED";
 
     /**
+     * Action passed for copy data for the Copyable Slices.
+     */
+    public static final String ACTION_COPY =
+            "com.android.settings.slice.action.COPY";
+
+    /**
      * Intent Extra passed for the key identifying the Setting Slice.
      */
     public static final String EXTRA_SLICE_KEY = "com.android.settings.slice.extra.key";
@@ -134,8 +139,7 @@
 
     final Set<Uri> mRegisteredUris = new ArraySet<>();
 
-    final Map<Uri, SliceBackgroundWorker> mWorkerMap = new ArrayMap<>();
-    final Set<SliceBackgroundWorker> mLiveWorkers = new ArraySet<>();
+    final Map<Uri, SliceBackgroundWorker> mPinnedWorkers = new ArrayMap<>();
 
     public SettingsSliceProvider() {
         super(READ_SEARCH_INDEXABLES);
@@ -365,45 +369,37 @@
     }
 
     private void startBackgroundWorker(CustomSliceable sliceable) {
-        final SliceBackgroundWorker worker = sliceable.getBackgroundWorker();
-        if (worker == null) {
+        final Class workerClass = sliceable.getBackgroundWorkerClass();
+        if (workerClass == null) {
             return;
         }
 
         final Uri uri = sliceable.getUri();
-        if (mWorkerMap.containsKey(uri)) {
+        if (mPinnedWorkers.containsKey(uri)) {
             return;
         }
 
         Log.d(TAG, "Starting background worker for: " + uri);
-        mWorkerMap.put(uri, worker);
-        if (!mLiveWorkers.contains(worker)) {
-            mLiveWorkers.add(worker);
-        }
+        final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(
+                getContext(), sliceable);
+        mPinnedWorkers.put(uri, worker);
         worker.onSlicePinned();
     }
 
     private void stopBackgroundWorker(Uri uri) {
-        final SliceBackgroundWorker worker = mWorkerMap.get(uri);
+        final SliceBackgroundWorker worker = mPinnedWorkers.get(uri);
         if (worker != null) {
             Log.d(TAG, "Stopping background worker for: " + uri);
             worker.onSliceUnpinned();
-            mWorkerMap.remove(uri);
+            mPinnedWorkers.remove(uri);
         }
     }
 
     @Override
     public void shutdown() {
-        for (SliceBackgroundWorker worker : mLiveWorkers) {
-            ThreadUtils.postOnMainThread(() -> {
-                try {
-                    worker.close();
-                } catch (IOException e) {
-                    Log.w(TAG, "Exception when shutting down worker", e);
-                }
-            });
-        }
-        mLiveWorkers.clear();
+        ThreadUtils.postOnMainThread(() -> {
+            SliceBackgroundWorker.shutdown();
+        });
     }
 
     private List<Uri> buildUrisFromKeys(List<String> keys, String authority) {
@@ -532,4 +528,4 @@
         }
         return new String[0];
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/slices/SliceBackgroundWorker.java b/src/com/android/settings/slices/SliceBackgroundWorker.java
index 422fcc7..a663ece 100644
--- a/src/com/android/settings/slices/SliceBackgroundWorker.java
+++ b/src/com/android/settings/slices/SliceBackgroundWorker.java
@@ -17,36 +17,87 @@
 package com.android.settings.slices;
 
 import android.annotation.MainThread;
-import android.content.ContentResolver;
+import android.content.Context;
 import android.net.Uri;
+import android.util.ArrayMap;
+import android.util.Log;
 
 import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * The Slice background worker is used to make Settings Slices be able to work with data that is
  * changing continuously, e.g. available Wi-Fi networks.
  *
- * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, and be
- * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}.
+ * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, be
+ * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}, and be closed at {@link
+ * SettingsSliceProvider#shutdown()}.
  *
  * {@link SliceBackgroundWorker} caches the results, uses the cache to compare if there is any data
  * changed, and then notifies the Slice {@link Uri} to update.
+ *
+ * It also stores all instances of all workers to ensure each worker is a Singleton.
  */
 public abstract class SliceBackgroundWorker<E> implements Closeable {
 
-    private final ContentResolver mContentResolver;
+    private static final String TAG = "SliceBackgroundWorker";
+
+    private static final Map<Uri, SliceBackgroundWorker> LIVE_WORKERS = new ArrayMap<>();
+
+    private final Context mContext;
     private final Uri mUri;
 
     private List<E> mCachedResults;
 
-    protected SliceBackgroundWorker(ContentResolver cr, Uri uri) {
-        mContentResolver = cr;
+    protected SliceBackgroundWorker(Context context, Uri uri) {
+        mContext = context;
         mUri = uri;
     }
 
     /**
+     * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link
+     * CustomSliceable}
+     */
+    public static SliceBackgroundWorker getInstance(Context context, CustomSliceable sliceable) {
+        final Uri uri = sliceable.getUri();
+        final Class<? extends SliceBackgroundWorker> workerClass =
+                sliceable.getBackgroundWorkerClass();
+        SliceBackgroundWorker worker = LIVE_WORKERS.get(uri);
+        if (worker == null) {
+            worker = createInstance(context, uri, workerClass);
+            LIVE_WORKERS.put(uri, worker);
+        }
+        return worker;
+    }
+
+    private static SliceBackgroundWorker createInstance(Context context, Uri uri,
+            Class<? extends SliceBackgroundWorker> clazz) {
+        Log.d(TAG, "create instance: " + clazz);
+        try {
+            return clazz.getConstructor(Context.class, Uri.class).newInstance(context, uri);
+        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException |
+                InvocationTargetException e) {
+            throw new IllegalStateException(
+                    "Invalid slice background worker: " + clazz, e);
+        }
+    }
+
+    static void shutdown() {
+        for (SliceBackgroundWorker worker : LIVE_WORKERS.values()) {
+            try {
+                worker.close();
+            } catch (IOException e) {
+                Log.w(TAG, "Shutting down worker failed", e);
+            }
+        }
+        LIVE_WORKERS.clear();
+    }
+
+    /**
      * Called when the Slice is pinned. This is the place to register callbacks or initialize scan
      * tasks.
      */
@@ -83,7 +134,7 @@
 
         if (needNotify) {
             mCachedResults = results;
-            mContentResolver.notifyChange(mUri, null);
+            mContext.getContentResolver().notifyChange(mUri, null);
         }
     }
 }
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index e9e9d2c..4b86f33 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -24,6 +24,7 @@
 import static com.android.settings.notification.ZenModeSliceBuilder.ACTION_ZEN_MODE_SLICE_CHANGED;
 import static com.android.settings.slices.SettingsSliceProvider.ACTION_SLIDER_CHANGED;
 import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CHANGED;
+import static com.android.settings.slices.SettingsSliceProvider.ACTION_COPY;
 import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
 import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED;
 import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED;
@@ -115,6 +116,9 @@
             case ACTION_FLASHLIGHT_SLICE_CHANGED:
                 FlashlightSliceBuilder.handleUriChange(context, intent);
                 break;
+            case ACTION_COPY:
+                handleCopyAction(context, key, isPlatformSlice);
+                break;
         }
     }
 
@@ -184,6 +188,29 @@
         updateUri(context, key, isPlatformSlice);
     }
 
+    private void handleCopyAction(Context context, String key, boolean isPlatformSlice) {
+        if (TextUtils.isEmpty(key)) {
+            throw new IllegalArgumentException("No key passed to Intent for controller");
+        }
+
+        final BasePreferenceController controller = getPreferenceController(context, key);
+
+        if (!(controller instanceof CopyableSlice)) {
+            throw new IllegalArgumentException(
+                    "Copyable action passed for a non-copyable key:" + key);
+        }
+
+        if (!controller.isAvailable()) {
+            Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
+            if (!controller.hasAsyncUpdate()) {
+                updateUri(context, key, isPlatformSlice);
+            }
+            return;
+        }
+
+        ((CopyableSlice) controller).copy();
+    }
+
     /**
      * Log Slice value update events into MetricsFeatureProvider. The logging schema generally
      * follows the pattern in SharedPreferenceLogger.
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index 2432cc6..f6cc57f 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -93,6 +93,10 @@
             return buildUnavailableSlice(context, sliceData);
         }
 
+        if (controller instanceof CopyableSlice) {
+            return buildCopyableSlice(context, sliceData, controller);
+        }
+
         switch (sliceData.getSliceType()) {
             case SliceData.SliceType.INTENT:
                 return buildIntentSlice(context, sliceData, controller);
@@ -324,6 +328,28 @@
                 .build();
     }
 
+    private static Slice buildCopyableSlice(Context context, SliceData sliceData,
+            BasePreferenceController controller) {
+        final SliceAction copyableAction = getCopyableAction(context, sliceData);
+        final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
+        final IconCompat icon = getSafeIcon(context, sliceData);
+        final SliceAction primaryAction = new SliceAction(contentIntent, icon,
+                sliceData.getTitle());
+        final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
+        @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
+        final Set<String> keywords = buildSliceKeywords(sliceData);
+
+        return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
+                .setAccentColor(color)
+                .addRow(new RowBuilder()
+                        .setTitle(sliceData.getTitle())
+                        .setSubtitle(subtitleText)
+                        .setPrimaryAction(primaryAction)
+                        .addEndItem(copyableAction))
+                .setKeywords(keywords)
+                .build();
+    }
+
     private static BasePreferenceController getPreferenceController(Context context,
             String controllerClassName, String controllerKey) {
         try {
@@ -346,6 +372,14 @@
         return getActionIntent(context, SettingsSliceProvider.ACTION_SLIDER_CHANGED, sliceData);
     }
 
+    private static SliceAction getCopyableAction(Context context, SliceData sliceData) {
+        final PendingIntent intent = getActionIntent(context,
+                SettingsSliceProvider.ACTION_COPY, sliceData);
+        final IconCompat icon = IconCompat.createWithResource(context,
+                R.drawable.ic_content_copy_grey600_24dp);
+        return new SliceAction(intent, icon, sliceData.getTitle());
+    }
+
     private static boolean isValidSummary(Context context, CharSequence summary) {
         if (summary == null || TextUtils.isEmpty(summary.toString().trim())) {
             return false;
diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java
index 866e5a8..cce871b 100644
--- a/src/com/android/settings/tts/TextToSpeechSettings.java
+++ b/src/com/android/settings/tts/TextToSpeechSettings.java
@@ -251,15 +251,20 @@
         mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
             @Override
             public void onStart(String utteranceId) {
+                updateWidgetState(false);
             }
 
             @Override
             public void onDone(String utteranceId) {
+                updateWidgetState(true);
             }
 
             @Override
             public void onError(String utteranceId) {
                 Log.e(TAG, "Error while trying to synthesize sample text");
+                // Re-enable just in case, although there isn't much hope that following synthesis
+                // requests are going to succeed.
+                updateWidgetState(true);
             }
         });
     }
@@ -696,9 +701,11 @@
     }
 
     private void updateWidgetState(boolean enable) {
-        mActionButtons.setButton1Enabled(enable);
-        mDefaultRatePref.setEnabled(enable);
-        mDefaultPitchPref.setEnabled(enable);
+        getActivity().runOnUiThread(() -> {
+            mActionButtons.setButton1Enabled(enable);
+            mDefaultRatePref.setEnabled(enable);
+            mDefaultPitchPref.setEnabled(enable);
+        });
     }
 
     private void displayNetworkAlert() {
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index a4e0cff..5f899eb 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -450,7 +450,7 @@
     private void addLocationAppRestrictionsPreference(AppRestrictionsHelper.SelectableAppInfo app,
             AppRestrictionsPreference p) {
         String packageName = app.packageName;
-        p.setIcon(R.drawable.ic_settings_location);
+        p.setIcon(R.drawable.ic_preference_location);
         p.setKey(getKeyForPackage(packageName));
         ArrayList<RestrictionEntry> restrictions = RestrictionUtils.getRestrictions(
                 getActivity(), mUser);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 4837a88..f097d5b 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -112,9 +112,9 @@
     private static final String PREF_KEY_EMPTY_WIFI_LIST = "wifi_empty_list";
     private static final String PREF_KEY_CONNECTED_ACCESS_POINTS = "connected_access_point";
     private static final String PREF_KEY_ACCESS_POINTS = "access_points";
-    private static final String PREF_KEY_ADDITIONAL_SETTINGS = "additional_settings";
     private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_settings";
     private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks";
+    private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message";
 
     private static boolean isVerboseLoggingEnabled() {
         return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE);
@@ -167,17 +167,19 @@
     private Bundle mAccessPointSavedState;
     private Bundle mWifiNfcDialogSavedState;
 
-    private WifiTracker mWifiTracker;
+    @VisibleForTesting
+    WifiTracker mWifiTracker;
     private String mOpenSsid;
 
     private AccessPointPreference.UserBadgeCache mUserBadgeCache;
 
     private PreferenceCategory mConnectedAccessPointPreferenceCategory;
     private PreferenceCategory mAccessPointsPreferenceCategory;
-    private PreferenceCategory mAdditionalSettingsPreferenceCategory;
     private Preference mAddPreference;
-    private Preference mConfigureWifiSettingsPreference;
-    private Preference mSavedNetworksPreference;
+    @VisibleForTesting
+    Preference mConfigureWifiSettingsPreference;
+    @VisibleForTesting
+    Preference mSavedNetworksPreference;
     private LinkablePreference mStatusMessagePreference;
 
     // For Search
@@ -229,8 +231,6 @@
                 (PreferenceCategory) findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS);
         mAccessPointsPreferenceCategory =
                 (PreferenceCategory) findPreference(PREF_KEY_ACCESS_POINTS);
-        mAdditionalSettingsPreferenceCategory =
-                (PreferenceCategory) findPreference(PREF_KEY_ADDITIONAL_SETTINGS);
         mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS);
         mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS);
 
@@ -238,7 +238,7 @@
         mAddPreference = new Preference(prefContext);
         mAddPreference.setIcon(R.drawable.ic_menu_add);
         mAddPreference.setTitle(R.string.wifi_add_network);
-        mStatusMessagePreference = new LinkablePreference(prefContext);
+        mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
 
         mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
     }
@@ -692,14 +692,14 @@
 
             case WifiManager.WIFI_STATE_ENABLING:
                 removeConnectedAccessPointPreference();
-                mAccessPointsPreferenceCategory.removeAll();
+                removeAccessPointPreference();
                 addMessagePreference(R.string.wifi_starting);
                 setProgressBarVisible(true);
                 break;
 
             case WifiManager.WIFI_STATE_DISABLING:
                 removeConnectedAccessPointPreference();
-                mAccessPointsPreferenceCategory.removeAll();
+                removeAccessPointPreference();
                 addMessagePreference(R.string.wifi_stopping);
                 break;
 
@@ -746,7 +746,10 @@
         }
 
         boolean hasAvailableAccessPoints = false;
-        mAccessPointsPreferenceCategory.removePreference(mStatusMessagePreference);
+        mStatusMessagePreference.setVisible(false);
+        mConnectedAccessPointPreferenceCategory.setVisible(true);
+        mAccessPointsPreferenceCategory.setVisible(true);
+
         cacheRemoveAllPrefs(mAccessPointsPreferenceCategory);
 
         int index =
@@ -960,26 +963,28 @@
         unregisterCaptivePortalNetworkCallback();
     }
 
-    private void setAdditionalSettingsSummaries() {
-        mAdditionalSettingsPreferenceCategory.addPreference(mConfigureWifiSettingsPreference);
+    private void removeAccessPointPreference() {
+        mAccessPointsPreferenceCategory.removeAll();
+        mAccessPointsPreferenceCategory.setVisible(false);
+    }
+
+    @VisibleForTesting
+    void setAdditionalSettingsSummaries() {
         mConfigureWifiSettingsPreference.setSummary(getString(
                 isWifiWakeupEnabled()
                         ? R.string.wifi_configure_settings_preference_summary_wakeup_on
                         : R.string.wifi_configure_settings_preference_summary_wakeup_off));
-        int numSavedNetworks = mWifiTracker.getNumSavedNetworks();
-        if (numSavedNetworks > 0) {
-            mAdditionalSettingsPreferenceCategory.addPreference(mSavedNetworksPreference);
-            mSavedNetworksPreference.setSummary(
-                    getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary,
-                            numSavedNetworks, numSavedNetworks));
-        } else {
-            mAdditionalSettingsPreferenceCategory.removePreference(mSavedNetworksPreference);
-        }
+        final int numSavedNetworks = mWifiTracker.getNumSavedNetworks();
+        mSavedNetworksPreference.setVisible(numSavedNetworks > 0);
+        mSavedNetworksPreference.setSummary(
+                getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary,
+                        numSavedNetworks, numSavedNetworks));
     }
 
     private boolean isWifiWakeupEnabled() {
-        PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
-        ContentResolver contentResolver = getContentResolver();
+        final Context context = getContext();
+        final PowerManager powerManager = context.getSystemService(PowerManager.class);
+        final ContentResolver contentResolver = context.getContentResolver();
         return Settings.Global.getInt(contentResolver,
                 Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1
                 && Settings.Global.getInt(contentResolver,
@@ -1006,15 +1011,14 @@
                         .launch();
         mStatusMessagePreference.setText(title, description, clickListener);
         removeConnectedAccessPointPreference();
-        mAccessPointsPreferenceCategory.removeAll();
-        mAccessPointsPreferenceCategory.addPreference(mStatusMessagePreference);
+        removeAccessPointPreference();
+        mStatusMessagePreference.setVisible(true);
     }
 
     private void addMessagePreference(int messageId) {
         mStatusMessagePreference.setTitle(messageId);
-        removeConnectedAccessPointPreference();
-        mAccessPointsPreferenceCategory.removeAll();
-        mAccessPointsPreferenceCategory.addPreference(mStatusMessagePreference);
+        mStatusMessagePreference.setVisible(true);
+
     }
 
     protected void setProgressBarVisible(boolean visible) {
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/WifiSlice.java
index 43f5372..d06d830 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/WifiSlice.java
@@ -121,7 +121,7 @@
             return listBuilder.build();
         }
 
-        List<AccessPoint> results = getBackgroundWorker().getResults();
+        List<AccessPoint> results = SliceBackgroundWorker.getInstance(mContext, this).getResults();
         if (results == null) {
             results = new ArrayList<>();
         }
@@ -264,36 +264,27 @@
     }
 
     @Override
-    public SliceBackgroundWorker getBackgroundWorker() {
-        return WifiScanWorker.getInstance(mContext, WIFI_URI);
+    public Class getBackgroundWorkerClass() {
+        return WifiScanWorker.class;
     }
 
-    private static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint>
+    public static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint>
             implements WifiTracker.WifiListener {
 
-        // TODO: enforce all the SliceBackgroundWorkers being singletons at syntax level
-        private static WifiScanWorker mWifiScanWorker;
-
         private final Context mContext;
 
         private WifiTracker mWifiTracker;
 
-        private WifiScanWorker(Context context, Uri uri) {
-            super(context.getContentResolver(), uri);
+        public WifiScanWorker(Context context, Uri uri) {
+            super(context, uri);
             mContext = context;
         }
 
-        public static WifiScanWorker getInstance(Context context, Uri uri) {
-            if (mWifiScanWorker == null) {
-                mWifiScanWorker = new WifiScanWorker(context, uri);
-            }
-            return mWifiScanWorker;
-        }
-
         @Override
         protected void onSlicePinned() {
             if (mWifiTracker == null) {
-                mWifiTracker = new WifiTracker(mContext, this, true, true);
+                mWifiTracker = new WifiTracker(mContext, this /* wifiListener */,
+                        true /* includeSaved */, true /* includeScans */);
             }
             mWifiTracker.onStart();
             onAccessPointsChanged();
@@ -307,7 +298,6 @@
         @Override
         public void close() {
             mWifiTracker.onDestroy();
-            mWifiScanWorker = null;
         }
 
         @Override
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
index a4d1567..2648916 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
@@ -35,8 +35,10 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.os.UserManager;
 
 import androidx.fragment.app.FragmentActivity;
 import androidx.preference.Preference;
@@ -44,9 +46,12 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.dashboard.DashboardFeatureProviderImpl;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowAccountManager;
+import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settingslib.drawer.CategoryKey;
 import com.android.settingslib.drawer.Tile;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -54,10 +59,11 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.Shadows;
 import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowAccountManager;
+import org.robolectric.shadow.api.Shadow;
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowAccountManager.class, ShadowUserManager.class})
 public class AccountDetailDashboardFragmentTest {
 
     private static final String METADATA_CATEGORY = "com.android.settings.category";
@@ -86,6 +92,11 @@
         when(mFragment.getContext()).thenReturn(mContext);
     }
 
+    @After
+    public void tearDown() {
+        ShadowAccountManager.reset();
+    }
+
     @Test
     public void testCategory_isAccountDetail() {
         assertThat(new AccountDetailDashboardFragment().getCategoryKey())
@@ -152,17 +163,45 @@
     }
 
     @Test
-    @Config(shadows = {ShadowAccountManager.class})
     public void onResume_accountMissing_shouldFinish() {
+        ShadowUserManager userManager = Shadow.extract(
+                mContext.getSystemService(UserManager.class));
+        ShadowAccountManager acctMgr = Shadow.extract(
+                mContext.getSystemService(AccountManager.class));
+
+        userManager.addProfile(new UserInfo(1, null, 0));
+        acctMgr.addAccountForUser(1, new Account("test@test.com", "com.test"));
+
         mFragment.finishIfAccountMissing();
         verify(mFragment).finish();
     }
 
     @Test
-    @Config(shadows = {ShadowAccountManager.class})
-    public void onResume_accountPresent_shouldNotFinish() {
-        AccountManager mgr = mContext.getSystemService(AccountManager.class);
-        Shadows.shadowOf(mgr).addAccount(mFragment.mAccount);
+    public void onResume_accountPresentOneProfile_shouldNotFinish() {
+        ShadowUserManager userManager = Shadow.extract(
+                mContext.getSystemService(UserManager.class));
+        ShadowAccountManager acctMgr = Shadow.extract(
+                mContext.getSystemService(AccountManager.class));
+
+        userManager.addProfile(new UserInfo(1, null, 0));
+        acctMgr.addAccountForUser(1, mFragment.mAccount);
+
+        mFragment.finishIfAccountMissing();
+        verify(mFragment, never()).finish();
+    }
+
+    @Test
+    public void onResume_accountPresentTwoProfiles_shouldNotFinish() {
+        ShadowUserManager userManager = Shadow.extract(
+                mContext.getSystemService(UserManager.class));
+        ShadowAccountManager acctMgr = Shadow.extract(
+                mContext.getSystemService(AccountManager.class));
+
+        userManager.addProfile(new UserInfo(1, null, 0));
+        userManager.addProfile(new UserInfo(2, null, 0));
+        acctMgr.addAccountForUser(1, new Account("test@test.com", "com.test"));
+        acctMgr.addAccountForUser(2, mFragment.mAccount);
+
         mFragment.finishIfAccountMissing();
         verify(mFragment, never()).finish();
     }
diff --git a/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
index 22c2cdb..241765e 100644
--- a/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
@@ -76,7 +76,7 @@
     @After
     public void tearDown() {
         ShadowContentResolver.reset();
-        ShadowAccountManager.resetAuthenticator();
+        ShadowAccountManager.reset();
         ShadowRestrictedLockUtilsInternal.clearDisabledTypes();
     }
 
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
index 4ef982f..b25508b 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
@@ -74,6 +74,7 @@
                 CardDatabaseHelper.CardColumns.CARD_ACTION,
                 CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS,
                 CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH,
+                CardDatabaseHelper.CardColumns.CARD_DISMISSED,
         };
 
         assertThat(columnNames).isEqualTo(expectedNames);
diff --git a/tests/robotests/src/com/android/settings/location/LocationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationPreferenceControllerTest.java
deleted file mode 100644
index c12fdc9..0000000
--- a/tests/robotests/src/com/android/settings/location/LocationPreferenceControllerTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.location;
-
-import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
-import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.LocationManager;
-import android.provider.Settings.Secure;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class LocationPreferenceControllerTest {
-    @Mock
-    private Preference mPreference;
-    @Mock
-    private PreferenceScreen mScreen;
-
-    private LifecycleOwner mLifecycleOwner;
-    private Lifecycle mLifecycle;
-    private LocationPreferenceController mController;
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mController = new LocationPreferenceController(mContext, mLifecycle);
-        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-    }
-
-    @Test
-    public void isAvailable_shouldReturnTrue() {
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void updateState_shouldSetSummary() {
-        mController.updateState(mPreference);
-
-        verify(mPreference).setSummary(nullable(String.class));
-    }
-
-    @Test
-    public void updateSummary_shouldSetSummary() {
-        mController.displayPreference(mScreen);
-        mController.updateSummary();
-
-        verify(mPreference).setSummary(nullable(String.class));
-    }
-
-    @Test
-    public void getLocationSummary_locationOff_shouldSetSummaryOff() {
-        final ContentResolver contentResolver = mContext.getContentResolver();
-        Secure.putInt(contentResolver, Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF);
-
-        final String locationSummary = mController.getLocationSummary(mContext);
-        assertThat(locationSummary).isEqualTo(mContext.getString(R.string.location_off_summary));
-    }
-
-    @Test
-    public void getLocationSummary_sensorsOnly_shouldSetSummaryOn() {
-        final ContentResolver contentResolver = mContext.getContentResolver();
-        Secure.putInt(contentResolver, Secure.LOCATION_MODE, Secure.LOCATION_MODE_SENSORS_ONLY);
-
-        final String locationSummary = mController.getLocationSummary(mContext);
-        assertThat(locationSummary).isEqualTo(mContext.getString(R.string.location_on_summary));
-    }
-
-    @Test
-    public void getLocationSummary_highAccuracy_shouldSetSummaryOn() {
-        final ContentResolver contentResolver = mContext.getContentResolver();
-        Secure.putInt(contentResolver, Secure.LOCATION_MODE, Secure.LOCATION_MODE_HIGH_ACCURACY);
-
-        final String locationSummary = mController.getLocationSummary(mContext);
-        assertThat(locationSummary).isEqualTo(mContext.getString(R.string.location_on_summary));
-    }
-
-    @Test
-    public void getLocationSummary_batterySaving_shouldSetSummaryOn() {
-        final ContentResolver contentResolver = mContext.getContentResolver();
-        Secure.putInt(contentResolver, Secure.LOCATION_MODE, Secure.LOCATION_MODE_BATTERY_SAVING);
-
-        final String locationSummary = mController.getLocationSummary(mContext);
-        assertThat(locationSummary).isEqualTo(mContext.getString(R.string.location_on_summary));
-    }
-
-    @Test
-    public void onResume_shouldRegisterObserver() {
-        mLifecycle.handleLifecycleEvent(ON_RESUME);
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
-    }
-
-    @Test
-    public void onPause_shouldUnregisterObserver() {
-        mLifecycle.handleLifecycleEvent(ON_RESUME);
-        mLifecycle.handleLifecycleEvent(ON_PAUSE);
-        verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
-    }
-
-    @Test
-    public void locationProvidersChangedReceiver_updatesPreferenceSummary() {
-        mController.displayPreference(mScreen);
-        mController.onResume();
-
-        mController.mLocationProvidersChangedReceiver
-                .onReceive(mContext, new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
-
-        verify(mPreference).setSummary(any());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
index dc277d2..9664428 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.Activity;
 import android.content.Context;
@@ -115,6 +116,14 @@
     }
 
     @Test
+    public void getAvailabilityStatus_carrierConfigNull_returnUnavailable() {
+        doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType();
+        when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(null);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
     public void handPreferenceTreeClick_fireIntent() {
         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
 
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index a0fd21b..3c2cbdb 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -60,6 +61,7 @@
 import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settings.wifi.WifiSlice;
+import com.android.settingslib.wifi.WifiTracker;
 
 import org.junit.After;
 import org.junit.Before;
@@ -75,7 +77,6 @@
 import org.robolectric.shadow.api.Shadow;
 import org.robolectric.shadows.ShadowAccessibilityManager;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -91,7 +92,8 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {ShadowUserManager.class, ShadowThreadUtils.class, ShadowUtils.class,
         SlicesDatabaseAccessorTest.ShadowApplicationPackageManager.class,
-        ShadowBluetoothAdapter.class, ShadowLockPatternUtils.class})
+        ShadowBluetoothAdapter.class, ShadowLockPatternUtils.class,
+        SettingsSliceProviderTest.ShadowWifiScanWorker.class})
 public class SettingsSliceProviderTest {
 
     private static final String KEY = "KEY";
@@ -135,7 +137,7 @@
         mProvider.mSliceWeakDataCache = new HashMap<>();
         mProvider.mSliceDataCache = new HashMap<>();
         mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
-        mProvider.mCustomSliceManager = spy(new CustomSliceManager(mContext));
+        mProvider.mCustomSliceManager = new CustomSliceManager(mContext);
         when(mProvider.getContext()).thenReturn(mContext);
 
         SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
@@ -497,57 +499,52 @@
         mProvider.onSlicePinned(uri);
     }
 
-    private SliceBackgroundWorker initBackgroundWorker(Uri uri) {
-        final SliceBackgroundWorker worker = spy(new SliceBackgroundWorker(
-                mContext.getContentResolver(), uri) {
-            @Override
-            protected void onSlicePinned() {
-            }
+    @Implements(WifiSlice.WifiScanWorker.class)
+    public static class ShadowWifiScanWorker {
+        private static WifiTracker mWifiTracker;
 
-            @Override
-            protected void onSliceUnpinned() {
-            }
+        @Implementation
+        protected void onSlicePinned() {
+            mWifiTracker = mock(WifiTracker.class);
+            mWifiTracker.onStart();
+        }
 
-            @Override
-            public void close() {
-            }
-        });
-        final WifiSlice wifiSlice = spy(new WifiSlice(mContext));
-        when(wifiSlice.getBackgroundWorker()).thenReturn(worker);
-        when(mProvider.mCustomSliceManager.getSliceableFromUri(uri)).thenReturn(wifiSlice);
-        return worker;
+        @Implementation
+        protected void onSliceUnpinned() {
+            mWifiTracker.onStop();
+        }
+
+        @Implementation
+        public void close() {
+            mWifiTracker.onDestroy();
+        }
+
+        static WifiTracker getWifiTracker() {
+            return mWifiTracker;
+        }
     }
 
     @Test
     public void onSlicePinned_backgroundWorker_started() {
-        final Uri uri = WifiSlice.WIFI_URI;
-        final SliceBackgroundWorker worker = initBackgroundWorker(uri);
+        mProvider.onSlicePinned(WifiSlice.WIFI_URI);
 
-        mProvider.onSlicePinned(uri);
-
-        verify(worker).onSlicePinned();
+        verify(ShadowWifiScanWorker.getWifiTracker()).onStart();
     }
 
     @Test
     public void onSlicePinned_backgroundWorker_stopped() {
-        final Uri uri = WifiSlice.WIFI_URI;
-        final SliceBackgroundWorker worker = initBackgroundWorker(uri);
+        mProvider.onSlicePinned(WifiSlice.WIFI_URI);
+        mProvider.onSliceUnpinned(WifiSlice.WIFI_URI);
 
-        mProvider.onSlicePinned(uri);
-        mProvider.onSliceUnpinned(uri);
-
-        verify(worker).onSliceUnpinned();
+        verify(ShadowWifiScanWorker.getWifiTracker()).onStop();
     }
 
     @Test
-    public void shutdown_backgroundWorker_closed() throws IOException {
-        final Uri uri = WifiSlice.WIFI_URI;
-        final SliceBackgroundWorker worker = initBackgroundWorker(uri);
-
-        mProvider.onSlicePinned(uri);
+    public void shutdown_backgroundWorker_closed() {
+        mProvider.onSlicePinned(WifiSlice.WIFI_URI);
         mProvider.shutdown();
 
-        verify(worker).close();
+        verify(ShadowWifiScanWorker.getWifiTracker()).onDestroy();
     }
 
     @Test
@@ -630,4 +627,4 @@
             return sSetThreadPolicyCount != 0;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 1055667..4371278 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -41,6 +41,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.FakeCopyableController;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.FakeSliderController;
 import com.android.settings.testutils.FakeToggleController;
@@ -67,6 +68,7 @@
     private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
     private final Class TOGGLE_CONTROLLER = FakeToggleController.class;
     private final Class SLIDER_CONTROLLER = FakeSliderController.class;
+    private final Class COPYABLE_CONTROLLER = FakeCopyableController.class;
     private final Class CONTEXT_CONTROLLER = FakeContextOnlyPreferenceController.class;
     private final boolean IS_DYNAMIC_SUMMARY_ALLOWED = false;
 
@@ -116,7 +118,6 @@
     public void buildSliderSlice_returnsMatchingSlice() {
         final SliceData data = getDummyData(SLIDER_CONTROLLER, SliceData.SliceType.SLIDER);
 
-
         final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
         verify(mFeatureFactory.metricsFeatureProvider)
                 .action(eq(mContext), eq(MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED),
@@ -131,6 +132,23 @@
     }
 
     @Test
+    public void buildCopyableSlice_returnsMatchingSlice() {
+        final SliceData dummyData = getDummyData(COPYABLE_CONTROLLER, -1);
+
+        final Slice slice = SliceBuilderUtils.buildSlice(mContext, dummyData);
+        verify(mFeatureFactory.metricsFeatureProvider)
+                .action(eq(mContext), eq(MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED),
+                        mLoggingArgumentCatpor.capture());
+        final Pair<Integer, Object> capturedLoggingPair = mLoggingArgumentCatpor.getValue();
+
+        assertThat(capturedLoggingPair.first)
+                .isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
+        assertThat(capturedLoggingPair.second)
+                .isEqualTo(dummyData.getKey());
+        SliceTester.testSettingsCopyableSlice(mContext, slice, dummyData);
+    }
+
+    @Test
     public void testUriBuilder_oemAuthority_intentPath_returnsValidSliceUri() {
         final Uri expectedUri = new Uri.Builder()
                 .scheme(ContentResolver.SCHEME_CONTENT)
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java b/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
new file mode 100644
index 0000000..a02377c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.slices.CopyableSlice;
+
+public class FakeCopyableController extends BasePreferenceController implements
+        CopyableSlice {
+
+    public FakeCopyableController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public boolean isSliceable() {
+        return true;
+    }
+
+    @Override
+    public void copy() {
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index 892f948..be4199d 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -169,6 +169,43 @@
     }
 
     /**
+     * Test the copyable slice, including:
+     * - No intent
+     * - Correct title
+     * - Correct intent
+     * - Correct keywords
+     * - TTL
+     * - Color
+     */
+    public static void testSettingsCopyableSlice(Context context, Slice slice,
+            SliceData sliceData) {
+        final SliceMetadata metadata = SliceMetadata.from(context, slice);
+
+        final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
+        final int color = colorItem.getInt();
+        assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context));
+
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+
+        final IconCompat expectedIcon = IconCompat.createWithResource(context,
+                sliceData.getIconResource());
+        assertThat(expectedIcon.toString()).isEqualTo(primaryAction.getIcon().toString());
+
+        final long sliceTTL = metadata.getExpiry();
+        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
+
+        // Check primary intent
+        final PendingIntent primaryPendingIntent = primaryAction.getAction();
+        assertThat(primaryPendingIntent).isEqualTo(
+                SliceBuilderUtils.getContentPendingIntent(context, sliceData));
+
+        final List<SliceItem> sliceItems = slice.getItems();
+        assertTitle(sliceItems, sliceData.getTitle());
+
+        assertKeywords(metadata, sliceData);
+    }
+
+    /**
      * Test the contents of an unavailable slice, including:
      * - No toggles
      * - Correct title
@@ -229,4 +266,4 @@
         expectedKeywords.add(data.getScreenTitle().toString());
         assertThat(keywords).containsExactlyElementsIn(expectedKeywords);
     }
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
index 03aabb5..4401926 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
@@ -16,19 +16,24 @@
 
 package com.android.settings.testutils.shadow;
 
+import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.AuthenticatorDescription;
+import android.annotation.NonNull;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 @Implements(AccountManager.class)
 public class ShadowAccountManager{
 
     private static final Map<String, AuthenticatorDescription> sAuthenticators = new HashMap<>();
+    private static final Map<Integer, List<Account>> sAccountsByUserId = new HashMap<>();
 
     @Implementation
     public AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) {
@@ -39,7 +44,24 @@
         sAuthenticators.put(authenticator.type, authenticator);
     }
 
-    public static void resetAuthenticator() {
+    public static void reset() {
         sAuthenticators.clear();
+        sAccountsByUserId.clear();
+    }
+
+    @Implementation @NonNull
+    public Account[] getAccountsAsUser(int userId) {
+        if (sAccountsByUserId.containsKey(userId)) {
+            return sAccountsByUserId.get(userId).toArray(new Account[0]);
+        } else {
+            return new Account[0];
+        }
+    }
+
+    public static void addAccountForUser(int userId, Account account) {
+        if (!sAccountsByUserId.containsKey(userId)) {
+            sAccountsByUserId.put(userId, new ArrayList<>());
+        }
+        sAccountsByUserId.get(userId).add(account);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
index e9daec3..c9e6c1e 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
@@ -20,20 +20,31 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.Activity;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.PowerManager;
+import android.provider.Settings;
 
+import androidx.preference.Preference;
+
+import com.android.settings.R;
 import com.android.settings.search.SearchIndexableRaw;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.wifi.WifiTracker;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
@@ -42,18 +53,33 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 public class WifiSettingsTest {
 
+    private static final int NUM_NETWORKS = 4;
+
+    @Mock
+    private WifiTracker mWifiTracker;
+    @Mock
+    private PowerManager mPowerManager;
     private Context mContext;
+    private WifiSettings mWifiSettings;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
+
+        mWifiSettings = spy(new WifiSettings());
+        doReturn(mContext).when(mWifiSettings).getContext();
+        doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+        mWifiSettings.mSavedNetworksPreference = new Preference(mContext);
+        mWifiSettings.mConfigureWifiSettingsPreference = new Preference(mContext);
+        mWifiSettings.mWifiTracker = mWifiTracker;
     }
 
     @Test
     public void testSearchIndexProvider_shouldIndexFragmentTitle() {
         final List<SearchIndexableRaw> indexRes =
-            WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true /* enabled */);
+                WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext,
+                        true /* enabled */);
 
         assertThat(indexRes).isNotNull();
         assertThat(indexRes.get(0).key).isEqualTo(WifiSettings.DATA_KEY_REFERENCE);
@@ -63,7 +89,8 @@
     @Config(qualifiers = "mcc999")
     public void testSearchIndexProvider_ifWifiSettingsNotVisible_shouldNotIndexFragmentTitle() {
         final List<SearchIndexableRaw> indexRes =
-            WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true /* enabled */);
+                WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext,
+                        true /* enabled */);
 
         assertThat(indexRes).isEmpty();
     }
@@ -78,4 +105,51 @@
 
         verify(wifiSettings).handleAddNetworkRequest(anyInt(), any(Intent.class));
     }
+
+    @Test
+    public void setAdditionalSettingsSummaries_hasSavedNetwork_preferenceVisible() {
+        when(mWifiTracker.getNumSavedNetworks()).thenReturn(NUM_NETWORKS);
+
+        mWifiSettings.setAdditionalSettingsSummaries();
+
+        assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isTrue();
+        assertThat(mWifiSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
+                mContext.getResources().getQuantityString(
+                        R.plurals.wifi_saved_access_points_summary,
+                        NUM_NETWORKS, NUM_NETWORKS));
+    }
+
+    @Test
+    public void setAdditionalSettingsSummaries_noSavedNetwork_preferenceInvisible() {
+        when(mWifiTracker.getNumSavedNetworks()).thenReturn(0);
+
+        mWifiSettings.setAdditionalSettingsSummaries();
+
+        assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isFalse();
+    }
+
+    @Test
+    public void setAdditionalSettingsSummaries_wifiWakeupEnabled_displayOn() {
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        Settings.Global.putInt(contentResolver, Settings.Global.WIFI_WAKEUP_ENABLED, 1);
+        Settings.Global.putInt(contentResolver, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1);
+        Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
+        when(mPowerManager.isPowerSaveMode()).thenReturn(false);
+
+        mWifiSettings.setAdditionalSettingsSummaries();
+
+        assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
+                mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_on));
+    }
+
+    @Test
+    public void setAdditionalSettingsSummaries_wifiWakeupDisabled_displayOff() {
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        Settings.Global.putInt(contentResolver, Settings.Global.WIFI_WAKEUP_ENABLED, 0);
+
+        mWifiSettings.setAdditionalSettingsSummaries();
+
+        assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
+                mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_off));
+    }
 }
\ No newline at end of file