Merge "Update condition title text color." into pi-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5dd22c2..74a18ea 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3137,6 +3137,8 @@
                        android:value="com.android.settings.accounts.AccountDashboardFragment"/>
             <meta-data android:name="com.android.settings.category"
                        android:value="com.android.settings.category.ia.homepage"/>
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
         </activity>
 
         <activity
diff --git a/res/layout/ownerinfo.xml b/res/layout/ownerinfo.xml
index c5eaff5..29e0840 100644
--- a/res/layout/ownerinfo.xml
+++ b/res/layout/ownerinfo.xml
@@ -25,6 +25,7 @@
         android:id="@+id/owner_info_edit_text"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:minHeight="@dimen/min_tap_target_size"
         android:gravity="top"
         android:hint="@string/owner_info_settings_edit_text_hint"
         android:inputType="textMultiLine|textCapSentences"
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
index 502505c..0ec1f10 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -91,6 +91,30 @@
             <TextView android:id="@+id/roaming" style="@style/info_value" />
         </LinearLayout>
 
+        <!-- Link Bandwidth -->
+        <LinearLayout style="@style/entry_layout" android:orientation="horizontal">
+            <TextView android:text="@string/radio_info_dl_kbps" style="@style/info_label" />
+            <TextView android:id="@+id/dl_kbps" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Link Bandwidth -->
+        <LinearLayout style="@style/entry_layout" android:orientation="horizontal">
+            <TextView android:text="@string/radio_info_ul_kbps" style="@style/info_label" />
+            <TextView android:id="@+id/ul_kbps" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Physical Channel Config -->
+        <LinearLayout style="@style/entry_layout">
+            <TextView android:text="@string/radio_info_phy_chan_config" style="@style/info_label" />
+            <TextView android:id="@+id/phy_chan_config" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- Horizontal Rule -->
+        <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dip"
+            android:background="#000000" />
+
         <!-- Preferred Network Type -->
         <TextView
                 android:layout_width="match_parent"
diff --git a/res/layout/storage_item.xml b/res/layout/storage_item.xml
index ba1c697..aa2b4f8 100644
--- a/res/layout/storage_item.xml
+++ b/res/layout/storage_item.xml
@@ -72,7 +72,7 @@
                 android:layout_height="wrap_content"
                 android:textAlignment="viewStart"
                 android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                android:textColor="?android:attr/textColorSecondaryNoDisable"
+                android:textColor="?android:attr/textColorSecondary"
                 android:maxLines="10"
                 android:layout_alignParentEnd="true"/>
 
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 16c8c22..fe891e1 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -291,7 +291,6 @@
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
                         style="@style/wifi_item_content"
-                        android:textSize="14sp"
                         android:text="@string/wifi_show_password" />
             </LinearLayout>
         </LinearLayout>
diff --git a/res/values/config.xml b/res/values/config.xml
index f8a7acc..e204b7f 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -131,7 +131,7 @@
     <!-- List of a11y components on the device allowed to be enabled by Settings Slices -->
     <string-array name="config_settings_slices_accessibility_components" translatable="false"/>
 
-    <!-- Whether or not swipe up gesture's opt-in setting is available on this device -->
-    <bool name="config_swipe_up_gesture_setting_available">false</bool>
+    <!-- Whether or not to show the night light suggestion. -->
+    <bool name="config_night_light_suggestion_enabled">true</bool>
 
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fda46b7..f617df1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -472,10 +472,16 @@
     <string name="proxy_url_title">"PAC URL: "</string>
 
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_dl_kbps">DL Bandwidth (kbps):</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_ul_kbps">UL Bandwidth (kbps):</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="radio_info_signal_location_label">Cell Location Info (deprecated):</string>
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="radio_info_neighboring_location_label">Neighbor Cell Info (deprecated):</string>
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_phy_chan_config">LTE Physical Channel Configuration:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="radio_info_cell_info_refresh_rate">Cell Info Refresh Rate:</string>
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="radio_info_cellinfo_label">All Cell Measurement Info:</string>
@@ -9249,7 +9255,7 @@
     <!-- Informational text about update time only, without carrier. First argument intentionally skipped. [CHAR LIMIT=30] -->
     <string name="no_carrier_update_text">Updated <xliff:g name="time" example="3m">^2</xliff:g> ago</string>
 
-    <!-- Informational text about a recent carrier and update time [CHAR LIMIT=30] -->
+    <!-- Informational text about a recent carrier and update time [CHAR LIMIT=34] -->
     <string name="carrier_and_update_now_text">Updated by <xliff:g name="carrier" example="T-mobile">^1</xliff:g> just now</string>
 
     <!-- Informational text about recent update time only, without carrier [CHAR LIMIT=30] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 763d8fa..8052616 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -200,6 +200,7 @@
         <item name="android:textAlignment">viewStart</item>
         <item name="android:textAppearance">@android:style/TextAppearance.Material.Subhead</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:minHeight">@dimen/min_tap_target_size</item>
     </style>
 
     <style name="wifi_item_spinner" parent="wifi_item_content">
@@ -219,6 +220,7 @@
         <item name="android:layout_marginStart">4dip</item>
         <item name="android:textSize">18sp</item>
         <item name="android:textAlignment">viewStart</item>
+        <item name="android:minHeight">@dimen/min_tap_target_size</item>
     </style>
 
     <style name="wifi_section">
@@ -285,6 +287,7 @@
         <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
         <item name="android:singleLine">true</item>
         <item name="android:textAlignment">viewStart</item>
+        <item name="android:minHeight">@dimen/min_tap_target_size</item>
     </style>
 
     <style name="vpn_warning">
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 762b434..8c38649 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -284,6 +284,7 @@
     <style name="Widget.SwitchBar.Switch" parent="@android:style/Widget.Material.CompoundButton.Switch">
         <item name="android:trackTint">@color/switchbar_switch_track_tint</item>
         <item name="android:thumbTint">@color/switchbar_switch_thumb_tint</item>
+        <item name="android:minHeight">@dimen/min_tap_target_size</item>
     </style>
 
     <style name="Theme.CryptKeeper" parent="@android:style/Theme.Material.NoActionBar">
diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index 86b0df0..15afb5f 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -162,9 +162,16 @@
     </PreferenceCategory>
 
     <Preference
+        android:key="app_settings_link"
+        android:title="@string/app_settings_link"
+        settings:controller="com.android.settings.applications.appinfo.AppSettingPreferenceController"
+        settings:allowDividerAbove="true" />
+
+    <Preference
         android:key="app_version"
         android:selectable="false"
         android:order="9999"
-        settings:controller="com.android.settings.applications.appinfo.AppVersionPreferenceController" />
+        settings:controller="com.android.settings.applications.appinfo.AppVersionPreferenceController"
+        settings:allowDividerAbove="true" />
 
 </PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/bluetooth_pairing_detail.xml b/res/xml/bluetooth_pairing_detail.xml
index e654a3c..86fb9e4 100644
--- a/res/xml/bluetooth_pairing_detail.xml
+++ b/res/xml/bluetooth_pairing_detail.xml
@@ -16,12 +16,14 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/bluetooth_pairing_pref_title">
 
     <Preference
         android:key="bt_pair_rename_devices"
         android:title="@string/bluetooth_device_name"
-        android:summary="@string/summary_placeholder" />
+        android:summary="@string/summary_placeholder"
+        settings:controller="com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController"/>
 
     <com.android.settings.bluetooth.BluetoothProgressCategory
         android:key="available_devices"
diff --git a/res/xml/bluetooth_screen.xml b/res/xml/bluetooth_screen.xml
index 9f09a8a..5679cd4 100644
--- a/res/xml/bluetooth_screen.xml
+++ b/res/xml/bluetooth_screen.xml
@@ -19,6 +19,12 @@
     android:key="bluetooth_switchbar_screen"
     android:title="@string/bluetooth_settings_title">
 
+    <Preference
+        android:key="bluetooth_screen_bt_pair_rename_devices"
+        android:title="@string/bluetooth_device_name"
+        android:summary="@string/summary_placeholder"
+        settings:controller="com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController"/>
+
     <com.android.settingslib.RestrictedPreference
         android:key="bluetooth_screen_add_bt_devices"
         android:title="@string/bluetooth_pairing_pref_title"
diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml
index 6d25c58..75f9988 100644
--- a/res/xml/connected_devices.xml
+++ b/res/xml/connected_devices.xml
@@ -49,21 +49,6 @@
         settings:allowDividerAbove="true"/>
 
     <Preference
-        android:fragment="com.android.settings.connecteddevice.BluetoothDashboardFragment"
-        android:key="bluetooth_settings"
-        android:title="@string/bluetooth_settings_title"
-        android:icon="@drawable/ic_settings_bluetooth"/>
-
-    <PreferenceCategory
-        android:key="dashboard_tile_placeholder" />
-
-    <SwitchPreference
-        android:key="toggle_nfc"
-        android:title="@string/nfc_quick_toggle_title"
-        android:icon="@drawable/ic_nfc"
-        android:summary="@string/nfc_quick_toggle_summary"/>
-
-    <Preference
         android:key="connection_preferences"
         android:title="@string/connected_device_connections_title"
         android:fragment="com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment"/>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 1917df1..f81fd79 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -20,12 +20,26 @@
     android:key="connected_devices_advanced_screen"
     android:title="@string/connected_device_connections_title">
 
+    <Preference
+        android:fragment="com.android.settings.connecteddevice.BluetoothDashboardFragment"
+        android:key="bluetooth_settings"
+        android:title="@string/bluetooth_settings_title"
+        android:icon="@drawable/ic_settings_bluetooth"
+        android:order="-9"/>
+
+    <SwitchPreference
+        android:key="toggle_nfc"
+        android:title="@string/nfc_quick_toggle_title"
+        android:icon="@drawable/ic_nfc"
+        android:summary="@string/nfc_quick_toggle_summary"
+        android:order="-7"/>
+
     <com.android.settingslib.RestrictedPreference
         android:fragment="com.android.settings.nfc.AndroidBeam"
         android:key="android_beam_settings"
         android:title="@string/android_beam_settings_title"
         android:icon="@drawable/ic_android"
-        android:order="-4"/>
+        android:order="-6"/>
 
     <SwitchPreference
         android:key="bluetooth_on_while_driving"
@@ -33,7 +47,7 @@
         android:icon="@drawable/ic_settings_bluetooth"
         android:summary="@string/bluetooth_on_while_driving_summary"
         settings:controller="com.android.settings.connecteddevice.BluetoothOnWhileDrivingPreferenceController"
-        android:order="-2"/>
+        android:order="-4"/>
 
     <com.android.settingslib.RestrictedPreference
         android:key="connected_device_printing"
@@ -41,7 +55,7 @@
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_settings_print"
         android:fragment="com.android.settings.print.PrintSettingsFragment"
-        android:order="-1"/>
+        android:order="-3"/>
 
     <Preference
         android:key="bt_received_files"
@@ -50,6 +64,6 @@
 
     <PreferenceCategory
         android:key="dashboard_tile_placeholder"
-        android:order="50"/>
+        android:order="-8"/>
 
 </PreferenceScreen>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 5bee7b0..353d1f1 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -62,12 +62,6 @@
         android:order="-160"
         settings:controller="com.android.settings.notification.RingVolumePreferenceController"/>
 
-    <!-- Also vibrate for calls -->
-    <SwitchPreference
-        android:key="vibrate_when_ringing"
-        android:title="@string/vibrate_when_ringing_title"
-        android:order="-155"/>
-
     <!-- Alarm volume -->
     <com.android.settings.notification.VolumeSeekBarPreference
         android:key="alarm_volume"
@@ -84,6 +78,13 @@
         android:order="-140"
         settings:controller="com.android.settings.notification.NotificationVolumePreferenceController"/>
 
+    <!-- Also vibrate for calls -->
+    <SwitchPreference
+        android:key="vibrate_when_ringing"
+        android:title="@string/vibrate_when_ringing_title"
+        settings:controller="com.android.settings.notification.VibrateWhenRingPreferenceController"
+        android:order="-130"/>
+
     <!-- Interruptions -->
     <com.android.settingslib.RestrictedPreference
         android:key="zen_mode"
@@ -108,8 +109,7 @@
         android:dialogTitle="@string/ringtone_title"
         android:summary="@string/summary_placeholder"
         android:ringtoneType="ringtone"
-        android:order="-100"
-        settings:allowDividerAbove="true"/>
+        android:order="-100"/>
 
     <!-- Default notification ringtone -->
     <com.android.settings.DefaultRingtonePreference
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index b885483..170db16 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -16,6 +16,8 @@
 
 package com.android.settings;
 
+import static android.net.ConnectivityManager.NetworkCallback;
+
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -27,6 +29,10 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.graphics.Typeface;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
 import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.AsyncResult;
@@ -52,12 +58,14 @@
 import android.telephony.NeighboringCellInfo;
 import android.telephony.PreciseCallState;
 import android.telephony.PhoneStateListener;
+import android.telephony.PhysicalChannelConfig;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.gsm.GsmCellLocation;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -193,7 +201,10 @@
     private TextView mPingHostnameV4;
     private TextView mPingHostnameV6;
     private TextView mHttpClientTest;
+    private TextView mPhyChanConfig;
     private TextView dnsCheckState;
+    private TextView mDownlinkKbps;
+    private TextView mUplinkKbps;
     private EditText smsc;
     private Switch radioPowerOnSwitch;
     private Button cellInfoRefreshRateButton;
@@ -211,6 +222,7 @@
     private Spinner preferredNetworkType;
     private Spinner cellInfoRefreshRateSpinner;
 
+    private ConnectivityManager mConnectivityManager;
     private TelephonyManager mTelephonyManager;
     private ImsManager mImsManager = null;
     private Phone phone = null;
@@ -228,6 +240,19 @@
     private int mPreferredNetworkTypeResult;
     private int mCellInfoRefreshRateIndex;
 
+    private final NetworkRequest mDefaultNetworkRequest = new NetworkRequest.Builder()
+            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+            .build();
+
+    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
+        public void onCapabilitiesChanged(Network n, NetworkCapabilities nc) {
+            int dlbw = nc.getLinkDownstreamBandwidthKbps();
+            int ulbw = nc.getLinkUpstreamBandwidthKbps();
+            updateBandwidths(dlbw, ulbw);
+        }
+    };
+
     private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
         @Override
         public void onDataConnectionStateChanged(int state) {
@@ -295,8 +320,29 @@
             updateNetworkType();
             updateImsProvisionedState();
         }
+
+        @Override
+        public void onPhysicalChannelConfigurationChanged(
+                List<PhysicalChannelConfig> configs) {
+            updatePhysicalChannelConfiguration(configs);
+        }
+
     };
 
+    private void updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) {
+            StringBuilder sb = new StringBuilder();
+            String div = "";
+            sb.append("{");
+            if (configs != null) {
+                for(PhysicalChannelConfig c : configs) {
+                    sb.append(div).append(c);
+                    div = ",";
+                }
+            }
+            sb.append("}");
+            mPhyChanConfig.setText(sb.toString());
+    }
+
     private void updatePreferredNetworkType(int type) {
         if (type >= mPreferredNetworkLabels.length || type < 0) {
             log("EVENT_QUERY_PREFERRED_TYPE_DONE: unknown " +
@@ -365,6 +411,7 @@
         log("Started onCreate");
 
         mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
+        mConnectivityManager = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
         phone = PhoneFactory.getDefaultPhone();
 
         //TODO: Need to update this if the default phoneId changes?
@@ -399,6 +446,8 @@
         mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6);
         mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
 
+        mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config);
+
         preferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
         ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,
                 android.R.layout.simple_spinner_item, mPreferredNetworkLabels);
@@ -418,6 +467,10 @@
 
         radioPowerOnSwitch = (Switch) findViewById(R.id.radio_power);
 
+        mDownlinkKbps = (TextView) findViewById(R.id.dl_kbps);
+        mUplinkKbps = (TextView) findViewById(R.id.ul_kbps);
+        updateBandwidths(0, 0);
+
         pingTestButton = (Button) findViewById(R.id.ping_test);
         pingTestButton.setOnClickListener(mPingButtonHandler);
         updateSmscButton = (Button) findViewById(R.id.update_smsc);
@@ -501,7 +554,10 @@
                 | PhoneStateListener.LISTEN_CELL_INFO
                 | PhoneStateListener.LISTEN_SERVICE_STATE
                 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
-                | PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO);
+                | PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION);
+
+        mConnectivityManager.registerNetworkCallback(
+                mDefaultNetworkRequest, mNetworkCallback, mHandler);
 
         smsc.clearFocus();
     }
@@ -514,6 +570,8 @@
 
         mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
         mTelephonyManager.setCellInfoListRate(CELL_INFO_LIST_RATE_DISABLED);
+        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+
     }
 
     private void restoreFromBundle(Bundle b) {
@@ -593,6 +651,14 @@
                 "0.0.0.0 allowed" :"0.0.0.0 not allowed");
     }
 
+    private void updateBandwidths(int dlbw, int ulbw) {
+        dlbw = (dlbw < 0 || dlbw == Integer.MAX_VALUE) ? -1 : dlbw;
+        ulbw = (ulbw < 0 || ulbw == Integer.MAX_VALUE) ? -1 : ulbw;
+        mDownlinkKbps.setText(String.format("%-5d", dlbw));
+        mUplinkKbps.setText(String.format("%-5d", ulbw));
+    }
+
+
     private final void
     updateSignalStrength(SignalStrength signalStrength) {
         Resources r = getResources();
@@ -673,12 +739,34 @@
         return (i != Long.MAX_VALUE) ? Long.toString(i) : "";
     }
 
+    private final String getConnectionStatusString(CellInfo ci) {
+        String regStr = "";
+        String connStatStr = "";
+        String connector = "";
+
+        if (ci.isRegistered()) {
+            regStr = "R";
+        }
+        switch (ci.getCellConnectionStatus()) {
+            case CellInfo.CONNECTION_PRIMARY_SERVING: connStatStr = "P"; break;
+            case CellInfo.CONNECTION_SECONDARY_SERVING: connStatStr = "S"; break;
+            case CellInfo.CONNECTION_NONE: connStatStr = "N"; break;
+            case CellInfo.CONNECTION_UNKNOWN: /* Field is unsupported */ break;
+            default: break;
+        }
+        if (!TextUtils.isEmpty(regStr) && !TextUtils.isEmpty(connStatStr)) {
+            connector = "+";
+        }
+
+        return regStr + connector + connStatStr;
+    }
+
     private final String buildCdmaInfoString(CellInfoCdma ci) {
         CellIdentityCdma cidCdma = ci.getCellIdentity();
         CellSignalStrengthCdma ssCdma = ci.getCellSignalStrength();
 
         return String.format("%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s",
-                ci.isRegistered() ? "S  " : "   ",
+                getConnectionStatusString(ci),
                 getCellInfoDisplayString(cidCdma.getSystemId()),
                 getCellInfoDisplayString(cidCdma.getNetworkId()),
                 getCellInfoDisplayString(cidCdma.getBasestationId()),
@@ -694,7 +782,7 @@
         CellSignalStrengthGsm ssGsm = ci.getCellSignalStrength();
 
         return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
-                ci.isRegistered() ? "S  " : "   ",
+                getConnectionStatusString(ci),
                 getCellInfoDisplayString(cidGsm.getMcc()),
                 getCellInfoDisplayString(cidGsm.getMnc()),
                 getCellInfoDisplayString(cidGsm.getLac()),
@@ -709,14 +797,15 @@
         CellSignalStrengthLte ssLte = ci.getCellSignalStrength();
 
         return String.format(
-                "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-4.4s %-4.4s %-2.2s\n",
-                ci.isRegistered() ? "S  " : "   ",
+                "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n",
+                getConnectionStatusString(ci),
                 getCellInfoDisplayString(cidLte.getMcc()),
                 getCellInfoDisplayString(cidLte.getMnc()),
                 getCellInfoDisplayString(cidLte.getTac()),
                 getCellInfoDisplayString(cidLte.getCi()),
                 getCellInfoDisplayString(cidLte.getPci()),
                 getCellInfoDisplayString(cidLte.getEarfcn()),
+                getCellInfoDisplayString(cidLte.getBandwidth()),
                 getCellInfoDisplayString(ssLte.getDbm()),
                 getCellInfoDisplayString(ssLte.getRsrq()),
                 getCellInfoDisplayString(ssLte.getTimingAdvance()));
@@ -727,7 +816,7 @@
         CellSignalStrengthWcdma ssWcdma = ci.getCellSignalStrength();
 
         return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
-                ci.isRegistered() ? "S  " : "   ",
+                getConnectionStatusString(ci),
                 getCellInfoDisplayString(cidWcdma.getMcc()),
                 getCellInfoDisplayString(cidWcdma.getMnc()),
                 getCellInfoDisplayString(cidWcdma.getLac()),
@@ -759,17 +848,21 @@
             }
             if (lteCells.length() != 0) {
                 value += String.format(
-                        "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-4.4s %-4.4s %-2.2s\n",
-                        "SRV", "MCC", "MNC", "TAC", "CID", "PCI", "EARFCN", "RSRP", "RSRQ", "TA");
+                        "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s"
+                                + " %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n",
+                        "SRV", "MCC", "MNC", "TAC", "CID", "PCI",
+                        "EARFCN", "BW", "RSRP", "RSRQ", "TA");
                 value += lteCells.toString();
             }
             if (wcdmaCells.length() != 0) {
-                value += String.format("WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
+                value += String.format(
+                        "WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
                         "SRV", "MCC", "MNC", "LAC", "CID", "UARFCN", "PSC", "RSCP");
                 value += wcdmaCells.toString();
             }
             if (gsmCells.length() != 0) {
-                value += String.format("GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
+                value += String.format(
+                        "GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
                         "SRV", "MCC", "MNC", "LAC", "CID", "ARFCN", "BSIC", "RSSI");
                 value += gsmCells.toString();
             }
diff --git a/src/com/android/settings/accessibility/MagnificationGesturesPreferenceController.java b/src/com/android/settings/accessibility/MagnificationGesturesPreferenceController.java
index 71901af..603b698 100644
--- a/src/com/android/settings/accessibility/MagnificationGesturesPreferenceController.java
+++ b/src/com/android/settings/accessibility/MagnificationGesturesPreferenceController.java
@@ -19,9 +19,9 @@
 import android.support.v7.preference.Preference;
 
 import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.TogglePreferenceController;
 
-public class MagnificationGesturesPreferenceController extends BasePreferenceController {
+public class MagnificationGesturesPreferenceController extends TogglePreferenceController {
 
     private boolean mIsFromSUW = false;
 
@@ -29,6 +29,18 @@
         super(context, key);
     }
 
+    @Override
+    public boolean isChecked() {
+        return MagnificationPreferenceFragment.isChecked(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return MagnificationPreferenceFragment.setChecked(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, isChecked);
+    }
+
     public void setIsFromSUW(boolean fromSUW) {
         mIsFromSUW = fromSUW;
     }
@@ -38,6 +50,7 @@
         if (getPreferenceKey().equals(preference.getKey())) {
             Bundle extras = preference.getExtras();
             populateMagnificationGesturesPreferenceExtras(extras, mContext);
+            extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED, isChecked());
             extras.putBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW, mIsFromSUW);
         }
         return false;
@@ -54,8 +67,7 @@
         if (mIsFromSUW) {
             resId = R.string.accessibility_screen_magnification_short_summary;
         } else {
-            final boolean enabled = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1;
+            final boolean enabled = isChecked();
             resId = (enabled ? R.string.accessibility_feature_state_on :
                     R.string.accessibility_feature_state_off);
         }
@@ -69,9 +81,6 @@
                 R.string.accessibility_screen_magnification_gestures_title);
         extras.putInt(AccessibilitySettings.EXTRA_SUMMARY_RES,
                 R.string.accessibility_screen_magnification_summary);
-        extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED,
-                Settings.Secure.getInt(context.getContentResolver(),
-                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1);
         extras.putInt(AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID,
                 R.raw.accessibility_screen_magnification);
     }
diff --git a/src/com/android/settings/accessibility/MagnificationNavbarPreferenceController.java b/src/com/android/settings/accessibility/MagnificationNavbarPreferenceController.java
index 84063a1..9c6301b 100644
--- a/src/com/android/settings/accessibility/MagnificationNavbarPreferenceController.java
+++ b/src/com/android/settings/accessibility/MagnificationNavbarPreferenceController.java
@@ -19,9 +19,9 @@
 import android.support.v7.preference.Preference;
 
 import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.TogglePreferenceController;
 
-public class MagnificationNavbarPreferenceController extends BasePreferenceController {
+public class MagnificationNavbarPreferenceController extends TogglePreferenceController {
 
     private boolean mIsFromSUW = false;
 
@@ -29,6 +29,18 @@
         super(context, key);
     }
 
+    @Override
+    public boolean isChecked() {
+        return MagnificationPreferenceFragment.isChecked(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return MagnificationPreferenceFragment.setChecked(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, isChecked);
+    }
+
     public void setIsFromSUW(boolean fromSUW) {
         mIsFromSUW = fromSUW;
     }
@@ -43,10 +55,7 @@
                     R.string.accessibility_screen_magnification_navbar_title);
             extras.putInt(AccessibilitySettings.EXTRA_SUMMARY_RES,
                     R.string.accessibility_screen_magnification_navbar_summary);
-            extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED,
-                    Settings.Secure.getInt(mContext.getContentResolver(),
-                            Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0)
-                            == 1);
+            extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED, isChecked());
             extras.putBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW, mIsFromSUW);
         }
         return false;
@@ -65,8 +74,7 @@
         if (mIsFromSUW) {
             resId = R.string.accessibility_screen_magnification_navbar_short_summary;
         } else {
-            final boolean enabled = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 1;
+            final boolean enabled = isChecked();
             resId = (enabled ? R.string.accessibility_feature_state_on :
                     R.string.accessibility_feature_state_off);
         }
diff --git a/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
index aa6d4f3..615c874 100644
--- a/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
@@ -18,11 +18,13 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.provider.SearchIndexableResource;
 import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 import android.text.TextUtils;
 import android.view.accessibility.AccessibilityManager;
@@ -39,6 +41,10 @@
 import java.util.List;
 
 public final class MagnificationPreferenceFragment extends DashboardFragment {
+    @VisibleForTesting
+    static final int ON = 1;
+    @VisibleForTesting
+    static final int OFF = 0;
 
     private static final String TAG = "MagnificationPreferenceFragment";
 
@@ -132,6 +138,15 @@
         return null;
     }
 
+    static boolean isChecked(ContentResolver contentResolver, String settingsKey) {
+        return Settings.Secure.getInt(contentResolver, settingsKey, OFF) == ON;
+    }
+
+    static boolean setChecked(ContentResolver contentResolver, String settingsKey,
+            boolean isChecked) {
+        return Settings.Secure.putInt(contentResolver, settingsKey, isChecked ? ON : OFF);
+    }
+
     /**
      * @return {@code true} if this fragment should be shown, {@code false} otherwise. This
      * fragment is shown in the case that more than one magnification mode is available.
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index ecb4b9f..d7ca22a 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -25,7 +25,6 @@
 import android.media.MediaPlayer.OnPreparedListener;
 import android.net.Uri;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 import android.support.v7.preference.PreferenceViewHolder;
@@ -174,7 +173,7 @@
 
     @Override
     protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
-        Settings.Secure.putInt(getContentResolver(), preferenceKey, enabled ? 1 : 0);
+        MagnificationPreferenceFragment.setChecked(getContentResolver(), preferenceKey, enabled);
         updateConfigurationWarningIfNeeded();
     }
 
@@ -183,7 +182,7 @@
         super.onInstallSwitchBarToggleSwitch();
 
         mSwitchBar.setCheckedInternal(
-                Settings.Secure.getInt(getContentResolver(), mPreferenceKey, 0) == 1);
+                MagnificationPreferenceFragment.isChecked(getContentResolver(), mPreferenceKey));
         mSwitchBar.addOnSwitchChangeListener(this);
     }
 
diff --git a/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java b/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java
index 4b7631a..15d1789 100644
--- a/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceController.java
@@ -68,7 +68,7 @@
         mEntityHeaderController = EntityHeaderController
                 .newInstance(activity, mParent, mHeader.findViewById(R.id.entity_header))
                 .setPackageName(mPackageName)
-                .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
+                .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
                         EntityHeaderController.ActionType.ACTION_NONE)
                 .bindHeaderButtons();
     }
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 4a0db4e..e71c8d1 100755
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -167,6 +167,9 @@
         use(AppOpenByDefaultPreferenceController.class).setParentFragment(this);
         use(AppPermissionPreferenceController.class).setParentFragment(this);
         use(AppPermissionPreferenceController.class).setPackageName(packageName);
+        use(AppSettingPreferenceController.class)
+                .setPackageName(packageName)
+                .setParentFragment(this);
         use(AppStoragePreferenceController.class).setParentFragment(this);
         use(AppVersionPreferenceController.class).setParentFragment(this);
         use(InstantAppDomainsPreferenceController.class).setParentFragment(this);
diff --git a/src/com/android/settings/applications/appinfo/AppSettingPreferenceController.java b/src/com/android/settings/applications/appinfo/AppSettingPreferenceController.java
new file mode 100644
index 0000000..f2941b2
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/AppSettingPreferenceController.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.appinfo;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_OPEN_APP_SETTING;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+
+import com.android.settings.overlay.FeatureFactory;
+
+public class AppSettingPreferenceController extends AppInfoPreferenceControllerBase {
+
+    private String mPackageName;
+
+    public AppSettingPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    public AppSettingPreferenceController setPackageName(String packageName) {
+        mPackageName = packageName;
+        return this;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (TextUtils.isEmpty(mPackageName) || mParent == null) {
+            return CONDITIONALLY_UNAVAILABLE;
+        }
+        final Intent intent = resolveIntent(
+                new Intent(Intent.ACTION_APPLICATION_PREFERENCES).setPackage(mPackageName));
+        return intent != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            return false;
+        }
+        final Intent intent = resolveIntent(
+                new Intent(Intent.ACTION_APPLICATION_PREFERENCES).setPackage(mPackageName));
+        if (intent == null) {
+            return false;
+        }
+        FeatureFactory.getFactory(mContext).getMetricsFeatureProvider()
+                .actionWithSource(mContext, mParent.getMetricsCategory(),
+                        ACTION_OPEN_APP_SETTING);
+        mContext.startActivity(intent);
+        return true;
+    }
+
+    private Intent resolveIntent(Intent i) {
+        ResolveInfo result = mContext.getPackageManager().resolveActivity(i, 0);
+        if (result != null) {
+            return new Intent(i.getAction())
+                    .setClassName(result.activityInfo.packageName, result.activityInfo.name);
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceController.java b/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceController.java
index 8827a71..05b5a8a 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceController.java
@@ -32,7 +32,6 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -44,16 +43,16 @@
         LifecycleObserver, OnStart, OnStop {
     private static final String TAG = "BluetoothNamePrefCtrl";
 
-    public static final String KEY_DEVICE_NAME = "device_name";
-
-
     @VisibleForTesting
     Preference mPreference;
     private LocalBluetoothManager mLocalManager;
     private LocalBluetoothAdapter mLocalAdapter;
 
-    public BluetoothDeviceNamePreferenceController(Context context, Lifecycle lifecycle) {
-        this(context, (LocalBluetoothAdapter) null);
+    /**
+     * Constructor exclusively used for Slice.
+     */
+    public BluetoothDeviceNamePreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
 
         mLocalManager = Utils.getLocalBtManager(context);
         if (mLocalManager == null) {
@@ -61,22 +60,12 @@
             return;
         }
         mLocalAdapter = mLocalManager.getBluetoothAdapter();
-
-        if (lifecycle != null) {
-            lifecycle.addObserver(this);
-        }
-    }
-
-    /**
-     * Constructor exclusively used for Slice.
-     */
-    public BluetoothDeviceNamePreferenceController(Context context) {
-        this(context, (Lifecycle) null);
     }
 
     @VisibleForTesting
-    BluetoothDeviceNamePreferenceController(Context context, LocalBluetoothAdapter localAdapter) {
-        super(context, KEY_DEVICE_NAME);
+    BluetoothDeviceNamePreferenceController(Context context, LocalBluetoothAdapter localAdapter,
+            String preferenceKey) {
+        super(context, preferenceKey);
         mLocalAdapter = localAdapter;
     }
 
@@ -103,11 +92,6 @@
     }
 
     @Override
-    public String getPreferenceKey() {
-        return KEY_DEVICE_NAME;
-    }
-
-    @Override
     public void updateState(Preference preference) {
         updateDeviceName(preference);
     }
@@ -134,7 +118,7 @@
     public Preference createBluetoothDeviceNamePreference(PreferenceScreen screen, int order) {
         mPreference = new Preference(screen.getContext());
         mPreference.setOrder(order);
-        mPreference.setKey(KEY_DEVICE_NAME);
+        mPreference.setKey(getPreferenceKey());
         screen.addPreference(mPreference);
 
         return mPreference;
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java b/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java
index 262d6b3..21f0487 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java
@@ -26,44 +26,35 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class BluetoothDeviceRenamePreferenceController extends
         BluetoothDeviceNamePreferenceController {
 
-    private final Fragment mFragment;
-    private String mPrefKey;
+    private Fragment mFragment;
     private MetricsFeatureProvider mMetricsFeatureProvider;
 
-    public BluetoothDeviceRenamePreferenceController(Context context, String prefKey,
-            Fragment fragment, Lifecycle lifecycle) {
-        super(context, lifecycle);
-        mPrefKey = prefKey;
-        mFragment = fragment;
-        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
-    }
-
     /**
      * Constructor exclusively used for Slice.
      */
-    public BluetoothDeviceRenamePreferenceController(Context context, String prefKey) {
-        super(context, (Lifecycle) null);
-        mPrefKey = prefKey;
-        mFragment = null;
-    }
-
-    @VisibleForTesting
-    BluetoothDeviceRenamePreferenceController(Context context, String prefKey, Fragment fragment,
-            LocalBluetoothAdapter localAdapter) {
-        super(context, localAdapter);
-        mPrefKey = prefKey;
-        mFragment = fragment;
+    public BluetoothDeviceRenamePreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     }
 
-    @Override
-    public String getPreferenceKey() {
-        return mPrefKey;
+    @VisibleForTesting
+    BluetoothDeviceRenamePreferenceController(Context context, LocalBluetoothAdapter localAdapter,
+            String preferenceKey) {
+        super(context, localAdapter, preferenceKey);
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+    }
+
+    /**
+     * Set the {@link Fragment} that used to show {@link LocalDeviceNameDialogFragment}
+     * in {@code handlePreferenceTreeClick}
+     */
+    @VisibleForTesting
+    public void setFragment(Fragment fragment) {
+        mFragment = fragment;
     }
 
     @Override
@@ -78,7 +69,7 @@
 
     @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
-        if (TextUtils.equals(mPrefKey, preference.getKey()) && mFragment != null) {
+        if (TextUtils.equals(getPreferenceKey(), preference.getKey()) && mFragment != null) {
             mMetricsFeatureProvider.action(mContext,
                     MetricsProto.MetricsEvent.ACTION_BLUETOOTH_RENAME);
             LocalDeviceNameDialogFragment.newInstance()
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
index b31d4c8..1ab7f87 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
@@ -30,12 +30,8 @@
 import com.android.settings.search.Indexable;
 import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.widget.FooterPreference;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * BluetoothPairingDetail is a page to scan bluetooth devices and pair them.
  */
@@ -47,7 +43,6 @@
     static final String KEY_AVAIL_DEVICES = "available_devices";
     @VisibleForTesting
     static final String KEY_FOOTER_PREF = "footer_preference";
-    private static final String KEY_RENAME_DEVICES = "bt_pair_rename_devices";
 
     @VisibleForTesting
     BluetoothProgressCategory mAvailableDevicesCategory;
@@ -80,6 +75,12 @@
         mAvailableDevicesCategory.setProgress(mLocalAdapter.isDiscovering());
     }
 
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        use(BluetoothDeviceRenamePreferenceController.class).setFragment(this);
+    }
+
     @VisibleForTesting
     void updateBluetooth() {
         if (mLocalAdapter.isEnabled()) {
@@ -200,16 +201,6 @@
     }
 
     @Override
-    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
-        final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(
-                new BluetoothDeviceRenamePreferenceController(context, KEY_RENAME_DEVICES, this,
-                        getLifecycle()));
-
-        return controllers;
-    }
-
-    @Override
     public String getDeviceListKey() {
         return KEY_AVAIL_DEVICES;
     }
diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java
index 45794c5..a64a430 100644
--- a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java
@@ -24,6 +24,7 @@
 import com.android.settings.bluetooth.BluetoothFilesPreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.nfc.AndroidBeamPreferenceController;
+import com.android.settings.nfc.NfcPreferenceController;
 import com.android.settings.print.PrintSettingPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -78,10 +79,16 @@
 
         final PrintSettingPreferenceController printerController =
                 new PrintSettingPreferenceController(context);
+        final NfcPreferenceController nfcPreferenceController =
+                new NfcPreferenceController(context);
+
         if (lifecycle != null) {
             lifecycle.addObserver(beamPreferenceController);
             lifecycle.addObserver(printerController);
+            lifecycle.addObserver(nfcPreferenceController);
         }
+
+        controllers.add(nfcPreferenceController);
         controllers.add(printerController);
 
         return controllers;
diff --git a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
index 77b75c5..3b24271 100644
--- a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
@@ -24,6 +24,7 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
+import com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController;
 import com.android.settings.bluetooth.BluetoothSwitchPreferenceController;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.core.TogglePreferenceController;
@@ -79,6 +80,12 @@
     }
 
     @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        use(BluetoothDeviceRenamePreferenceController.class).setFragment(this);
+    }
+
+    @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index 227fd9b..3dc1437 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -26,10 +26,7 @@
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.nfc.NfcPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -63,25 +60,6 @@
     }
 
     @Override
-    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
-        return buildPreferenceControllers(context, getLifecycle());
-    }
-
-    private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
-            Lifecycle lifecycle) {
-        final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        final NfcPreferenceController nfcPreferenceController =
-                new NfcPreferenceController(context);
-        controllers.add(nfcPreferenceController);
-
-        if (lifecycle != null) {
-            lifecycle.addObserver(nfcPreferenceController);
-        }
-
-        return controllers;
-    }
-
-    @Override
     public void onAttach(Context context) {
         super.onAttach(context);
         use(AvailableMediaDeviceGroupController.class).init(this);
@@ -139,12 +117,6 @@
                 }
 
                 @Override
-                public List<AbstractPreferenceController> createPreferenceControllers(Context
-                        context) {
-                    return buildPreferenceControllers(context, null /* lifecycle */);
-                }
-
-                @Override
                 public List<String> getNonIndexableKeys(Context context) {
                     List<String> keys = super.getNonIndexableKeys(context);
                     // Disable because they show dynamic data
diff --git a/src/com/android/settings/core/TogglePreferenceController.java b/src/com/android/settings/core/TogglePreferenceController.java
index ffe7fd3..e01a38d 100644
--- a/src/com/android/settings/core/TogglePreferenceController.java
+++ b/src/com/android/settings/core/TogglePreferenceController.java
@@ -51,8 +51,10 @@
     public void updateState(Preference preference) {
         if (preference instanceof TwoStatePreference) {
             ((TwoStatePreference) preference).setChecked(isChecked());
-        } if (preference instanceof MasterSwitchPreference) {
+        } else if (preference instanceof MasterSwitchPreference) {
             ((MasterSwitchPreference) preference).setChecked(isChecked());
+        } else {
+            refreshSummary(preference);
         }
     }
 
diff --git a/src/com/android/settings/display/NightDisplayPreferenceController.java b/src/com/android/settings/display/NightDisplayPreferenceController.java
index 5e8dfe0..0bbab93 100644
--- a/src/com/android/settings/display/NightDisplayPreferenceController.java
+++ b/src/com/android/settings/display/NightDisplayPreferenceController.java
@@ -18,6 +18,7 @@
 import com.android.internal.app.ColorDisplayController;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settings.R;
 
 public class NightDisplayPreferenceController extends AbstractPreferenceController implements
         PreferenceControllerMixin {
@@ -29,6 +30,12 @@
     }
 
     public static boolean isSuggestionComplete(Context context) {
+        final boolean isEnabled = context.getResources().getBoolean(
+                R.bool.config_night_light_suggestion_enabled);
+        // The suggestion is always complete if not enabled.
+        if (!isEnabled) {
+            return true;
+        }
         final ColorDisplayController controller = new ColorDisplayController(context);
         return controller.getAutoMode() != ColorDisplayController.AUTO_MODE_DISABLED;
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index e727521..b76aef0 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -131,6 +131,7 @@
 
     @Override
     public boolean isSmartBatterySupported() {
-        return false;
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_smart_battery_available);
     }
 }
diff --git a/src/com/android/settings/gestures/GesturePreferenceController.java b/src/com/android/settings/gestures/GesturePreferenceController.java
index 7f1100b..c4ee8c2 100644
--- a/src/com/android/settings/gestures/GesturePreferenceController.java
+++ b/src/com/android/settings/gestures/GesturePreferenceController.java
@@ -59,9 +59,6 @@
     public void updateState(Preference preference) {
         super.updateState(preference);
         if (preference != null) {
-            if (!(preference instanceof TwoStatePreference)) {
-                preference.setSummary(getSummary());
-            }
             // Different meanings of "Enabled" for the Preference and Controller.
             preference.setEnabled(canHandleClicks());
         }
diff --git a/src/com/android/settings/gestures/SwipeUpPreferenceController.java b/src/com/android/settings/gestures/SwipeUpPreferenceController.java
index 27c7241..b768a2c 100644
--- a/src/com/android/settings/gestures/SwipeUpPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeUpPreferenceController.java
@@ -24,7 +24,7 @@
 import android.provider.Settings;
 import android.support.annotation.VisibleForTesting;
 
-import com.android.settings.R;
+import com.android.internal.R;
 
 public class SwipeUpPreferenceController extends GesturePreferenceController {
 
@@ -46,7 +46,7 @@
         }
 
         final ComponentName recentsComponentName = ComponentName.unflattenFromString(
-                context.getString(com.android.internal.R.string.config_recentsComponentName));
+                context.getString(R.string.config_recentsComponentName));
         final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
                 .setPackage(recentsComponentName.getPackageName());
         if (context.getPackageManager().resolveService(quickStepIntent,
@@ -81,7 +81,7 @@
     @Override
     public boolean isChecked() {
         final int defaultValue = mContext.getResources()
-                .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_default) ? ON : OFF;
+                .getBoolean(R.bool.config_swipe_up_gesture_default) ? ON : OFF;
         final int swipeUpEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, defaultValue);
         return swipeUpEnabled != OFF;
diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java
index 1c9959e..1f19031 100644
--- a/src/com/android/settings/network/TetherPreferenceController.java
+++ b/src/com/android/settings/network/TetherPreferenceController.java
@@ -131,7 +131,8 @@
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        if (mBluetoothAdapter != null) {
+        if (mBluetoothAdapter != null &&
+            mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
             mBluetoothAdapter.getProfileProxy(mContext, mBtProfileServiceListener,
                     BluetoothProfile.PAN);
         }
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 3ba71a1..1005d20 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -26,16 +26,22 @@
 import android.preference.SeekBarVolumizer;
 import android.provider.SearchIndexableResource;
 import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.ListPreference;
 import android.support.v7.preference.Preference;
 import android.text.TextUtils;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.RingtonePreference;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.sound.HandsFreeProfileOutputPreferenceController;
+import com.android.settings.sound.MediaOutputPreferenceController;
 import com.android.settings.widget.PreferenceCategoryController;
+import com.android.settings.widget.UpdatableListPreferenceDialogFragment;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.instrumentation.Instrumentable;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import java.util.ArrayList;
@@ -48,7 +54,6 @@
     private static final String SELECTED_PREFERENCE_KEY = "selected_preference";
     private static final int REQUEST_CODE = 200;
     private static final String KEY_ZEN_MODE = "zen_mode";
-
     private static final int SAMPLE_CUTOFF = 2000;  // manually cap sample playback at 2 seconds
 
     @VisibleForTesting
@@ -69,6 +74,9 @@
     };
 
     private RingtonePreference mRequestPreference;
+    private UpdatableListPreferenceDialogFragment mDialogFragment;
+    private String mMediaOutputControllerKey;
+    private String mHfpOutputControllerKey;
 
     @Override
     public int getMetricsCategory() {
@@ -83,6 +91,11 @@
             if (!TextUtils.isEmpty(selectedPreference)) {
                 mRequestPreference = (RingtonePreference) findPreference(selectedPreference);
             }
+
+            UpdatableListPreferenceDialogFragment dialogFragment =
+                    (UpdatableListPreferenceDialogFragment) getFragmentManager()
+                            .findFragmentByTag(TAG);
+            mDialogFragment = dialogFragment;
         }
     }
 
@@ -113,6 +126,23 @@
     }
 
     @Override
+    public void onDisplayPreferenceDialog(Preference preference) {
+        final int metricsCategory;
+        if (mHfpOutputControllerKey.equals(preference.getKey())) {
+            metricsCategory = MetricsProto.MetricsEvent.DIALOG_SWITCH_HFP_DEVICES;
+        } else if (mMediaOutputControllerKey.equals(preference.getKey())) {
+            metricsCategory = MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES;
+        } else {
+            metricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN;
+        }
+
+        mDialogFragment = UpdatableListPreferenceDialogFragment.
+                newInstance(preference.getKey(), metricsCategory);
+        mDialogFragment.setTargetFragment(this, 0);
+        mDialogFragment.show(getFragmentManager(), TAG);
+    }
+
+    @Override
     protected String getLogTag() {
         return TAG;
     }
@@ -153,6 +183,14 @@
         volumeControllers.add(use(NotificationVolumePreferenceController.class));
         volumeControllers.add(use(CallVolumePreferenceController.class));
 
+        use(MediaOutputPreferenceController.class).setCallback(listPreference ->
+                onPreferenceDataChanged(listPreference));
+        mMediaOutputControllerKey = use(MediaOutputPreferenceController.class).getPreferenceKey();
+        use(HandsFreeProfileOutputPreferenceController.class).setCallback(listPreference ->
+            onPreferenceDataChanged(listPreference));
+        mHfpOutputControllerKey =
+                use(HandsFreeProfileOutputPreferenceController.class).getPreferenceKey();
+
         for (VolumeSeekBarPreferenceController controller : volumeControllers) {
             controller.setCallback(mVolumeCallback);
             getLifecycle().addObserver(controller);
@@ -195,7 +233,6 @@
             SoundSettings fragment, Lifecycle lifecycle) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         controllers.add(new ZenModePreferenceController(context, lifecycle, KEY_ZEN_MODE));
-        controllers.add(new VibrateWhenRingPreferenceController(context));
 
         // Volumes are added via xml
 
@@ -289,4 +326,10 @@
             workSoundController.enableWorkSync();
         }
     }
-}
+
+    private void onPreferenceDataChanged(ListPreference preference) {
+        if (mDialogFragment != null) {
+            mDialogFragment.onListPreferenceUpdated(preference);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java b/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
index d41e16b..d2ff7c5 100644
--- a/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
+++ b/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.notification;
 
+import static android.provider.Settings.System.VIBRATE_WHEN_RINGING;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -24,26 +26,41 @@
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
-import android.support.v7.preference.TwoStatePreference;
 
 import com.android.settings.Utils;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settings.core.TogglePreferenceController;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
 
-import static android.provider.Settings.System.VIBRATE_WHEN_RINGING;
-
-public class VibrateWhenRingPreferenceController extends AbstractPreferenceController
-        implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
-        LifecycleObserver, OnResume, OnPause {
+public class VibrateWhenRingPreferenceController extends TogglePreferenceController
+        implements LifecycleObserver, OnResume, OnPause {
 
     private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
+    private final int DEFAULT_VALUE = 0;
+    private final int NOTIFICATION_VIBRATE_WHEN_RINGING = 1;
     private SettingObserver mSettingObserver;
 
-    public VibrateWhenRingPreferenceController(Context context) {
-        super(context);
+    public VibrateWhenRingPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.System.getInt(mContext.getContentResolver(),
+                VIBRATE_WHEN_RINGING, DEFAULT_VALUE) != DEFAULT_VALUE;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return Settings.System.putInt(mContext.getContentResolver(), VIBRATE_WHEN_RINGING,
+                isChecked ? NOTIFICATION_VIBRATE_WHEN_RINGING : DEFAULT_VALUE);
+    }
+
+    @Override
+    @AvailabilityStatus
+    public int getAvailabilityStatus() {
+        return Utils.isVoiceCapable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
@@ -70,38 +87,10 @@
         }
     }
 
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_VIBRATE_WHEN_RINGING;
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return Utils.isVoiceCapable(mContext);
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        ((TwoStatePreference) preference).setChecked(
-            Settings.System.getInt(mContext.getContentResolver(), VIBRATE_WHEN_RINGING, 0) != 0);
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        final boolean val = (Boolean) newValue;
-        return Settings.System.putInt(mContext.getContentResolver(),
-            VIBRATE_WHEN_RINGING, val ? 1 : 0);
-    }
-
     private final class SettingObserver extends ContentObserver {
 
         private final Uri VIBRATE_WHEN_RINGING_URI =
-            Settings.System.getUriFor(VIBRATE_WHEN_RINGING);
+                Settings.System.getUriFor(VIBRATE_WHEN_RINGING);
 
         private final Preference mPreference;
 
@@ -127,5 +116,4 @@
             }
         }
     }
-
 }
diff --git a/src/com/android/settings/search/DeviceIndexFeatureProvider.java b/src/com/android/settings/search/DeviceIndexFeatureProvider.java
index 8e64d79..bf75ee8 100644
--- a/src/com/android/settings/search/DeviceIndexFeatureProvider.java
+++ b/src/com/android/settings/search/DeviceIndexFeatureProvider.java
@@ -24,8 +24,10 @@
 import android.net.Uri;
 import android.os.Build;
 import android.provider.Settings;
+import android.util.Log;
 
 import com.android.settings.R;
+import com.android.settings.Utils;
 import com.android.settings.slices.SettingsSliceProvider;
 
 import java.util.List;
@@ -48,6 +50,12 @@
 
     default void updateIndex(Context context, boolean force) {
         if (!isIndexingEnabled()) {
+            Log.w(TAG, "Skipping: device index is not enabled");
+            return;
+        }
+
+        if (!Utils.isDeviceProvisioned(context)) {
+            Log.w(TAG, "Skipping: device is not provisioned");
             return;
         }
 
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 8f07447..0ebf8c0 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -18,41 +18,39 @@
 
 import static android.Manifest.permission.READ_SEARCH_INDEXABLES;
 
-import static com.android.settings.wifi.calling.WifiCallingSliceHelper.PATH_WIFI_CALLING;
-
-import android.app.PendingIntent;
 import android.app.slice.SliceManager;
 import android.content.ContentResolver;
-import android.content.Context;
 import android.content.Intent;
-import android.graphics.drawable.Icon;
+import android.content.IntentFilter;
+import android.content.Context;
 import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.provider.Settings;
 import android.provider.SettingsSlicesContract;
 import android.support.annotation.VisibleForTesting;
 import android.support.v4.graphics.drawable.IconCompat;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
 
-import androidx.slice.Slice;
-import androidx.slice.SliceProvider;
-import androidx.slice.builders.ListBuilder;
-import androidx.slice.builders.SliceAction;
-
-import com.android.settings.R;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.wifi.WifiSliceBuilder;
+import com.android.settings.wifi.calling.WifiCallingSliceHelper;
+import com.android.settingslib.SliceBroadcastRelay;
 import com.android.settingslib.utils.ThreadUtils;
 
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 
+import androidx.slice.Slice;
+import androidx.slice.SliceProvider;
+
 /**
  * A {@link SliceProvider} for Settings to enabled inline results in system apps.
  *
@@ -84,10 +82,6 @@
      */
     public static final String SLICE_AUTHORITY = "com.android.settings.slices";
 
-    public static final String PATH_WIFI = "wifi";
-    public static final String ACTION_WIFI_CHANGED =
-            "com.android.settings.slice.action.WIFI_CHANGED";
-
     /**
      * Action passed for changes to Toggle Slices.
      */
@@ -121,6 +115,8 @@
     @VisibleForTesting
     Map<Uri, SliceData> mSliceDataCache;
 
+    final Set<Uri> mRegisteredUris = new ArraySet<>();
+
     public SettingsSliceProvider() {
         super(READ_SEARCH_INDEXABLES);
     }
@@ -146,28 +142,37 @@
 
     @Override
     public void onSlicePinned(Uri sliceUri) {
+        if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
+            registerIntentToUri(WifiSliceBuilder.INTENT_FILTER , sliceUri);
+            // TODO (b/) Register IntentFilters for database entries.
+            mRegisteredUris.add(sliceUri);
+            return;
+        }
+
         // Start warming the slice, we expect someone will want it soon.
         loadSliceInBackground(sliceUri);
     }
 
     @Override
     public void onSliceUnpinned(Uri sliceUri) {
+        if (mRegisteredUris.contains(sliceUri)) {
+            SliceBroadcastRelay.unregisterReceivers(getContext(), sliceUri);
+            mRegisteredUris.remove(sliceUri);
+        }
         mSliceDataCache.remove(sliceUri);
     }
 
     @Override
     public Slice onBindSlice(Uri sliceUri) {
-        String path = sliceUri.getPath();
         // If adding a new Slice, do not directly match Slice URIs.
         // Use {@link SlicesDatabaseAccessor}.
-        switch (path) {
-            case "/" + PATH_WIFI:
-                return createWifiSlice(sliceUri);
-            case "/" + PATH_WIFI_CALLING:
-                return FeatureFactory.getFactory(getContext())
-                        .getSlicesFeatureProvider()
-                        .getNewWifiCallingSliceHelper(getContext())
-                        .createWifiCallingSlice(sliceUri);
+        if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
+            return FeatureFactory.getFactory(getContext())
+                    .getSlicesFeatureProvider()
+                    .getNewWifiCallingSliceHelper(getContext())
+                    .createWifiCallingSlice(sliceUri);
+        } else if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
+            return WifiSliceBuilder.getSlice(getContext());
         }
 
         SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
@@ -223,11 +228,12 @@
                     true /* isPlatformSlice */);
             final List<String> oemKeys = mSlicesDatabaseAccessor.getSliceKeys(
                     false /* isPlatformSlice */);
-            final List<Uri> allUris = buildUrisFromKeys(platformKeys,
-                    SettingsSlicesContract.AUTHORITY);
-            allUris.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY));
+            descendants.addAll(buildUrisFromKeys(platformKeys, SettingsSlicesContract.AUTHORITY));
+            descendants.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY));
+            descendants.addAll(getSpecialCaseUris(true /* isPlatformSlice */));
+            descendants.addAll(getSpecialCaseUris(false /* isPlatformSlice */));
 
-            return allUris;
+            return descendants;
         }
 
         // Path is anything but empty, "action", or "intent". Return empty list.
@@ -242,7 +248,9 @@
         // Can assume authority belongs to the provider. Return all Uris for the authority.
         final boolean isPlatformUri = TextUtils.equals(authority, SettingsSlicesContract.AUTHORITY);
         final List<String> keys = mSlicesDatabaseAccessor.getSliceKeys(isPlatformUri);
-        return buildUrisFromKeys(keys, authority);
+        descendants.addAll(buildUrisFromKeys(keys, authority));
+        descendants.addAll(getSpecialCaseUris(isPlatformUri));
+        return descendants;
     }
 
     private List<Uri> buildUrisFromKeys(List<String> keys, String authority) {
@@ -295,55 +303,28 @@
         return new Slice.Builder(uri).build();
     }
 
-    // TODO (b/70622039) remove this when the proper wifi slice is enabled.
-    private Slice createWifiSlice(Uri sliceUri) {
-        // Get wifi state
-        WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
-        int wifiState = wifiManager.getWifiState();
-        boolean wifiEnabled = false;
-        String state;
-        switch (wifiState) {
-            case WifiManager.WIFI_STATE_DISABLED:
-            case WifiManager.WIFI_STATE_DISABLING:
-                state = getContext().getString(R.string.disconnected);
-                break;
-            case WifiManager.WIFI_STATE_ENABLED:
-            case WifiManager.WIFI_STATE_ENABLING:
-                state = wifiManager.getConnectionInfo().getSSID();
-                wifiEnabled = true;
-                break;
-            case WifiManager.WIFI_STATE_UNKNOWN:
-            default:
-                state = ""; // just don't show anything?
-                break;
+    private List<Uri> getSpecialCaseUris(boolean isPlatformUri) {
+        if (isPlatformUri) {
+            return getSpecialCasePlatformUris();
         }
-
-        boolean finalWifiEnabled = wifiEnabled;
-        return new ListBuilder(getContext(), sliceUri)
-                .setColor(R.color.material_blue_500)
-                .addRow(b -> b
-                        .setTitle(getContext().getString(R.string.wifi_settings))
-                        .setTitleItem(Icon.createWithResource(getContext(), R.drawable.wifi_signal))
-                        .setSubtitle(state)
-                        .addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
-                                null, finalWifiEnabled))
-                        .setPrimaryAction(
-                                new SliceAction(getIntent(Settings.ACTION_WIFI_SETTINGS),
-                                        (IconCompat) null, null)))
-                .build();
+        return getSpecialCaseOemUris();
     }
 
-    private PendingIntent getIntent(String action) {
-        Intent intent = new Intent(action);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        PendingIntent pi = PendingIntent.getActivity(getContext(), 0, intent, 0);
-        return pi;
+    private List<Uri> getSpecialCasePlatformUris() {
+        return Arrays.asList(WifiSliceBuilder.WIFI_URI);
     }
 
-    private PendingIntent getBroadcastIntent(String action) {
-        Intent intent = new Intent(action);
-        intent.setClass(getContext(), SliceBroadcastReceiver.class);
-        return PendingIntent.getBroadcast(getContext(), 0, intent,
-                PendingIntent.FLAG_CANCEL_CURRENT);
+    private List<Uri> getSpecialCaseOemUris() {
+        return new ArrayList<>();
+    }
+
+    @VisibleForTesting
+    /**
+     * Registers an IntentFilter in SysUI to notify changes to {@param sliceUri} when broadcasts to
+     * {@param intentFilter} happen.
+     */
+    void registerIntentToUri(IntentFilter intentFilter, Uri sliceUri) {
+        SliceBroadcastRelay.registerReceiver(getContext(), sliceUri, SliceBroadcastReceiver.class,
+                intentFilter);
     }
 }
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 0409734..3e349ff 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -18,18 +18,16 @@
 
 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_WIFI_CHANGED;
 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;
+import static com.android.settings.wifi.WifiSliceBuilder.ACTION_WIFI_SLICE_CHANGED;
 
 import android.app.slice.Slice;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
 import android.provider.SettingsSlicesContract;
 import android.text.TextUtils;
 import android.util.Log;
@@ -40,6 +38,8 @@
 import com.android.settings.core.SliderPreferenceController;
 import com.android.settings.core.TogglePreferenceController;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.wifi.WifiSliceBuilder;
+import com.android.settingslib.SliceBroadcastRelay;
 
 /**
  * Responds to actions performed on slices and notifies slices of updates in state changes.
@@ -67,25 +67,21 @@
                 final int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1);
                 handleSliderAction(context, key, newPosition, isPlatformSlice);
                 break;
-            case ACTION_WIFI_CHANGED:
-                WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-                boolean newState = intent.getBooleanExtra(Slice.EXTRA_TOGGLE_STATE,
-                        wm.isWifiEnabled());
-                wm.setWifiEnabled(newState);
-                // Wait a bit for wifi to update (TODO: is there a better way to do this?)
-                Handler h = new Handler();
-                h.postDelayed(() -> {
-                    Uri uri = SliceBuilderUtils.getUri(SettingsSliceProvider.PATH_WIFI,
-                            false /* isPlatformSlice */);
-                    context.getContentResolver().notifyChange(uri, null);
-                }, 1000);
+            case ACTION_WIFI_SLICE_CHANGED:
+                WifiSliceBuilder.handleUriChange(context, intent);
                 break;
             case ACTION_WIFI_CALLING_CHANGED:
                 FeatureFactory.getFactory(context)
-                      .getSlicesFeatureProvider()
-                      .getNewWifiCallingSliceHelper(context)
-                      .handleWifiCallingChanged(intent);
+                        .getSlicesFeatureProvider()
+                        .getNewWifiCallingSliceHelper(context)
+                        .handleWifiCallingChanged(intent);
                 break;
+            default:
+                final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI);
+                if (!TextUtils.isEmpty(uriString)) {
+                    final Uri uri = Uri.parse(uriString);
+                    context.getContentResolver().notifyChange(uri, null /* observer */);
+                }
         }
     }
 
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index be2e8df..feb7042 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -24,11 +24,11 @@
 import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
 import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED;
 
+import android.annotation.ColorInt;
 import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.provider.Settings;
 import android.provider.SettingsSlicesContract;
@@ -39,13 +39,14 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
-import com.android.settings.SettingsActivity;
 import com.android.settings.SubSettings;
+import com.android.settings.Utils;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.SliderPreferenceController;
 import com.android.settings.core.TogglePreferenceController;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
+import com.android.settingslib.SliceBroadcastRelay;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 import android.support.v4.graphics.drawable.IconCompat;
@@ -53,6 +54,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import androidx.slice.Slice;
 import androidx.slice.builders.ListBuilder;
@@ -67,9 +69,6 @@
 
     private static final String TAG = "SliceBuilder";
 
-    // A Slice should not be store for longer than 60,000 milliseconds / 1 minute.
-    public static final long SLICE_TTL_MILLIS = 60000;
-
     /**
      * Build a Slice from {@link SliceData}.
      *
@@ -190,7 +189,12 @@
      */
     public static CharSequence getSubtitleText(Context context,
             AbstractPreferenceController controller, SliceData sliceData) {
-        CharSequence summaryText;
+        CharSequence summaryText = sliceData.getScreenTitle();
+        if (isValidSummary(context, summaryText) && !TextUtils.equals(summaryText,
+                sliceData.getTitle())) {
+            return summaryText;
+        }
+
         if (controller != null) {
             summaryText = controller.getSummary();
 
@@ -234,13 +238,15 @@
         final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
         final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource());
         final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
+        @ColorInt final int color = Utils.getColorAccent(context);
         final TogglePreferenceController toggleController =
                 (TogglePreferenceController) controller;
         final SliceAction sliceAction = getToggleAction(context, sliceData,
                 toggleController.isChecked());
         final List<String> keywords = buildSliceKeywords(sliceData);
 
-        return new ListBuilder(context, sliceData.getUri(), SLICE_TTL_MILLIS)
+        return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
+                .setAccentColor(color)
                 .addRow(rowBuilder -> rowBuilder
                         .setTitle(sliceData.getTitle())
                         .setSubtitle(subtitleText)
@@ -256,9 +262,11 @@
         final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
         final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource());
         final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
+        @ColorInt final int color = Utils.getColorAccent(context);
         final List<String> keywords = buildSliceKeywords(sliceData);
 
-        return new ListBuilder(context, sliceData.getUri(), SLICE_TTL_MILLIS)
+        return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
+                .setAccentColor(color)
                 .addRow(rowBuilder -> rowBuilder
                         .setTitle(sliceData.getTitle())
                         .setSubtitle(subtitleText)
@@ -274,11 +282,13 @@
         final PendingIntent actionIntent = getSliderAction(context, sliceData);
         final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
         final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource());
+        @ColorInt final int color = Utils.getColorAccent(context);
         final SliceAction primaryAction = new SliceAction(contentIntent, icon,
                 sliceData.getTitle());
         final List<String> keywords = buildSliceKeywords(sliceData);
 
-        return new ListBuilder(context, sliceData.getUri(), SLICE_TTL_MILLIS)
+        return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
+                .setAccentColor(color)
                 .addInputRange(builder -> builder
                         .setTitle(sliceData.getTitle())
                         .setMax(sliderController.getMaxSteps())
@@ -336,7 +346,10 @@
         final String keywordString = data.getKeywords();
         if (keywordString != null) {
             final String[] keywordArray = keywordString.split(",");
-            keywords.addAll(Arrays.asList(keywordArray));
+            final List<String> strippedKeywords = Arrays.stream(keywordArray)
+                    .map(s -> s = s.trim())
+                    .collect(Collectors.toList());
+            keywords.addAll(strippedKeywords);
         }
 
         return keywords;
@@ -346,6 +359,7 @@
             BasePreferenceController controller) {
         final String title = data.getTitle();
         final List<String> keywords = buildSliceKeywords(data);
+        @ColorInt final int color = Utils.getColorAccent(context);
         final String summary;
         final SliceAction primaryAction;
         final IconCompat icon = IconCompat.createWithResource(context, data.getIconResource());
@@ -371,7 +385,8 @@
                 primaryAction = new SliceAction(getSettingsIntent(context), icon, title);
         }
 
-        return new ListBuilder(context, data.getUri(), SLICE_TTL_MILLIS)
+        return new ListBuilder(context, data.getUri(), ListBuilder.INFINITY)
+                .setAccentColor(color)
                 .addRow(builder -> builder
                         .setTitle(title)
                         .setSubtitle(summary)
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index d02431c..7f1a0f3 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -45,7 +45,11 @@
                 // This shouldn't matter since the slice is shown instead of the device
                 // index caring about the launch uri.
                 Uri slice = Uri.parse(intent.getStringExtra(EXTRA_SLICE));
-                Log.e(TAG, "Slice intent launched: " + slice);
+                SlicesDatabaseAccessor slicesDatabaseAccessor = new SlicesDatabaseAccessor(this);
+                // Sadly have to block here because we don't know where to go.
+                final SliceData sliceData = slicesDatabaseAccessor.getSliceDataFromUri(slice);
+                Intent launchIntent = SliceBuilderUtils.getContentIntent(this, sliceData);
+                startActivity(launchIntent);
             } else {
                 startActivity(intent);
             }
diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
index dde2b30..6d9d3a4 100644
--- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java
+++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
@@ -78,6 +78,7 @@
     protected final LocalBluetoothProfileManager mProfileManager;
     protected int mSelectedIndex;
     protected Preference mPreference;
+    protected AudioSwitchCallback mAudioSwitchPreferenceCallback;
 
     private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback;
     private final LocalBluetoothManager mLocalBluetoothManager;
@@ -85,6 +86,10 @@
     private final WiredHeadsetBroadcastReceiver mReceiver;
     private final Handler mHandler;
 
+    public interface AudioSwitchCallback {
+        void onPreferenceDataChanged(ListPreference preference);
+    }
+
     public AudioSwitchPreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -207,6 +212,10 @@
     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
     }
 
+    public void setCallback(AudioSwitchCallback callback) {
+        mAudioSwitchPreferenceCallback = callback;
+    }
+
     protected boolean isStreamFromOutputDevice(int streamType, int device) {
         return (device & mAudioManager.getDevicesForStream(streamType)) != 0;
     }
@@ -335,6 +344,7 @@
         listPreference.setEntryValues(mediaValues);
         listPreference.setValueIndex(mSelectedIndex);
         listPreference.setSummary(mediaOutputs[mSelectedIndex]);
+        mAudioSwitchPreferenceCallback.onPreferenceDataChanged(listPreference);
     }
 
     private int getConnectedDeviceIndex(String hardwareAddress) {
diff --git a/src/com/android/settings/widget/EntityHeaderController.java b/src/com/android/settings/widget/EntityHeaderController.java
index 5131159..6d67eb4 100644
--- a/src/com/android/settings/widget/EntityHeaderController.java
+++ b/src/com/android/settings/widget/EntityHeaderController.java
@@ -18,7 +18,6 @@
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
         .ACTION_OPEN_APP_NOTIFICATION_SETTING;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_OPEN_APP_SETTING;
 
 import android.annotation.IdRes;
 import android.annotation.UserIdInt;
@@ -28,7 +27,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
-import android.content.pm.ResolveInfo;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -59,15 +57,13 @@
 public class EntityHeaderController {
 
     @IntDef({ActionType.ACTION_NONE,
-            ActionType.ACTION_APP_PREFERENCE,
             ActionType.ACTION_NOTIF_PREFERENCE,
             ActionType.ACTION_DND_RULE_PREFERENCE,})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ActionType {
         int ACTION_NONE = 0;
-        int ACTION_APP_PREFERENCE = 1;
-        int ACTION_NOTIF_PREFERENCE = 2;
-        int ACTION_DND_RULE_PREFERENCE = 3;
+        int ACTION_NOTIF_PREFERENCE = 1;
+        int ACTION_DND_RULE_PREFERENCE = 2;
     }
 
     public static final String PREF_KEY_APP_HEADER = "pref_app_header";
@@ -298,9 +294,9 @@
             @Override
             public void onClick(View v) {
                 AppInfoBase.startAppInfoFragment(
-                    AppInfoDashboardFragment.class, R.string.application_info_label,
-                    mPackageName, mUid, mFragment, 0 /* request */,
-                    mMetricsCategory);
+                        AppInfoDashboardFragment.class, R.string.application_info_label,
+                        mPackageName, mUid, mFragment, 0 /* request */,
+                        mMetricsCategory);
             }
         });
         return;
@@ -371,27 +367,6 @@
                 }
                 return;
             }
-            case ActionType.ACTION_APP_PREFERENCE: {
-                final Intent intent = resolveIntent(
-                        new Intent(Intent.ACTION_APPLICATION_PREFERENCES).setPackage(mPackageName));
-                if (intent == null) {
-                    button.setImageDrawable(null);
-                    button.setVisibility(View.GONE);
-                    return;
-                }
-                button.setOnClickListener(new View.OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        FeatureFactory.getFactory(mAppContext).getMetricsFeatureProvider()
-                                .actionWithSource(mAppContext, mMetricsCategory,
-                                        ACTION_OPEN_APP_SETTING);
-                        mFragment.startActivity(intent);
-                    }
-                });
-                button.setImageResource(R.drawable.ic_settings_24dp);
-                button.setVisibility(View.VISIBLE);
-                return;
-            }
             case ActionType.ACTION_NONE: {
                 button.setVisibility(View.GONE);
                 return;
@@ -399,14 +374,6 @@
         }
     }
 
-    private Intent resolveIntent(Intent i) {
-        ResolveInfo result = mAppContext.getPackageManager().resolveActivity(i, 0);
-        if (result != null) {
-            return new Intent(i.getAction())
-                    .setClassName(result.activityInfo.packageName, result.activityInfo.name);
-        }
-        return null;
-    }
 
     private void setText(@IdRes int id, CharSequence text) {
         TextView textView = mHeader.findViewById(id);
diff --git a/src/com/android/settings/widget/UpdatableListPreferenceDialogFragment.java b/src/com/android/settings/widget/UpdatableListPreferenceDialogFragment.java
new file mode 100644
index 0000000..9369778
--- /dev/null
+++ b/src/com/android/settings/widget/UpdatableListPreferenceDialogFragment.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.widget;
+
+import android.app.AlertDialog;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.PreferenceDialogFragment;
+import android.support.v7.preference.ListPreference;
+import android.widget.ArrayAdapter;
+import com.android.settingslib.core.instrumentation.Instrumentable;
+
+import java.util.ArrayList;
+
+/**
+ * {@link PreferenceDialogFragment} that updates the available options
+ * when {@code onListPreferenceUpdated} is called."
+ */
+public class UpdatableListPreferenceDialogFragment extends PreferenceDialogFragment implements
+        Instrumentable {
+
+    private static final String SAVE_STATE_INDEX = "UpdatableListPreferenceDialogFragment.index";
+    private static final String SAVE_STATE_ENTRIES =
+            "UpdatableListPreferenceDialogFragment.entries";
+    private static final String SAVE_STATE_ENTRY_VALUES =
+            "UpdatableListPreferenceDialogFragment.entryValues";
+    private static final String METRICS_CATEGORY_KEY = "metrics_category_key";
+    private ArrayAdapter mAdapter;
+    private int mClickedDialogEntryIndex;
+    private ArrayList<CharSequence> mEntries;
+    private CharSequence[] mEntryValues;
+    private int mMetricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN;
+
+    public static UpdatableListPreferenceDialogFragment newInstance(
+            String key, int metricsCategory) {
+        UpdatableListPreferenceDialogFragment fragment =
+                new UpdatableListPreferenceDialogFragment();
+        Bundle args = new Bundle(1);
+        args.putString(ARG_KEY, key);
+        args.putInt(METRICS_CATEGORY_KEY, metricsCategory);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final Bundle bundle = getArguments();
+        mMetricsCategory =
+                bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN);
+        if (savedInstanceState == null) {
+            mEntries = new ArrayList<>();
+            setPreferenceData(getListPreference());
+        } else {
+            mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0);
+            mEntries = savedInstanceState.getCharSequenceArrayList(SAVE_STATE_ENTRIES);
+            mEntryValues =
+                    savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex);
+        outState.putCharSequenceArrayList(SAVE_STATE_ENTRIES, mEntries);
+        outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
+    }
+
+    @Override
+    public void onDialogClosed(boolean positiveResult) {
+        final ListPreference preference = getListPreference();
+        if (positiveResult && mClickedDialogEntryIndex >= 0) {
+            final String value = mEntryValues[mClickedDialogEntryIndex].toString();
+            if (preference.callChangeListener(value)) {
+                preference.setValue(value);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    void setAdapter(ArrayAdapter adapter) {
+        mAdapter = adapter;
+    }
+
+    @VisibleForTesting
+    void setEntries(ArrayList<CharSequence> entries) {
+        mEntries = entries;
+    }
+
+    @VisibleForTesting
+    ArrayAdapter getAdapter() {
+        return mAdapter;
+    }
+
+    @VisibleForTesting
+    void setMetricsCategory(Bundle bundle) {
+        mMetricsCategory =
+                bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN);
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+        super.onPrepareDialogBuilder(builder);
+        final TypedArray a = getContext().obtainStyledAttributes(
+                null,
+                com.android.internal.R.styleable.AlertDialog,
+                com.android.internal.R.attr.alertDialogStyle, 0);
+
+        mAdapter = new ArrayAdapter<>(
+                getContext(),
+                a.getResourceId(
+                        com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
+                        com.android.internal.R.layout.select_dialog_singlechoice),
+                mEntries);
+
+        builder.setSingleChoiceItems(mAdapter, mClickedDialogEntryIndex,
+                (dialog, which) -> {
+                    mClickedDialogEntryIndex = which;
+                    onClick(dialog, -1);
+                    dialog.dismiss();
+                });
+        builder.setPositiveButton(null, null);
+        a.recycle();
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return mMetricsCategory;
+    }
+
+    private ListPreference getListPreference() {
+        return (ListPreference) getPreference();
+    }
+
+    private void setPreferenceData(ListPreference preference) {
+        mEntries.clear();
+        mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
+        for (CharSequence entry : preference.getEntries()) {
+            mEntries.add(entry);
+        }
+        mEntryValues = preference.getEntryValues();
+    }
+
+    public void onListPreferenceUpdated(ListPreference preference) {
+        if (mAdapter != null) {
+            setPreferenceData(preference);
+            mAdapter.notifyDataSetChanged();
+        }
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiSliceBuilder.java b/src/com/android/settings/wifi/WifiSliceBuilder.java
new file mode 100644
index 0000000..2ebba67
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiSliceBuilder.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import static android.provider.SettingsSlicesContract.KEY_WIFI;
+
+import android.annotation.ColorInt;
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
+import android.provider.SettingsSlicesContract;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.SubSettings;
+import com.android.settings.Utils;
+import com.android.settings.search.DatabaseIndexingUtils;
+import com.android.settings.slices.SliceBroadcastReceiver;
+import com.android.settings.slices.SliceBuilderUtils;
+
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+import android.support.v4.graphics.drawable.IconCompat;
+import android.text.TextUtils;
+
+/**
+ * Utility class to build a Wifi Slice, and handle all associated actions.
+ */
+public class WifiSliceBuilder {
+
+    /**
+     * Backing Uri for the Wifi Slice.
+     */
+    public static final Uri WIFI_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSlicesContract.AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath(KEY_WIFI)
+            .build();
+
+    /**
+     * Action notifying a change on the Wifi Slice.
+     */
+    public static final String ACTION_WIFI_SLICE_CHANGED =
+            "com.android.settings.wifi.action.WIFI_CHANGED";
+
+    public static final IntentFilter INTENT_FILTER = new IntentFilter();
+
+    static {
+        INTENT_FILTER.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        INTENT_FILTER.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+    }
+
+    private WifiSliceBuilder() {
+    }
+
+    /**
+     * Return a Wifi Slice bound to {@link #WIFI_URI}.
+     * <p>
+     * Note that you should register a listener with {@link #registerIntentFilter(Context, Uri)}
+     * to get changes from Wifi.
+     */
+    public static Slice getSlice(Context context) {
+        final boolean isWifiEnabled = isWifiEnabled(context);
+        final IconCompat icon = IconCompat.createWithResource(context,
+                R.drawable.ic_settings_wireless);
+        final String title = context.getString(R.string.wifi_settings);
+        final CharSequence summary = getSummary(context);
+        @ColorInt final int color = Utils.getColorAccent(context);
+        final PendingIntent toggleAction = getBroadcastIntent(context);
+        final PendingIntent primaryAction = getPrimaryAction(context);
+        final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
+        final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
+                isWifiEnabled);
+
+        return new ListBuilder(context, WIFI_URI, ListBuilder.INFINITY)
+                .setAccentColor(color)
+                .addRow(b -> b
+                        .setTitle(title)
+                        .setSubtitle(summary)
+                        .addEndItem(toggleSliceAction)
+                        .setPrimaryAction(primarySliceAction))
+                .build();
+    }
+
+    /**
+     * Update the current wifi status to the boolean value keyed by
+     * {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
+     */
+    public static void handleUriChange(Context context, Intent intent) {
+        final WifiManager wifiManager = context.getSystemService(WifiManager.class);
+        final boolean newState = intent.getBooleanExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE,
+                wifiManager.isWifiEnabled());
+        wifiManager.setWifiEnabled(newState);
+        // Do not notifyChange on Uri. The service takes longer to update the current value than it
+        // does for the Slice to check the current value again. Let {@link SliceBroadcastRelay}
+        // handle it.
+    }
+
+    private static boolean isWifiEnabled(Context context) {
+        final WifiManager wifiManager = context.getSystemService(WifiManager.class);
+
+        switch (wifiManager.getWifiState()) {
+            case WifiManager.WIFI_STATE_ENABLED:
+            case WifiManager.WIFI_STATE_ENABLING:
+                return true;
+            case WifiManager.WIFI_STATE_DISABLED:
+            case WifiManager.WIFI_STATE_DISABLING:
+            case WifiManager.WIFI_STATE_UNKNOWN:
+            default:
+                return false;
+        }
+    }
+
+    private static CharSequence getSummary(Context context) {
+        final WifiManager wifiManager = context.getSystemService(WifiManager.class);
+
+        switch (wifiManager.getWifiState()) {
+            case WifiManager.WIFI_STATE_ENABLED:
+                final String ssid = WifiInfo.removeDoubleQuotes(wifiManager.getConnectionInfo()
+                        .getSSID());
+                if (TextUtils.equals(ssid, WifiSsid.NONE)) {
+                    return context.getText(R.string.disconnected);
+                }
+                return ssid;
+            case WifiManager.WIFI_STATE_ENABLING:
+                return context.getText(R.string.disconnected);
+            case WifiManager.WIFI_STATE_DISABLED:
+            case WifiManager.WIFI_STATE_DISABLING:
+                return context.getText(R.string.switch_off_text);
+            case WifiManager.WIFI_STATE_UNKNOWN:
+            default:
+                return "";
+        }
+    }
+
+    private static PendingIntent getPrimaryAction(Context context) {
+        final String screenTitle = context.getText(R.string.wifi_settings).toString();
+        final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build();
+        final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
+                WifiSettings.class.getName(), KEY_WIFI, screenTitle,
+                MetricsEvent.DIALOG_WIFI_AP_EDIT);
+        intent.setClassName(context.getPackageName(), SubSettings.class.getName());
+        intent.setData(contentUri);
+
+        return PendingIntent.getActivity(context, 0 /* requestCode */,
+                intent, 0 /* flags */);
+    }
+
+    private static PendingIntent getBroadcastIntent(Context context) {
+        final Intent intent = new Intent(ACTION_WIFI_SLICE_CHANGED);
+        intent.setClass(context, SliceBroadcastReceiver.class);
+        return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
+                PendingIntent.FLAG_CANCEL_CURRENT);
+    }
+}
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
index 7213148..a554e74 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
@@ -20,6 +20,7 @@
 
 import android.app.PendingIntent;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -38,6 +39,7 @@
 import com.android.ims.ImsManager;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
+import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBroadcastReceiver;
 import com.android.settings.slices.SliceBuilderUtils;
 
@@ -77,15 +79,19 @@
             "android.settings.WIFI_CALLING_SETTINGS";
 
     /**
+     * Full {@link Uri} for the Wifi Calling Slice.
+     */
+    public static final Uri WIFI_CALLING_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(PATH_WIFI_CALLING)
+            .build();
+
+    /**
      * Timeout for querying wifi calling setting from ims manager.
      */
     private static final int TIMEOUT_MILLIS = 2000;
 
-    /**
-     * Time for which data contained in the slice can remain fresh.
-     */
-    private static final int SLICE_TTL_MILLIS = 60000;
-
     protected SubscriptionManager mSubscriptionManager;
     private final Context mContext;
 
@@ -182,7 +188,7 @@
 
         final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
         final String title = mContext.getString(R.string.wifi_calling_settings_title);
-        return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS)
+        return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
                 .setColor(R.color.material_blue_500)
                 .addRow(b -> b
                         .setTitle(title)
@@ -260,7 +266,7 @@
     private Slice getNonActionableWifiCallingSlice(String title, String subtitle, Uri sliceUri,
             PendingIntent primaryActionIntent) {
         final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
-        return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS)
+        return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
                 .setColor(R.color.material_blue_500)
                 .addRow(b -> b
                         .setTitle(title)
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
index 1d9d3cd..9764a45 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
@@ -44,6 +44,7 @@
     private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
     private static final IntentFilter AIRPLANE_INTENT_FILTER = new IntentFilter(
             Intent.ACTION_AIRPLANE_MODE_CHANGED);
+    private static final int ID_NULL = -1;
 
     private final ConnectivityManager mConnectivityManager;
     private final String[] mWifiRegexs;
@@ -152,7 +153,7 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
-                clearSummaryForAirplaneMode();
+                clearSummaryForAirplaneMode(R.string.wifi_hotspot_off_subtext);
             }
         }
     };
@@ -194,10 +195,16 @@
     }
 
     private void clearSummaryForAirplaneMode() {
+        clearSummaryForAirplaneMode(ID_NULL);
+    }
+
+    private void clearSummaryForAirplaneMode(int defaultId) {
         boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
         if (isAirplaneMode) {
             mPreference.setSummary(R.string.wifi_tether_disabled_by_airplane);
+        } else if (defaultId != ID_NULL){
+            mPreference.setSummary(defaultId);
         }
     }
     //
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationGesturesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationGesturesPreferenceControllerTest.java
index 23ac795..cd0558a 100644
--- a/tests/robotests/src/com/android/settings/accessibility/MagnificationGesturesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationGesturesPreferenceControllerTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.accessibility;
 
+import static com.android.settings.accessibility.MagnificationPreferenceFragment.OFF;
+import static com.android.settings.accessibility.MagnificationPreferenceFragment.ON;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
@@ -57,13 +60,13 @@
     @Test
     public void updateState_shouldRefreshSummary() {
         Settings.System.putInt(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 1);
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ON);
         mController.updateState(mPreference);
         assertThat(mPreference.getSummary())
                 .isEqualTo(mContext.getString(R.string.accessibility_feature_state_on));
 
         Settings.System.putInt(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0);
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF);
         mController.updateState(mPreference);
         assertThat(mPreference.getSummary())
                 .isEqualTo(mContext.getString(R.string.accessibility_feature_state_off));
@@ -77,4 +80,38 @@
                 .isEqualTo(mContext.getString(R.string.
                         accessibility_screen_magnification_short_summary));
     }
+
+    @Test
+    public void isChecked_enabled() {
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ON);
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_disabled() {
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF);
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_enabled() {
+        mController.setChecked(true);
+
+        assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, -1))
+                .isEqualTo(ON);
+    }
+
+    @Test
+    public void setChecked_disabled() {
+        mController.setChecked(false);
+
+        assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, -1))
+                .isEqualTo(OFF);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationNavbarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationNavbarPreferenceControllerTest.java
index 486ccd3..bca81a2 100644
--- a/tests/robotests/src/com/android/settings/accessibility/MagnificationNavbarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationNavbarPreferenceControllerTest.java
@@ -16,8 +16,12 @@
 
 package com.android.settings.accessibility;
 
+import static com.android.settings.accessibility.MagnificationPreferenceFragment.OFF;
+import static com.android.settings.accessibility.MagnificationPreferenceFragment.ON;
 import static com.android.settings.search.ResultPayload.Availability.AVAILABLE;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.spy;
 
 import android.content.Context;
@@ -81,13 +85,13 @@
     @Test
     public void updateState_shouldRefreshSummary() {
         Settings.System.putInt(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 1);
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, ON);
         mController.updateState(mPreference);
         assertThat(mPreference.getSummary())
                 .isEqualTo(mContext.getText(R.string.accessibility_feature_state_on));
 
         Settings.System.putInt(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0);
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, OFF);
         mController.updateState(mPreference);
         assertThat(mPreference.getSummary())
                 .isEqualTo(mContext.getText(R.string.accessibility_feature_state_off));
@@ -102,6 +106,40 @@
                         accessibility_screen_magnification_navbar_short_summary));
     }
 
+    @Test
+    public void isChecked_enabled() {
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, ON);
+
+        assertThat(mController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_disabled() {
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, OFF);
+
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_enabled() {
+        mController.setChecked(true);
+
+        assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, -1))
+                .isEqualTo(ON);
+    }
+
+    @Test
+    public void setChecked_disabled() {
+        mController.setChecked(false);
+
+        assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, -1))
+                .isEqualTo(OFF);
+    }
+
     @Implements(MagnificationPreferenceFragment.class)
     public static class ShadowMagnificationPreferenceFragment {
         private static boolean sIsApplicable;
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppSettingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppSettingPreferenceControllerTest.java
new file mode 100644
index 0000000..66b58c8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppSettingPreferenceControllerTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.appinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.Application;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowPackageManager;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AppSettingPreferenceControllerTest {
+
+    private static final String TEST_PKG_NAME = "test_pkg";
+    private static final String TEST_CLASS_NAME = "name";
+    private static final Intent TEST_INTENT =
+        new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
+            .setClassName(TEST_PKG_NAME, TEST_CLASS_NAME);
+    private static final Intent RESOLVED_INTENT =
+        new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
+            .setPackage(TEST_PKG_NAME);
+
+    @Mock
+    private AppInfoDashboardFragment mParent;
+    private Application mApplication;
+    private ShadowPackageManager mPackageManager;
+    private AppSettingPreferenceController mController;
+    private Preference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mApplication = RuntimeEnvironment.application;
+        mPackageManager = shadowOf(mApplication.getPackageManager());
+        mController = new AppSettingPreferenceController(mApplication, "test_key");
+        mController.setPackageName(TEST_PKG_NAME).setParentFragment(mParent);
+        mPreference = new Preference(mApplication);
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void getAvailabilityStatus_noAppSetting_shouldNotBeAvailable() {
+        assertThat(mController.isAvailable())
+                .isFalse();
+    }
+
+    @Test
+    public void getAvailabilityStatus_noPackageName_shouldNotBeAvailable() {
+        mController.setPackageName(null);
+
+        assertThat(mController.isAvailable())
+                .isFalse();
+    }
+
+    @Test
+    public void getAvailabilityStatus_hasAppSetting_shouldBeAvailable() {
+        final ResolveInfo info = new ResolveInfo();
+        info.activityInfo = new ActivityInfo();
+        info.activityInfo.packageName = TEST_PKG_NAME;
+        info.activityInfo.name = TEST_CLASS_NAME;
+
+        mPackageManager.addResolveInfoForIntent(RESOLVED_INTENT, info);
+
+        assertThat(mController.isAvailable())
+                .isTrue();
+    }
+
+    @Test
+    public void clickPreference_noAppSetting_shouldDoNothing() {
+        assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
+    }
+
+    @Test
+    public void clickPreference_hasAppSetting_shouldLaunchIntent() {
+        final ResolveInfo info = new ResolveInfo();
+        info.activityInfo = new ActivityInfo();
+        info.activityInfo.packageName = TEST_PKG_NAME;
+        info.activityInfo.name = TEST_CLASS_NAME;
+
+        mPackageManager.addResolveInfoForIntent(RESOLVED_INTENT, info);
+
+        assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
+        assertThat(shadowOf(mApplication).getNextStartedActivity().getComponent())
+            .isEqualTo(TEST_INTENT.getComponent());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceControllerTest.java
index f5070ef..1d37883 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceNamePreferenceControllerTest.java
@@ -43,6 +43,7 @@
 
     private static final String DEVICE_NAME = "Nightshade";
     private static final int ORDER = 1;
+    private static final String KEY_DEVICE_NAME = "test_key_name";
 
     private Context mContext;
     @Mock
@@ -61,8 +62,9 @@
 
         when(mPreferenceScreen.getContext()).thenReturn(mContext);
         mPreference = new Preference(mContext);
-        mPreference.setKey(BluetoothDeviceNamePreferenceController.KEY_DEVICE_NAME);
-        mController = spy(new BluetoothDeviceNamePreferenceController(mContext, mLocalAdapter));
+        mPreference.setKey(KEY_DEVICE_NAME);
+        mController = spy(new BluetoothDeviceNamePreferenceController(mContext, mLocalAdapter,
+                KEY_DEVICE_NAME));
         doReturn(DEVICE_NAME).when(mController).getDeviceName();
     }
 
@@ -82,7 +84,7 @@
         Preference preference =
             mController.createBluetoothDeviceNamePreference(mPreferenceScreen, ORDER);
 
-        assertThat(preference.getKey()).isEqualTo(mController.KEY_DEVICE_NAME);
+        assertThat(preference.getKey()).isEqualTo(mController.getPreferenceKey());
         assertThat(preference.getOrder()).isEqualTo(ORDER);
         verify(mPreferenceScreen).addPreference(preference);
     }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceControllerTest.java
index 6ba8593..65eae2c 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceControllerTest.java
@@ -67,8 +67,9 @@
         mPreference = new Preference(mContext);
         mPreference.setKey(PREF_KEY);
 
-        mController = spy(new BluetoothDeviceRenamePreferenceController(
-                mContext, PREF_KEY, mFragment, mLocalAdapter));
+        mController = spy(new BluetoothDeviceRenamePreferenceController(mContext, mLocalAdapter,
+                PREF_KEY));
+        mController.setFragment(mFragment);
         doReturn(DEVICE_NAME).when(mController).getDeviceName();
     }
 
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
index bb68c0d..c62f63d 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
@@ -163,13 +163,6 @@
     }
 
     @Test
-    public void nightDisplaySuggestion_isNotCompleted_byDefault() {
-        final ComponentName componentName =
-                new ComponentName(mContext, NightDisplaySuggestionActivity.class);
-        assertThat(mProvider.isSuggestionComplete(mContext, componentName)).isFalse();
-    }
-
-    @Test
     public void testGetSmartSuggestionEnabledTaggedData_disabled() {
         assertThat(mProvider.getLoggingTaggedData(mContext)).asList().containsExactly(
                 Pair.create(MetricsEvent.FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED, 0));
diff --git a/tests/robotests/src/com/android/settings/display/NightDisplayPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/NightDisplayPreferenceControllerTest.java
index 3bc7d52..7440f63 100644
--- a/tests/robotests/src/com/android/settings/display/NightDisplayPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/NightDisplayPreferenceControllerTest.java
@@ -6,15 +6,22 @@
 import android.content.ComponentName;
 import android.provider.Settings.Secure;
 import com.android.internal.app.ColorDisplayController;
+import com.android.settings.R;
 import com.android.settings.Settings.NightDisplaySuggestionActivity;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {
+        SettingsShadowResources.class
+})
 public class NightDisplayPreferenceControllerTest {
 
   private NightDisplayPreferenceController mPreferenceController;
@@ -27,6 +34,7 @@
   @After
   public void tearDown() {
     mPreferenceController = null;
+    SettingsShadowResources.reset();
   }
 
   @Test
@@ -58,4 +66,16 @@
         new ComponentName(context, NightDisplaySuggestionActivity.class);
     assertThat(mPreferenceController.isSuggestionComplete(context)).isTrue();
   }
+
+  @Test
+  public void nightDisplaySuggestion_isCompleted_ifDisabled() {
+    final Application context = RuntimeEnvironment.application;
+    Secure.putInt(context.getContentResolver(),
+            Secure.NIGHT_DISPLAY_AUTO_MODE, ColorDisplayController.AUTO_MODE_DISABLED);
+    SettingsShadowResources.overrideResource(R.bool.config_night_light_suggestion_enabled, false);
+
+    final ComponentName componentName =
+            new ComponentName(context, NightDisplaySuggestionActivity.class);
+    assertThat(mPreferenceController.isSuggestionComplete(context)).isTrue();
+  }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index 70acb73..6d18109 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.fuelgauge;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -29,6 +30,7 @@
 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;
 
@@ -43,7 +45,7 @@
     private static final String[] PACKAGES_MEDIA = {"com.android.providers.media"};
     private static final String[] PACKAGES_SYSTEMUI = {"com.android.systemui"};
 
-    @Mock
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
     @Mock
     private BatterySipper mBatterySipper;
@@ -55,6 +57,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        when(mContext.getApplicationContext()).thenReturn(mContext);
         mPowerFeatureProvider = new PowerUsageFeatureProviderImpl(mContext);
         when(mPackageManager.getPackagesForUid(UID_CALENDAR)).thenReturn(PACKAGES_CALENDAR);
         when(mPackageManager.getPackagesForUid(UID_MEDIA)).thenReturn(PACKAGES_MEDIA);
@@ -138,7 +141,18 @@
     }
 
     @Test
-    public void testIsSmartBatterySupported_returnFalse() {
+    public void testIsSmartBatterySupported_smartBatterySupported_returnTrue() {
+        when(mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_smart_battery_available)).thenReturn(true);
+
+        assertThat(mPowerFeatureProvider.isSmartBatterySupported()).isTrue();
+    }
+
+    @Test
+    public void testIsSmartBatterySupported_smartBatteryNotSupported_returnFalse() {
+        when(mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_smart_battery_available)).thenReturn(false);
+
         assertThat(mPowerFeatureProvider.isSmartBatterySupported()).isFalse();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
index 4107b73..3585650 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
@@ -27,7 +27,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 
-import com.android.settings.R;
+import com.android.internal.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
 
@@ -57,8 +57,7 @@
     public void setUp() {
         SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_setting_available,
                 true);
-        SettingsShadowResources.overrideResource(
-                com.android.internal.R.bool.config_swipe_up_gesture_default, true);
+        SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, true);
 
         mContext = RuntimeEnvironment.application;
         mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
@@ -107,8 +106,7 @@
 
     @Test
     public void testIsChecked_defaultIsFalse_shouldReturnFalse() {
-        SettingsShadowResources.overrideResource(
-                com.android.internal.R.bool.config_swipe_up_gesture_default, false);
+        SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, false);
         assertThat(mController.isChecked()).isFalse();
     }
 
diff --git a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
index 6166d29..ac573b4 100644
--- a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
@@ -75,10 +75,21 @@
 
     @Test
     public void lifeCycle_onCreate_shouldInitBluetoothPan() {
+        when(mBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
         mController.onCreate(null);
 
-        verify(mBluetoothAdapter)
-            .getProfileProxy(mContext, mController.mBtProfileServiceListener, BluetoothProfile.PAN);
+        verify(mBluetoothAdapter).getState();
+        verify(mBluetoothAdapter).getProfileProxy(mContext, mController.mBtProfileServiceListener,
+                BluetoothProfile.PAN);
+    }
+
+    @Test
+    public void lifeCycle_onCreate_shouldNotInitBluetoothPanWhenBluetoothOff() {
+        when(mBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
+        mController.onCreate(null);
+
+        verify(mBluetoothAdapter).getState();
+        verifyNoMoreInteractions(mBluetoothAdapter);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/notification/VibrateWhenRingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/VibrateWhenRingPreferenceControllerTest.java
index 9314109..4e69c46 100644
--- a/tests/robotests/src/com/android/settings/notification/VibrateWhenRingPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/VibrateWhenRingPreferenceControllerTest.java
@@ -17,11 +17,17 @@
 package com.android.settings.notification;
 
 import static android.provider.Settings.System.VIBRATE_WHEN_RINGING;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
@@ -37,26 +43,32 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowContentResolver;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class VibrateWhenRingPreferenceControllerTest {
 
-    @Mock
+    private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
+    private final int DEFAULT_VALUE = 0;
+    private final int NOTIFICATION_VIBRATE_WHEN_RINGING = 1;
     private Context mContext;
+    private ContentResolver mContentResolver;
     @Mock
     private PreferenceScreen mScreen;
     @Mock
     private TelephonyManager mTelephonyManager;
-
     private VibrateWhenRingPreferenceController mController;
     private Preference mPreference;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mContentResolver = mContext.getContentResolver();
         when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
-        mController = new VibrateWhenRingPreferenceController(mContext);
-        mPreference = new Preference(RuntimeEnvironment.application);
+        mController = new VibrateWhenRingPreferenceController(mContext, KEY_VIBRATE_WHEN_RINGING);
+        mPreference = new Preference(mContext);
         mPreference.setKey(mController.getPreferenceKey());
         when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference);
     }
@@ -80,26 +92,95 @@
     }
 
     @Test
+    public void testOnPreferenceChange_turnOn_returnOn() {
+        mController.onPreferenceChange(null, true);
+        final int mode = Settings.System.getInt(mContext.getContentResolver(),
+                VIBRATE_WHEN_RINGING, DEFAULT_VALUE);
+
+        assertThat(mode).isEqualTo(NOTIFICATION_VIBRATE_WHEN_RINGING);
+    }
+
+    @Test
+    public void testOnPreferenceChange_turnOff_returnOff() {
+        mController.onPreferenceChange(null, false);
+        final int mode = Settings.System.getInt(mContext.getContentResolver(),
+                VIBRATE_WHEN_RINGING, DEFAULT_VALUE);
+
+        assertThat(mode).isEqualTo(DEFAULT_VALUE);
+    }
+
+    @Test
+    public void voiceCapable_availabled() {
+        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void voiceCapable_notAvailabled() {
+        when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
     public void updateState_settingIsOn_preferenceShouldBeChecked() {
         final TwoStatePreference preference = mock(TwoStatePreference.class);
-        final Context context = RuntimeEnvironment.application;
-        Settings.System.putInt(context.getContentResolver(), VIBRATE_WHEN_RINGING, 1);
+        Settings.System.putInt(mContext.getContentResolver(), VIBRATE_WHEN_RINGING, 1);
 
-        mController = new VibrateWhenRingPreferenceController(context);
         mController.updateState(preference);
 
-        verify(preference).setChecked(true);
+        assertThat(mController.isChecked()).isTrue();
     }
 
     @Test
     public void updateState_settingIsOff_preferenceShouldNotBeChecked() {
         final TwoStatePreference preference = mock(TwoStatePreference.class);
-        final Context context = RuntimeEnvironment.application;
-        Settings.System.putInt(context.getContentResolver(), VIBRATE_WHEN_RINGING, 0);
+        Settings.System.putInt(mContext.getContentResolver(), VIBRATE_WHEN_RINGING, 0);
 
-        mController = new VibrateWhenRingPreferenceController(context);
         mController.updateState(preference);
 
-        verify(preference).setChecked(false);
+        assertThat(mController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_settingsIsOn() {
+        mController.setChecked(true);
+        final int mode = Settings.System.getInt(mContext.getContentResolver(), VIBRATE_WHEN_RINGING,
+                -1);
+
+        assertThat(mode).isEqualTo(NOTIFICATION_VIBRATE_WHEN_RINGING);
+    }
+
+    @Test
+    public void setChecked_settingsIsOff() {
+        mController.setChecked(false);
+        final int mode = Settings.System.getInt(mContext.getContentResolver(), VIBRATE_WHEN_RINGING,
+                -1);
+
+        assertThat(mode).isEqualTo(DEFAULT_VALUE);
+    }
+
+    @Test
+    public void testObserver_onResume_shouldRegisterObserver() {
+        final ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver);
+        mController.displayPreference(mScreen);
+
+        mController.onResume();
+
+        assertThat(shadowContentResolver.getContentObservers(
+                Settings.System.getUriFor(VIBRATE_WHEN_RINGING))).isNotEmpty();
+    }
+
+    @Test
+    public void testObserver_onPause_shouldUnregisterObserver() {
+        final ShadowContentResolver shadowContentResolver = Shadow.extract(mContentResolver);
+        mController.displayPreference(mScreen);
+
+        mController.onResume();
+        mController.onPause();
+
+        assertThat(shadowContentResolver.getContentObservers(
+                Settings.System.getUriFor(VIBRATE_WHEN_RINGING))).isEmpty();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java b/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java
index 26c2830..d4c1580 100644
--- a/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java
+++ b/tests/robotests/src/com/android/settings/search/DeviceIndexFeatureProviderTest.java
@@ -15,7 +15,6 @@
 package com.android.settings.search;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -24,6 +23,7 @@
 
 import android.app.Activity;
 import android.app.job.JobScheduler;
+import android.provider.Settings;
 
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -47,7 +47,7 @@
     }
 
     @Test
-    public void verifyDisabled() {
+    public void updateIndex_disabled_shouldDoNothing() {
         when(mProvider.isIndexingEnabled()).thenReturn(false);
 
         mProvider.updateIndex(mActivity, false);
@@ -55,7 +55,20 @@
     }
 
     @Test
-    public void verifyIndexing() {
+    public void updateIndex_enabled_unprovisioned_shouldDoNothing() {
+        when(mProvider.isIndexingEnabled()).thenReturn(true);
+        Settings.Global.putInt(mActivity.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 0);
+
+        mProvider.updateIndex(mActivity, false);
+
+        verify(mProvider, never()).index(any(), any(), any(), any(), any());
+    }
+
+    @Test
+    public void updateIndex_enabled_provisioned_shouldIndex() {
+        Settings.Global.putInt(mActivity.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 1);
         JobScheduler jobScheduler = mock(JobScheduler.class);
         when(mProvider.isIndexingEnabled()).thenReturn(true);
         when(mActivity.getSystemService(JobScheduler.class)).thenReturn(jobScheduler);
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index a0bd33a..60fb5f9 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -19,6 +19,7 @@
 
 import static android.content.ContentResolver.SCHEME_CONTENT;
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
@@ -31,6 +32,7 @@
 import android.os.StrictMode;
 import android.provider.SettingsSlicesContract;
 
+import com.android.settings.wifi.WifiSliceBuilder;
 import com.android.settings.testutils.DatabaseTestUtils;
 import com.android.settings.testutils.FakeToggleController;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -45,6 +47,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 
 import androidx.slice.Slice;
 
@@ -70,6 +74,10 @@
     private SQLiteDatabase mDb;
     private SliceManager mManager;
 
+    private static final List<Uri> SPECIAL_CASE_PLATFORM_URIS = Arrays.asList(
+            WifiSliceBuilder.WIFI_URI
+    );
+
     @Before
     public void setUp() {
         mContext = spy(RuntimeEnvironment.application);
@@ -114,7 +122,7 @@
     }
 
     @Test
-    public void testLoadSlice_doesntCacheWithoutPin() {
+    public void testLoadSlice_doesNotCacheWithoutPin() {
         insertSpecialCase(KEY);
         Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
 
@@ -226,6 +234,7 @@
                 .build();
 
         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
+        descendants.removeAll(SPECIAL_CASE_PLATFORM_URIS);
 
         assertThat(descendants).isEmpty();
     }
@@ -293,16 +302,18 @@
                 .authority(SettingsSlicesContract.AUTHORITY)
                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
                 .build();
-        final Uri expectedUri = new Uri.Builder()
+        final Collection<Uri> expectedUris = new HashSet<>();
+        expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
+        expectedUris.add(new Uri.Builder()
                 .scheme(SCHEME_CONTENT)
                 .authority(SettingsSlicesContract.AUTHORITY)
                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
                 .appendPath(key)
-                .build();
+                .build());
 
         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
 
-        assertThat(descendants).containsExactly(expectedUri);
+        assertThat(descendants).containsExactlyElementsIn(expectedUris);
     }
 
     @Test
@@ -313,16 +324,18 @@
                 .scheme(SCHEME_CONTENT)
                 .authority(SettingsSlicesContract.AUTHORITY)
                 .build();
-        final Uri expectedUri = new Uri.Builder()
+        final Collection<Uri> expectedUris = new HashSet<>();
+        expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
+        expectedUris.add(new Uri.Builder()
                 .scheme(SCHEME_CONTENT)
                 .authority(SettingsSlicesContract.AUTHORITY)
                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
                 .appendPath(key)
-                .build();
+                .build());
 
         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
 
-        assertThat(descendants).containsExactly(expectedUri);
+        assertThat(descendants).containsExactlyElementsIn(expectedUris);
     }
 
     @Test
@@ -334,22 +347,31 @@
         final Uri uri = new Uri.Builder()
                 .scheme(SCHEME_CONTENT)
                 .build();
-        final Uri expectedPlatformUri = new Uri.Builder()
+        final Collection<Uri> expectedUris = new HashSet<>();
+        expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
+        expectedUris.add(new Uri.Builder()
                 .scheme(SCHEME_CONTENT)
                 .authority(SettingsSlicesContract.AUTHORITY)
                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
                 .appendPath(platformKey)
-                .build();
-        final Uri expectedOemUri = new Uri.Builder()
+                .build());
+        expectedUris.add(new Uri.Builder()
                 .scheme(SCHEME_CONTENT)
                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
                 .appendPath(oemKey)
-                .build();
+                .build());
 
         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
 
-        assertThat(descendants).containsExactly(expectedPlatformUri, expectedOemUri);
+        assertThat(descendants).containsExactlyElementsIn(expectedUris);
+    }
+
+    @Test
+    public void bindSlice_wifiSlice_returnsWifiSlice() {
+        final Slice wifiSlice = mProvider.onBindSlice(WifiSliceBuilder.WIFI_URI);
+
+        assertThat(wifiSlice.getUri()).isEqualTo(WifiSliceBuilder.WIFI_URI);
     }
 
     private void insertSpecialCase(String key) {
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index bd589bf..00e8fe1 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -204,18 +204,18 @@
     }
 
     @Test
-    public void testDynamicSummary_returnsSliceSummary() {
+    public void getDynamicSummary_returnsScreenTitle() {
         final SliceData data = getDummyData();
         final FakePreferenceController controller = new FakePreferenceController(mContext, KEY);
 
         final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
 
-        assertThat(summary).isEqualTo(data.getSummary());
+        assertThat(summary).isEqualTo(data.getScreenTitle());
     }
 
     @Test
-    public void testDynamicSummary_returnsFragmentSummary() {
-        final SliceData data = getDummyData(null);
+    public void getDynamicSummary_noScreenTitle_returnsPrefControllerSummary() {
+        final SliceData data = getDummyData("", "");
         final FakePreferenceController controller = spy(
                 new FakePreferenceController(mContext, KEY));
         final String controllerSummary = "new_Summary";
@@ -227,8 +227,21 @@
     }
 
     @Test
-    public void testDynamicSummary_returnsSliceEmptyString() {
-        final SliceData data = getDummyData(null);
+    public void getDynamicSummary_screenTitleMatchesTitle_returnsPrefControllerSummary() {
+        final SliceData data = getDummyData("", TITLE);
+        final FakePreferenceController controller = spy(
+                new FakePreferenceController(mContext, KEY));
+        final String controllerSummary = "new_Summary";
+        doReturn(controllerSummary).when(controller).getSummary();
+
+        final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
+
+        assertThat(summary).isEqualTo(controllerSummary);
+    }
+
+    @Test
+    public void getDynamicSummary_emptyScreenTitle_emptyControllerSummary_returnsEmptyString() {
+        final SliceData data = getDummyData(null, null);
         final FakePreferenceController controller = new FakePreferenceController(mContext, KEY);
         final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
 
@@ -236,8 +249,9 @@
     }
 
     @Test
-    public void testDynamicSummary_placeHolderString_returnsEmptyString() {
-        final SliceData data = getDummyData(mContext.getString(R.string.summary_placeholder));
+    public void
+    getDynamicSummary_emptyScreenTitle_placeHolderControllerSummary_returnsEmptyString() {
+        final SliceData data = getDummyData(mContext.getString(R.string.summary_placeholder), null);
         final FakePreferenceController controller = new FakePreferenceController(mContext, KEY);
         final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
 
@@ -245,9 +259,9 @@
     }
 
     @Test
-    public void testDynamicSummary_sliceDataAndFragmentPlaceholder_returnsSliceEmptyString() {
+    public void getDynamicSummary_screenTitleAndControllerPlaceholder_returnsSliceEmptyString() {
         final String summaryPlaceholder = mContext.getString(R.string.summary_placeholder);
-        final SliceData data = getDummyData(summaryPlaceholder);
+        final SliceData data = getDummyData(summaryPlaceholder, summaryPlaceholder);
         final FakePreferenceController controller = spy(
                 new FakePreferenceController(mContext, KEY));
         doReturn(summaryPlaceholder).when(controller).getSummary();
@@ -258,18 +272,6 @@
     }
 
     @Test
-    public void summaryText_bothDynamicAndStaticSummary_dynamicSummaryReturned() {
-        SliceData data = getDummyData("bad_summary");
-        FakePreferenceController controller = spy(new FakePreferenceController(mContext, KEY));
-        String controllerSummary = "new_Summary";
-        doReturn(controllerSummary).when(controller).getSummary();
-
-        CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
-
-        assertThat(summary).isEqualTo(controllerSummary);
-    }
-
-    @Test
     public void getPathData_splitsIntentUri() {
         final Uri uri = new Uri.Builder()
                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
@@ -417,23 +419,24 @@
     }
 
     private SliceData getDummyData() {
-        return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH);
+        return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE);
     }
 
-    private SliceData getDummyData(String summary) {
-        return getDummyData(TOGGLE_CONTROLLER, summary, SliceData.SliceType.SWITCH);
+    private SliceData getDummyData(String summary, String screenTitle) {
+        return getDummyData(TOGGLE_CONTROLLER, summary, SliceData.SliceType.SWITCH, screenTitle);
     }
 
     private SliceData getDummyData(Class prefController, int sliceType) {
-        return getDummyData(prefController, SUMMARY, sliceType);
+        return getDummyData(prefController, SUMMARY, sliceType, SCREEN_TITLE);
     }
 
-    private SliceData getDummyData(Class prefController, String summary, int sliceType) {
+    private SliceData getDummyData(Class prefController, String summary, int sliceType,
+            String screenTitle) {
         return new SliceData.Builder()
                 .setKey(KEY)
                 .setTitle(TITLE)
                 .setSummary(summary)
-                .setScreenTitle(SCREEN_TITLE)
+                .setScreenTitle(screenTitle)
                 .setKeywords(KEYWORDS)
                 .setIcon(ICON)
                 .setFragmentName(FRAGMENT_NAME)
diff --git a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
index db09eab..6a573e0 100644
--- a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.sound;
 
-
 import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
 import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
 import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
@@ -93,6 +92,8 @@
     private HeadsetProfile mHeadsetProfile;
     @Mock
     private HearingAidProfile mHearingAidProfile;
+    @Mock
+    private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback;
 
     private Context mContext;
     private PreferenceScreen mScreen;
@@ -156,6 +157,7 @@
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
         mScreen.addPreference(mPreference);
         mController.displayPreference(mScreen);
+        mController.setCallback(mAudioSwitchPreferenceCallback);
     }
 
     @After
diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
index b777239..6aec5ef 100644
--- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
@@ -94,6 +94,8 @@
     private A2dpProfile mA2dpProfile;
     @Mock
     private HearingAidProfile mHearingAidProfile;
+    @Mock
+    private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback;
 
     private Context mContext;
     private PreferenceScreen mScreen;
@@ -157,6 +159,7 @@
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
         mScreen.addPreference(mPreference);
         mController.displayPreference(mScreen);
+        mController.setCallback(mAudioSwitchPreferenceCallback);
     }
 
     @After
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index 529e32d..f617aa9 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -17,6 +17,8 @@
 package com.android.settings.testutils;
 
 import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.Slice.SUBTYPE_COLOR;
+import static android.app.slice.SliceItem.FORMAT_INT;
 import static android.app.slice.SliceItem.FORMAT_TEXT;
 
 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
@@ -33,15 +35,18 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.SliceMetadata;
+import androidx.slice.builders.ListBuilder;
 import androidx.slice.core.SliceAction;
 import androidx.slice.core.SliceQuery;
 
 import android.support.v4.graphics.drawable.IconCompat;
 
+import com.android.settings.Utils;
 import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBuilderUtils;
 import com.android.settings.slices.SliceData;
@@ -59,10 +64,19 @@
      * - Correct intent
      * - Correct title
      * - Correct keywords
+     * - TTL
+     * - Color
      */
     public static void testSettingsIntentSlice(Context context, Slice slice, SliceData sliceData) {
         final SliceMetadata metadata = SliceMetadata.from(context, slice);
 
+        final long sliceTTL = metadata.getExpiry();
+        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
+
+        final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
+        final int color = colorItem.getInt();
+        assertThat(color).isEqualTo(Utils.getColorAccent(context));
+
         final List<SliceAction> toggles = metadata.getToggles();
         assertThat(toggles).isEmpty();
 
@@ -83,13 +97,22 @@
      * - Correct content intent
      * - Correct title
      * - Correct keywords
+     * - TTL
+     * - Color
      */
     public static void testSettingsToggleSlice(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.getColorAccent(context));
+
         final List<SliceAction> toggles = metadata.getToggles();
         assertThat(toggles).hasSize(1);
 
+        final long sliceTTL = metadata.getExpiry();
+        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
+
         final SliceAction mainToggleAction = toggles.get(0);
 
         final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
@@ -117,13 +140,22 @@
      * - No intent
      * - Correct title
      * - Correct keywords
+     * - TTL
+     * - Color
      */
     public static void testSettingsSliderSlice(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.getColorAccent(context));
+
         final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
                 sliceData.getIconResource());
 
+        final long sliceTTL = metadata.getExpiry();
+        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
+
         // Check primary intent
         final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
         assertThat(primaryPendingIntent).isEqualTo(
@@ -141,11 +173,20 @@
      * - Correct title
      * - Correct intent
      * - Correct keywords
+     * - Color
+     * - TTL
      */
     public static void testSettingsUnavailableSlice(Context context, Slice slice,
             SliceData sliceData) {
         final SliceMetadata metadata = SliceMetadata.from(context, slice);
 
+        final long sliceTTL = metadata.getExpiry();
+        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
+
+        final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
+        final int color = colorItem.getInt();
+        assertThat(color).isEqualTo(Utils.getColorAccent(context));
+
         final List<SliceAction> toggles = metadata.getToggles();
         assertThat(toggles).isEmpty();
 
@@ -171,7 +212,7 @@
         assertKeywords(metadata, sliceData);
     }
 
-    private static void assertTitle(List<SliceItem> sliceItems, String title) {
+    public static void assertTitle(List<SliceItem> sliceItems, String title) {
         boolean hasTitle = false;
         for (SliceItem item : sliceItems) {
             List<SliceItem> titleItems = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE,
@@ -190,8 +231,9 @@
 
     private static void assertKeywords(SliceMetadata metadata, SliceData data) {
         final List<String> keywords = metadata.getSliceKeywords();
-        final Set<String> expectedKeywords = new HashSet<>(
-                Arrays.asList(data.getKeywords().split(",")));
+        final Set<String> expectedKeywords = Arrays.stream(data.getKeywords().split(","))
+                .map(s -> s = s.trim())
+                .collect(Collectors.toSet());
         expectedKeywords.add(data.getTitle());
         expectedKeywords.add(data.getScreenTitle().toString());
         assertThat(keywords).containsExactlyElementsIn(expectedKeywords);
diff --git a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
index e32ef77..22ad764 100644
--- a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
@@ -41,7 +41,6 @@
 import android.widget.ImageButton;
 import android.widget.TextView;
 
-import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.applications.LayoutPreference;
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -113,7 +112,7 @@
     public void bindViews_shouldBindAllData() {
         final String testString = "test";
         final View header =
-            mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
+                mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
         final TextView label = header.findViewById(R.id.entity_header_title);
         final TextView summary = header.findViewById(R.id.entity_header_summary);
         final TextView secondSummary = header.findViewById(R.id.entity_header_second_summary);
@@ -134,41 +133,6 @@
     }
 
     @Test
-    public void bindButton_hasAppPref_shouldShowButton() {
-        final ResolveInfo info = new ResolveInfo();
-        info.activityInfo = new ActivityInfo();
-        info.activityInfo.packageName = "123";
-        info.activityInfo.name = "321";
-        final View appLinks =
-            mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
-        when(mActivity.getApplicationContext()).thenReturn(mContext);
-        when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
-                .thenReturn(info);
-
-        mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
-        mController.setButtonActions(
-                EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
-                EntityHeaderController.ActionType.ACTION_NONE);
-        mController.done(mActivity);
-
-        final ImageButton button1 = appLinks.findViewById(android.R.id.button1);
-        assertThat(button1).isNotNull();
-        assertThat(button1.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(button1.getDrawable()).isNotNull();
-        assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        try {
-            appLinks.findViewById(android.R.id.button1).performClick();
-        } catch (Exception e) {
-            // Ignore exception because the launching intent is fake.
-        }
-        verify(mFeatureFactory.metricsFeatureProvider).actionWithSource(mContext,
-                MetricsProto.MetricsEvent.VIEW_UNKNOWN,
-                MetricsProto.MetricsEvent.ACTION_OPEN_APP_SETTING);
-        verify(mFragment).startActivity(any(Intent.class));
-    }
-
-    @Test
     public void bindButton_hasEditRuleNameClickListener_shouldShowButton() {
         final ResolveInfo info = new ResolveInfo();
         info.activityInfo = new ActivityInfo();
@@ -217,30 +181,9 @@
 
 
     @Test
-    public void bindButton_noAppPref_shouldNotShowButton() {
-        final View appLinks =
-            mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
-        when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
-            .thenReturn(null);
-
-        mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
-        mController.setButtonActions(
-                EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
-                EntityHeaderController.ActionType.ACTION_NONE);
-        mController.done(mActivity);
-
-        final ImageButton button1 = appLinks.findViewById(android.R.id.button1);
-        assertThat(button1).isNotNull();
-        assertThat(button1.getVisibility()).isEqualTo(View.GONE);
-        assertThat(button1.getDrawable()).isNull();
-        assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-    }
-
-    @Test
     public void bindButton_noAppInfo_shouldNotAttachClickListener() {
         final View appLinks =
-            mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
+                mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
         final Activity activity = mock(Activity.class);
         when(mFragment.getActivity()).thenReturn(activity);
 
@@ -265,7 +208,7 @@
     @Test
     public void bindButton_hasAppInfo_shouldAttachClickListener() {
         final View appLinks =
-            mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
+                mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
         final Activity activity = mock(Activity.class);
         when(mFragment.getActivity()).thenReturn(activity);
         when(mContext.getString(eq(R.string.application_info_label))).thenReturn("App Info");
@@ -281,13 +224,13 @@
 
         appLinks.findViewById(R.id.entity_header_content).performClick();
         verify(activity)
-            .startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
+                .startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
     }
 
     @Test
     public void iconContentDescription_shouldWorkWithSetIcon() {
         final View view =
-            mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
+                mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
         when(mFragment.getActivity()).thenReturn(mock(Activity.class));
         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
         String description = "Fake Description";
diff --git a/tests/robotests/src/com/android/settings/widget/UpdatableListPreferenceDialogFragmentTest.java b/tests/robotests/src/com/android/settings/widget/UpdatableListPreferenceDialogFragmentTest.java
new file mode 100644
index 0000000..cd57654
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/UpdatableListPreferenceDialogFragmentTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.v7.preference.ListPreference;
+import android.widget.ArrayAdapter;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+
+import static org.mockito.Mockito.spy;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowBluetoothUtils.class)
+public class UpdatableListPreferenceDialogFragmentTest {
+
+    private Context mContext;
+    private UpdatableListPreferenceDialogFragment mUpdatableListPrefDlgFragment;
+    private static final String KEY = "Test_Key";
+    private ArrayAdapter mAdapter;
+    private ArrayList<CharSequence> mEntries;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+
+        mUpdatableListPrefDlgFragment = UpdatableListPreferenceDialogFragment
+                .newInstance(KEY, MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES);
+        mEntries = spy(new ArrayList<>());
+        mUpdatableListPrefDlgFragment.setEntries(mEntries);
+        mUpdatableListPrefDlgFragment.
+                setMetricsCategory(mUpdatableListPrefDlgFragment.getArguments());
+        initAdapter();
+    }
+
+    private void initAdapter() {
+        mAdapter = spy(new ArrayAdapter<>(
+                mContext,
+                com.android.internal.R.layout.select_dialog_singlechoice,
+                mEntries));
+        mUpdatableListPrefDlgFragment.setAdapter(mAdapter);
+    }
+
+    @Test
+    public void getMetricsCategory() {
+        assertThat(mUpdatableListPrefDlgFragment.getMetricsCategory())
+                .isEqualTo(MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES);
+    }
+
+    @Test
+    public void onListPreferenceUpdated_verifyAdapterCanBeUpdate() {
+        assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).
+                isEqualTo(0);
+
+        ListPreference listPreference = new ListPreference(mContext);
+        final CharSequence[] charSequences = {"Test_DEVICE_1", "Test_DEVICE_2"};
+        listPreference.setEntries(charSequences);
+        mUpdatableListPrefDlgFragment.onListPreferenceUpdated(listPreference);
+
+        assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).
+                isEqualTo(2);
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSliceBuilderTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSliceBuilderTest.java
new file mode 100644
index 0000000..f1ac554
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSliceBuilderTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.settings.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.wifi.WifiSliceBuilder;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.SliceTester;
+
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.wifi.WifiManager;
+import android.support.v4.graphics.drawable.IconCompat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class WifiSliceBuilderTest {
+
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = spy(RuntimeEnvironment.application);
+
+        // Prevent crash in SliceMetadata.
+        Resources resources = spy(mContext.getResources());
+        doReturn(60).when(resources).getDimensionPixelSize(anyInt());
+        doReturn(resources).when(mContext).getResources();
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+    }
+
+    @Test
+    public void getWifiSlice_correctData() {
+        final Slice wifiSlice = WifiSliceBuilder.getSlice(mContext);
+        final SliceMetadata metadata = SliceMetadata.from(mContext, wifiSlice);
+
+
+        final List<SliceAction> toggles = metadata.getToggles();
+        assertThat(toggles).hasSize(1);
+
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+        final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_settings_wireless);
+        assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString());
+
+        final List<SliceItem> sliceItems = wifiSlice.getItems();
+        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.wifi_settings));
+    }
+
+    @Test
+    public void handleUriChange_updatesWifi() {
+        final Intent intent = new Intent(WifiSliceBuilder.ACTION_WIFI_SLICE_CHANGED);
+        intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, true);
+        final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
+
+        WifiSliceBuilder.handleUriChange(mContext, intent);
+
+        assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
index b5d0f9d..149cd22 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
@@ -123,7 +123,7 @@
     }
 
     @Test
-    public void testReceiver_goingToAirplaneMode_shouldClearPreferenceSummary() {
+    public void testReceiver_turnOnAirplaneMode_clearPreferenceSummary() {
         final ContentResolver cr = mock(ContentResolver.class);
         when(mContext.getContentResolver()).thenReturn(cr);
         Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, 1);
@@ -138,6 +138,21 @@
     }
 
     @Test
+    public void testReceiver_turnOffAirplaneMode_displayOffSummary() {
+        final ContentResolver cr = mock(ContentResolver.class);
+        when(mContext.getContentResolver()).thenReturn(cr);
+        Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, 0);
+        mController.displayPreference(mScreen);
+        final BroadcastReceiver receiver = ReflectionHelpers.getField(mController, "mReceiver");
+        final Intent broadcast = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+
+        receiver.onReceive(RuntimeEnvironment.application, broadcast);
+
+        assertThat(mPreference.getSummary().toString()).isEqualTo(
+                "Not sharing internet or content with other devices");
+    }
+
+    @Test
     public void testHandleWifiApStateChanged_stateEnabling_showEnablingSummary() {
         mController.handleWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0 /* reason */);