Merge "DO NOT MERGE Update zen onboarding" into pi-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d55493c..5dd22c2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -207,8 +207,6 @@
                 android:value="com.android.settings.category.ia.homepage"/>
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
-            <meta-data android:name="android.metadata.SLICE_URI"
-                android:value="content://android.settings.slices/action/toggle_bluetooth_switch" />
         </activity>
 
         <activity android:name="AirplaneModeVoiceActivity"
@@ -253,8 +251,6 @@
                 android:value="com.android.settings.wifi.WifiSettings" />
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
-            <meta-data android:name="android.metadata.SLICE_URI"
-                android:value="content://android.settings.slices/wifi" />
         </activity>
 
         <activity
@@ -745,7 +741,7 @@
         <activity
             android:name=".notification.ZenSuggestionActivity"
             android:label="@string/zen_mode_settings_title"
-            android:icon="@drawable/ic_zen"
+            android:icon="@drawable/ic_do_not_disturb_on_24dp"
             android:theme="@android:style/Theme.NoDisplay">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -2246,8 +2242,6 @@
                 android:value="com.android.settings.category.ia.homepage" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.fuelgauge.PowerUsageSummary" />
-            <meta-data android:name="android.metadata.SLICE_URI"
-                android:value="content://android.settings.slices/action/auto_brightness" />
         </activity>
 
         <activity
@@ -2264,8 +2258,6 @@
                 android:value="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings" />
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
-            <meta-data android:name="android.metadata.SLICE_URI"
-                android:value="content://android.settings.slices/action/battery_saver_summary" />
         </activity>
 
         <activity android:name=".fuelgauge.BatterySaverModeVoiceActivity"
@@ -2687,8 +2679,6 @@
                 android:value="true" />
             <meta-data android:name="com.android.settings.summary"
                 android:resource="@string/sound_dashboard_summary"/>
-            <meta-data android:name="android.metadata.SLICE_URI"
-                android:value="content://android.settings.slices/action/alarm_volume" />
         </activity>
 
         <!-- Show apps for which application-level notification settings are applicable -->
diff --git a/res/drawable/ic_do_not_disturb_on_24dp.xml b/res/drawable/ic_do_not_disturb_on_24dp.xml
new file mode 100644
index 0000000..cace8d4
--- /dev/null
+++ b/res/drawable/ic_do_not_disturb_on_24dp.xml
@@ -0,0 +1,28 @@
+<!--
+    Copyright (C) 2018 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10c5.52,0 10,-4.48 10,-10C22,6.48 17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8c0,-4.41 3.59,-8 8,-8c4.41,0 8,3.59 8,8C20,16.41 16.41,20 12,20z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M7,11h10v2h-10z"/>
+</vector>
diff --git a/res/drawable/ic_homepage_sound.xml b/res/drawable/ic_homepage_sound.xml
index 4991656..a7369ad 100644
--- a/res/drawable/ic_homepage_sound.xml
+++ b/res/drawable/ic_homepage_sound.xml
@@ -32,5 +32,5 @@
         android:height="@dimen/dashboard_tile_foreground_image_size"
         android:start="@dimen/dashboard_tile_foreground_image_inset"
         android:top="@dimen/dashboard_tile_foreground_image_inset"
-        android:drawable="@drawable/ic_settings_sound_white" />
+        android:drawable="@drawable/ic_volume_up_24dp" />
 </layer-list>
diff --git a/res/drawable/ic_notifications_off_24dp.xml b/res/drawable/ic_notifications_off_24dp.xml
new file mode 100644
index 0000000..1622025
--- /dev/null
+++ b/res/drawable/ic_notifications_off_24dp.xml
@@ -0,0 +1,31 @@
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="true"
+    android:height="24dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="24dp"
+    android:tint="?android:attr/colorControlNormal">
+    <path android:fillColor="#FF000000"
+          android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z" />
+    <path android:fillColor="#FF000000"
+          android:pathData="M16,16L2.81,2.81L1.39,4.22l4.85,4.85C6.09,9.68 6,10.33 6,11v6H4v2h12.17l3.61,3.61l1.41,-1.41L16,16zM8,17c0,0 0.01,-6.11 0.01,-6.16L14.17,17H8z" />
+    <path android:fillColor="#FF000000"
+          android:pathData="M12,6.5c2.49,0 4,2.02 4,4.5v2.17l2,2V11c0,-3.07 -1.63,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C9.72,4.86 9.05,5.2 8.46,5.63L9.93,7.1C10.51,6.73 11.2,6.5 12,6.5z" />
+</vector>
diff --git a/res/drawable/ic_volume_ringer_mute.xml b/res/drawable/ic_volume_ringer_mute.xml
deleted file mode 100644
index 03357e9..0000000
--- a/res/drawable/ic_volume_ringer_mute.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:height="24dp"
-        android:viewportHeight="23.4"
-        android:viewportWidth="23.3"
-        android:width="24dp"
-        android:tint="?android:attr/colorControlNormal">
-
-    <group
-        android:translateX="-0.85"
-        android:translateY="-0.5">
-        <path
-            android:fillColor="#FFF"
-            android:pathData="M20.73,19.46l-0.6,-0.6c0,0 0,0 0,0L5.54,4.26c-0.35,-0.35 -0.92,-0.35 -1.27,0c-0.35,0.35 -0.35,0.92 0,1.27l2.4,2.4C6.25,8.85 6,9.88 6,11v5l-2.15,2.15c-0.19,0.2 -0.19,0.51 0.01,0.71C3.95,18.95 4.07,19 4.2,19h13.53l1.73,1.73c0.35,0.35 0.92,0.35 1.27,0C21.09,20.38 21.09,19.81 20.73,19.46z" />
-        <path
-            android:fillColor="#FFF"
-            android:pathData="M18,11c0,-3.07 -1.64,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C9.87,4.83 9.31,5.08 8.8,5.4l9.2,9.2V11z" />
-        <path
-            android:fillColor="#FFF"
-            android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z" />
-    </group>
-
-</vector>
diff --git a/res/drawable/ic_settings_sound_white.xml b/res/drawable/ic_volume_up_24dp.xml
similarity index 61%
rename from res/drawable/ic_settings_sound_white.xml
rename to res/drawable/ic_volume_up_24dp.xml
index 4737349..8c68c00 100644
--- a/res/drawable/ic_settings_sound_white.xml
+++ b/res/drawable/ic_volume_up_24dp.xml
@@ -13,17 +13,19 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
+
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
+        android:width="24dp"
+        android:height="24dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M3 10v4c0 .55 .45 1 1 1h3l3.29 3.29c.63 .63 1.71 .18
-1.71-.71V6.41c0-.89-1.08-1.34-1.71-.71L7 9H4c-.55 0-1 .45-1 1zm13.5 2A4.5 4.5 0
-0 0 14 7.97v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 4.46v.19c0 .38 .25 .71 .61
-.85C17.18 6.54 19 9.06 19 12s-1.82 5.46-4.39 6.5c-.36 .14 -.61 .47 -.61 .85
-v.19c0 .63 .63 1.08 1.22 .86 a8.995 8.995 0 0 0 0-16.8c-.59-.23-1.22 .23 -1.22
-.86 z"/>
+        android:pathData="M3,9v6h4l5,5V4L7,9H3zM10,8.83v6.34L7.83,13H5v-2h2.83L10,8.83z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05C15.48,15.29 16.5,13.77 16.5,12z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M14,3.23v2.06c2.89,0.86 5,3.54 5,6.71c0,3.17 -2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77C21,7.72 18.01,4.14 14,3.23z"/>
 </vector>
diff --git a/res/drawable/ic_zen.xml b/res/drawable/ic_zen.xml
deleted file mode 100644
index 2c55e02..0000000
--- a/res/drawable/ic_zen.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:viewportHeight="24.0"
-        android:viewportWidth="24.0"
-        android:height="24dp"
-        android:width="24dp" >
-
-    <path
-        android:fillColor="?android:attr/colorControlActivated"
-        android:pathData="M 12 2 C 6.48 2 2 6.48 2 12 s 4.48 10 10 10 10 -4.48 10 -10 S 17.52 2 12 2 z m 4 11 H 8 c -.55 0 -1 -.45 -1 -1 s .45 -1 1 -1 h 8c.55 0 1 .45 1 1 s -.45 1 -1 1z" />
-
-</vector>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 50b6016..fda46b7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2340,6 +2340,17 @@
     <!-- Message of private dns that provides a help link. [CHAR LIMIT=NONE] -->
     <string name="private_dns_help_message"><annotation id="url">Learn more</annotation> about Private DNS features</string>
 
+    <!-- Message to display when setting wifi calling are not editable [CHAR LIMIT=NONE] -->
+    <string name="wifi_calling_pref_managed_by_carrier">Setting managed by carrier</string>
+    <!-- Message to display when wifi calling needs activation [CHAR LIMIT=NONE] -->
+    <string name="wifi_calling_settings_activation_instructions">Activate Wi\u2011Fi Calling</string>
+    <!-- Message to display when wifi calling should be on [CHAR LIMIT=NONE] -->
+    <string name="wifi_calling_turn_on">Turn on Wi\u2011Fi calling</string>
+    <!-- Message to display when carrier does not support wifi calling or doesn't want the user
+         to modify the settings [CHAR LIMIT=NONE] -->
+    <string name="wifi_calling_not_supported">Wi\u2011Fi calling is not supported for %1$s</string>
+    <!-- Carrier string to use in other messages -->
+    <string name="carrier">Carrier</string>
     <!-- Sound and alerts settings -->
     <skip/>
     <string name="display_settings_title">Display</string>
@@ -4912,6 +4923,8 @@
     <string name="background_activity_warning_dialog_title">Limit background activity?</string>
     <!-- TODO: Pending UX review. Text for the warning dialog to show to the user when limiting background activity for an app -->
     <string name="background_activity_warning_dialog_text">If you limit background activity for an app, it may misbehave</string>
+    <!-- Dialog message when app can't been restricted because it is not optimized [CHAR_LIMIT=120] -->
+    <string name="background_activity_disabled_dialog_text">Since this app is not set to optimize battery, you can\u2019t restrict it.\n\nTo restrict the app, first turn on battery optimization.</string>
 
     <!-- Title for the screen usage in power use UI [CHAR_LIMIT=60] -->
     <string name="device_screen_usage">Screen usage since full charge</string>
@@ -6905,9 +6918,13 @@
     <!-- Title for setting tile leading to Connected devices settings [CHAR LIMIT=40]-->
     <string name="connected_devices_dashboard_title">Connected devices</string>
     <!-- Summary for Connected devices settings, explaning a few important settings under it [CHAR LIMIT=NONE]-->
-    <string name="connected_devices_dashboard_summary">Bluetooth, Cast, NFC</string>
+    <string name="connected_devices_dashboard_summary">Bluetooth, driving mode, NFC</string>
     <!-- Summary for Connected devices settings, explaning a few important settings under it [CHAR LIMIT=NONE]-->
-    <string name="connected_devices_dashboard_no_nfc_summary">Bluetooth, Cast</string>
+    <string name="connected_devices_dashboard_no_nfc_summary">Bluetooth, driving mode</string>
+    <!-- Summary for Connected devices settings, explaning a few important settings under it [CHAR LIMIT=NONE]-->
+    <string name="connected_devices_dashboard_no_driving_mode_summary">Bluetooth, NFC</string>
+    <!-- Summary for Connected devices settings, explaning a few important settings under it [CHAR LIMIT=NONE]-->
+    <string name="connected_devices_dashboard_no_driving_mode_no_nfc_summary">Bluetooth</string>
     <!-- Title for setting tile leading to Apps & Notification settings [CHAR LIMIT=40]-->
     <string name="app_and_notification_dashboard_title">Apps &amp; notifications</string>
     <!-- Summary for Apps & Notification settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
diff --git a/res/xml/network_and_internet.xml b/res/xml/network_and_internet.xml
index 064d625..69d8fca 100644
--- a/res/xml/network_and_internet.xml
+++ b/res/xml/network_and_internet.xml
@@ -97,6 +97,7 @@
         android:order="15"
         android:dialogTitle="@string/select_private_dns_configuration_dialog_title"
         android:dialogLayout="@layout/private_dns_mode_dialog"
-        android:positiveButtonText="@string/save" />
+        android:positiveButtonText="@string/save"
+        android:negativeButtonText="@android:string/cancel" />
 
 </PreferenceScreen>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 61f529f..5bee7b0 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -44,7 +44,6 @@
         android:icon="@drawable/ic_local_phone_24_lib"
         android:title="@string/call_volume_option_title"
         android:order="-170"
-        settings:allowDividerAbove="true"
         settings:controller="com.android.settings.notification.CallVolumePreferenceController"/>
 
     <!-- Hands free profile output switcher -->
@@ -61,8 +60,7 @@
         android:icon="@*android:drawable/ic_audio_ring_notif"
         android:title="@string/ring_volume_option_title"
         android:order="-160"
-        settings:controller="com.android.settings.notification.RingVolumePreferenceController"
-        settings:allowDividerAbove="true"/>
+        settings:controller="com.android.settings.notification.RingVolumePreferenceController"/>
 
     <!-- Also vibrate for calls -->
     <SwitchPreference
@@ -76,7 +74,6 @@
         android:icon="@*android:drawable/ic_audio_alarm"
         android:title="@string/alarm_volume_option_title"
         android:order="-150"
-        settings:allowDividerAbove="true"
         settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
 
     <!-- Notification volume -->
@@ -102,7 +99,6 @@
         android:title="@string/gesture_prevent_ringing_sound_title"
         android:order="-110"
         android:fragment="com.android.settings.gestures.PreventRingingGestureSettings"
-        settings:allowDividerAbove="true"
         settings:controller="com.android.settings.gestures.PreventRingingPreferenceController" />
 
     <!-- Phone ringtone -->
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 94c3fb5..1e56e54 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -387,7 +387,6 @@
             if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
                 mBluetoothEnableForTether = true;
                 adapter.enable();
-                mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
                 mBluetoothTether.setEnabled(false);
                 return;
             }
diff --git a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
index c8e6f26..01c1ff6 100644
--- a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
@@ -25,11 +25,13 @@
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import android.support.v7.preference.Preference;
 
 /**
  * Controller to maintain available media Bluetooth devices
  */
-public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
+public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater
+        implements Preference.OnPreferenceClickListener {
 
     private static final String TAG = "AvailableMediaBluetoothDeviceUpdater";
     private static final boolean DBG = false;
@@ -116,5 +118,12 @@
         }
         return isFilterMatched;
     }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference) {
+        final CachedBluetoothDevice device = ((BluetoothDevicePreference) preference)
+                .getBluetoothDevice();
+        return device.setActive();
+    }
 }
 
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
index 8937b17..bab7171 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
@@ -59,24 +59,12 @@
     protected DashboardFragment mFragment;
 
     private final boolean mShowDeviceWithoutNames;
-    private Preference.OnPreferenceClickListener mDevicePreferenceClickListener = null;
-
+    
     @VisibleForTesting
     final GearPreference.OnGearClickListener mDeviceProfilesListener = pref -> {
         launchDeviceDetails(pref);
     };
 
-    private class PreferenceClickListener implements
-        Preference.OnPreferenceClickListener {
-        @Override
-        public boolean onPreferenceClick(Preference preference) {
-            final CachedBluetoothDevice device =
-                ((BluetoothDevicePreference) preference).getBluetoothDevice();
-            Log.i(TAG, "OnPreferenceClickListener: device=" + device);
-            return device.setActive();
-        }
-    }
-
     public BluetoothDeviceUpdater(Context context, DashboardFragment fragment,
             DevicePreferenceCallback devicePreferenceCallback) {
         this(fragment, devicePreferenceCallback, Utils.getLocalBtManager(context));
@@ -91,7 +79,6 @@
                 BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
         mPreferenceMap = new HashMap<>();
         mLocalManager = localManager;
-        mDevicePreferenceClickListener = new PreferenceClickListener();
     }
 
     /**
@@ -212,7 +199,10 @@
                     new BluetoothDevicePreference(mPrefContext, cachedDevice,
                             mShowDeviceWithoutNames);
             btPreference.setOnGearClickListener(mDeviceProfilesListener);
-            btPreference.setOnPreferenceClickListener(mDevicePreferenceClickListener);
+            if (this instanceof Preference.OnPreferenceClickListener) {
+                btPreference.setOnPreferenceClickListener(
+                        (Preference.OnPreferenceClickListener)this);
+            }
             mPreferenceMap.put(device, btPreference);
             mDevicePreferenceCallback.onDeviceAdded(btPreference);
         }
diff --git a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
index 34cb574..f087c6a 100644
--- a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
@@ -24,11 +24,15 @@
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import android.support.v7.preference.Preference;
+import android.util.Log;
 
 /**
  * Maintain and update saved bluetooth devices(bonded but not connected)
  */
-public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
+public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater
+        implements Preference.OnPreferenceClickListener {
+    private static final String TAG = "SavedBluetoothDeviceUpdater";
 
     public SavedBluetoothDeviceUpdater(Context context, DashboardFragment fragment,
             DevicePreferenceCallback devicePreferenceCallback) {
@@ -57,4 +61,12 @@
         final BluetoothDevice device = cachedDevice.getDevice();
         return device.getBondState() == BluetoothDevice.BOND_BONDED && !device.isConnected();
     }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference) {
+        final CachedBluetoothDevice device = ((BluetoothDevicePreference) preference)
+                .getBluetoothDevice();
+        device.connect(true);
+        return true;
+    }
 }
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index af7c900..20033b6 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -276,7 +276,7 @@
         mSummaryLoader.updateSummaryToCache(category);
         mStagingCategory = category;
         if (mSuggestionControllerMixin == null) {
-            mAdapter.setCategory(mStagingCategory);
+            ThreadUtils.postOnMainThread(() -> mAdapter.setCategory(mStagingCategory));
             return;
         }
         if (mSuggestionControllerMixin.isSuggestionLoaded()) {
diff --git a/src/com/android/settings/dashboard/conditional/DndCondition.java b/src/com/android/settings/dashboard/conditional/DndCondition.java
index 4acd332..405ed81 100644
--- a/src/com/android/settings/dashboard/conditional/DndCondition.java
+++ b/src/com/android/settings/dashboard/conditional/DndCondition.java
@@ -83,7 +83,7 @@
 
     @Override
     public Drawable getIcon() {
-        return mManager.getContext().getDrawable(R.drawable.ic_zen);
+        return mManager.getContext().getDrawable(R.drawable.ic_do_not_disturb_on_24dp);
     }
 
     @Override
diff --git a/src/com/android/settings/dashboard/conditional/RingerMutedCondition.java b/src/com/android/settings/dashboard/conditional/RingerMutedCondition.java
index bf5bc36..7f7bc2b 100644
--- a/src/com/android/settings/dashboard/conditional/RingerMutedCondition.java
+++ b/src/com/android/settings/dashboard/conditional/RingerMutedCondition.java
@@ -55,7 +55,7 @@
 
     @Override
     public Drawable getIcon() {
-        return mManager.getContext().getDrawable(R.drawable.ic_volume_ringer_mute);
+        return mManager.getContext().getDrawable(R.drawable.ic_notifications_off_24dp);
     }
 
     @Override
diff --git a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java
index 178aa27..969cb11 100644
--- a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java
+++ b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java
@@ -156,16 +156,18 @@
 
     @Override
     public void onClick(DialogInterface dialog, int which) {
-        final Context context = getContext();
-        if (mMode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
-            // Only clickable if hostname is valid, so we could save it safely
-            Settings.Global.putString(context.getContentResolver(), HOSTNAME_KEY,
-                    mEditText.getText().toString());
-        }
+        if (which == DialogInterface.BUTTON_POSITIVE) {
+            final Context context = getContext();
+            if (mMode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
+                // Only clickable if hostname is valid, so we could save it safely
+                Settings.Global.putString(context.getContentResolver(), HOSTNAME_KEY,
+                        mEditText.getText().toString());
+            }
 
-        FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
-                MetricsProto.MetricsEvent.ACTION_PRIVATE_DNS_MODE, mMode);
-        Settings.Global.putString(context.getContentResolver(), MODE_KEY, mMode);
+            FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
+                    MetricsProto.MetricsEvent.ACTION_PRIVATE_DNS_MODE, mMode);
+            Settings.Global.putString(context.getContentResolver(), MODE_KEY, mMode);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/notification/RingVolumePreferenceController.java b/src/com/android/settings/notification/RingVolumePreferenceController.java
index e328cd2..c4c71c4 100644
--- a/src/com/android/settings/notification/RingVolumePreferenceController.java
+++ b/src/com/android/settings/notification/RingVolumePreferenceController.java
@@ -17,7 +17,6 @@
 package com.android.settings.notification;
 
 import android.app.NotificationManager;
-import android.arch.lifecycle.LifecycleObserver;
 import android.arch.lifecycle.OnLifecycleEvent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -47,6 +46,8 @@
     private final RingReceiver mReceiver = new RingReceiver();
     private final H mHandler = new H();
 
+    private int mMuteIcon;
+
     public RingVolumePreferenceController(Context context) {
         this(context, KEY_RING_VOLUME);
     }
@@ -94,7 +95,7 @@
 
     @Override
     public int getMuteIcon() {
-        return R.drawable.ic_volume_ringer_vibrate;
+        return mMuteIcon;
     }
 
     private void updateRingerMode() {
@@ -104,11 +105,6 @@
         updatePreferenceIcon();
     }
 
-    private boolean wasRingerModeVibrate() {
-        return mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_SILENT
-            && mHelper.getLastAudibleStreamVolume(getAudioStream()) == 0;
-    }
-
     private void updateEffectsSuppressor() {
         final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor();
         if (Objects.equals(suppressor, mSuppressor)) return;
@@ -122,10 +118,15 @@
 
     private void updatePreferenceIcon() {
         if (mPreference != null) {
-            mPreference.showIcon(
-                    mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate()
-                            ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate
-                            : com.android.internal.R.drawable.ic_audio_ring_notif);
+            if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+                mMuteIcon = R.drawable.ic_volume_ringer_vibrate;
+                mPreference.showIcon(com.android.internal.R.drawable.ic_audio_ring_notif_vibrate);
+            } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
+                mMuteIcon = R.drawable.ic_notifications_off_24dp;
+                mPreference.showIcon(com.android.internal.R.drawable.ic_audio_ring_notif_mute);
+            } else {
+                mPreference.showIcon(com.android.internal.R.drawable.ic_audio_ring_notif);
+            }
         }
     }
 
diff --git a/src/com/android/settings/search/DeviceIndexFeatureProvider.java b/src/com/android/settings/search/DeviceIndexFeatureProvider.java
index a171844..8e64d79 100644
--- a/src/com/android/settings/search/DeviceIndexFeatureProvider.java
+++ b/src/com/android/settings/search/DeviceIndexFeatureProvider.java
@@ -65,7 +65,7 @@
         context.getSystemService(JobScheduler.class).schedule(
                 new JobInfo.Builder(jobId, jobComponent)
                         .setPersisted(true)
-                        .setMinimumLatency(1)
+                        .setMinimumLatency(1000)
                         .setOverrideDeadline(1)
                         .build());
 
diff --git a/src/com/android/settings/search/DeviceIndexUpdateJobService.java b/src/com/android/settings/search/DeviceIndexUpdateJobService.java
index 510da3a..19b7d5e 100644
--- a/src/com/android/settings/search/DeviceIndexUpdateJobService.java
+++ b/src/com/android/settings/search/DeviceIndexUpdateJobService.java
@@ -124,7 +124,7 @@
     }
 
     protected CharSequence findTitle(Slice loadedSlice, SliceMetadata metaData) {
-        ListContent content = new ListContent(this, loadedSlice);
+        ListContent content = new ListContent(null, loadedSlice);
         SliceItem headerItem = content.getHeaderItem();
         if (headerItem == null) {
             if (content.getRowItems().size() != 0) {
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index af165da..8f07447 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -18,6 +18,8 @@
 
 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;
@@ -34,7 +36,13 @@
 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.settingslib.utils.ThreadUtils;
 
 import java.net.URISyntaxException;
@@ -45,11 +53,6 @@
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 
-import androidx.slice.Slice;
-import androidx.slice.SliceProvider;
-import androidx.slice.builders.ListBuilder;
-import androidx.slice.builders.SliceAction;
-
 /**
  * A {@link SliceProvider} for Settings to enabled inline results in system apps.
  *
@@ -160,6 +163,11 @@
         switch (path) {
             case "/" + PATH_WIFI:
                 return createWifiSlice(sliceUri);
+            case "/" + PATH_WIFI_CALLING:
+                return FeatureFactory.getFactory(getContext())
+                        .getSlicesFeatureProvider()
+                        .getNewWifiCallingSliceHelper(getContext())
+                        .createWifiCallingSlice(sliceUri);
         }
 
         SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 47a7f5a..0409734 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -21,6 +21,7 @@
 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 android.app.slice.Slice;
 import android.content.BroadcastReceiver;
@@ -79,6 +80,12 @@
                     context.getContentResolver().notifyChange(uri, null);
                 }, 1000);
                 break;
+            case ACTION_WIFI_CALLING_CHANGED:
+                FeatureFactory.getFactory(context)
+                      .getSlicesFeatureProvider()
+                      .getNewWifiCallingSliceHelper(context)
+                      .handleWifiCallingChanged(intent);
+                break;
         }
     }
 
diff --git a/src/com/android/settings/slices/SlicesFeatureProvider.java b/src/com/android/settings/slices/SlicesFeatureProvider.java
index e5bba61..8dd6547 100644
--- a/src/com/android/settings/slices/SlicesFeatureProvider.java
+++ b/src/com/android/settings/slices/SlicesFeatureProvider.java
@@ -2,6 +2,8 @@
 
 import android.content.Context;
 
+import com.android.settings.wifi.calling.WifiCallingSliceHelper;
+
 /**
  * Manages Slices in Settings.
  */
@@ -24,4 +26,9 @@
      * If the data is already indexed, the data will not change.
      */
     void indexSliceData(Context context);
-}
\ No newline at end of file
+
+    /**
+     * Gets new WifiCallingSliceHelper object
+     */
+    WifiCallingSliceHelper getNewWifiCallingSliceHelper(Context context);
+}
diff --git a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
index 8e5bc06..16684bf 100644
--- a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
+++ b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
@@ -2,6 +2,7 @@
 
 import android.content.Context;
 
+import com.android.settings.wifi.calling.WifiCallingSliceHelper;
 import com.android.settingslib.utils.ThreadUtils;
 
 /**
@@ -39,4 +40,9 @@
         SlicesIndexer indexer = getSliceIndexer(context);
         indexer.indexSliceData();
     }
-}
\ No newline at end of file
+
+    @Override
+    public WifiCallingSliceHelper getNewWifiCallingSliceHelper(Context context) {
+        return new WifiCallingSliceHelper(context);
+    }
+}
diff --git a/src/com/android/settings/support/NewDeviceIntroSuggestionActivity.java b/src/com/android/settings/support/NewDeviceIntroSuggestionActivity.java
index f881e2f..cddbb57 100644
--- a/src/com/android/settings/support/NewDeviceIntroSuggestionActivity.java
+++ b/src/com/android/settings/support/NewDeviceIntroSuggestionActivity.java
@@ -20,9 +20,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
@@ -47,6 +50,8 @@
     @VisibleForTesting
     static final long PERMANENT_DISMISS_THRESHOLD = DateUtils.DAY_IN_MILLIS * 14;
 
+    public static final String TIPS_PACKAGE_NAME = "com.google.android.apps.tips";
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -62,7 +67,9 @@
     }
 
     public static boolean isSuggestionComplete(Context context) {
-        return !isSupported(context)
+        // Always returns 'true' if Tips application exists. Check b/77652536 for more details.
+        return isTipsInstalledAsSystemApp(context)
+                || !isSupported(context)
                 || isExpired(context)
                 || hasLaunchedBefore(context)
                 || !canOpenUrlInBrowser(context);
@@ -130,4 +137,18 @@
                 .addCategory(Intent.CATEGORY_BROWSABLE)
                 .setData(Uri.parse(url));
     }
+
+    /**
+     * Check if the specified package exists and is marked with <i>FLAG_SYSTEM</i>
+     */
+    private static boolean isTipsInstalledAsSystemApp(@NonNull Context context) {
+        try {
+            final PackageInfo info = context.getPackageManager().getPackageInfo(TIPS_PACKAGE_NAME,
+                    PackageManager.MATCH_SYSTEM_ONLY);
+            return info != null;
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(TAG, "Cannot find the package: " + TIPS_PACKAGE_NAME, e);
+            return false;
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
new file mode 100644
index 0000000..7213148
--- /dev/null
+++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
@@ -0,0 +1,363 @@
+/*
+ * 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.calling;
+
+import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.PersistableBundle;
+import android.support.v4.graphics.drawable.IconCompat;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+import com.android.ims.ImsManager;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.slices.SliceBroadcastReceiver;
+import com.android.settings.slices.SliceBuilderUtils;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+
+/**
+ * Helper class to control slices for wifi calling settings.
+ */
+public class WifiCallingSliceHelper {
+
+    private static final String TAG = "WifiCallingSliceHelper";
+
+    /**
+     * Settings slice path to wifi calling setting.
+     */
+    public static final String PATH_WIFI_CALLING = "wifi_calling";
+
+    /**
+     * Action passed for changes to wifi calling slice (toggle).
+     */
+    public static final String ACTION_WIFI_CALLING_CHANGED =
+            "com.android.settings.wifi.calling.action.WIFI_CALLING_CHANGED";
+
+    /**
+     * Action for Wifi calling Settings activity which
+     * allows setting configuration for Wifi calling
+     * related settings
+     */
+    public static final String ACTION_WIFI_CALLING_SETTINGS_ACTIVITY =
+            "android.settings.WIFI_CALLING_SETTINGS";
+
+    /**
+     * 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;
+
+    @VisibleForTesting
+    public WifiCallingSliceHelper(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Returns Slice object for wifi calling settings.
+     *
+     * If wifi calling is being turned on and if wifi calling activation is needed for the current
+     * carrier, this method will return Slice with instructions to go to Settings App.
+     *
+     * If wifi calling is not supported for the current carrier, this method will return slice with
+     * not supported message.
+     *
+     * If wifi calling setting can be changed, this method will return the slice to toggle wifi
+     * calling option with ACTION_WIFI_CALLING_CHANGED as endItem.
+     */
+    public Slice createWifiCallingSlice(Uri sliceUri) {
+        final int subId = getDefaultVoiceSubId();
+        final String carrierName = getSimCarrierName();
+
+        if (subId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            Log.d(TAG, "Invalid subscription Id");
+            return getNonActionableWifiCallingSlice(
+                    mContext.getString(R.string.wifi_calling_settings_title),
+                    mContext.getString(R.string.wifi_calling_not_supported, carrierName),
+                    sliceUri, SliceBuilderUtils.getSettingsIntent(mContext));
+        }
+
+        final ImsManager imsManager = getImsManager(subId);
+
+        if (!imsManager.isWfcEnabledByPlatform()
+                || !imsManager.isWfcProvisionedOnDevice()) {
+            Log.d(TAG, "Wifi calling is either not provisioned or not enabled by Platform");
+            return getNonActionableWifiCallingSlice(
+                    mContext.getString(R.string.wifi_calling_settings_title),
+                    mContext.getString(R.string.wifi_calling_not_supported, carrierName),
+                    sliceUri, SliceBuilderUtils.getSettingsIntent(mContext));
+        }
+
+        try {
+            final boolean isWifiCallingEnabled = isWifiCallingEnabled(imsManager);
+            final Intent activationAppIntent =
+                    getWifiCallingCarrierActivityIntent(subId);
+
+            // Send this actionable wifi calling slice to toggle the setting
+            // only when there is no need for wifi calling activation with the server
+            if (activationAppIntent != null && !isWifiCallingEnabled) {
+                Log.d(TAG, "Needs Activation");
+                // Activation needed for the next action of the user
+                // Give instructions to go to settings app
+                return getNonActionableWifiCallingSlice(
+                        mContext.getString(R.string.wifi_calling_settings_title),
+                        mContext.getString(
+                                R.string.wifi_calling_settings_activation_instructions),
+                        sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY));
+            }
+            return getWifiCallingSlice(sliceUri, mContext, isWifiCallingEnabled);
+        } catch (InterruptedException | TimeoutException | ExecutionException e) {
+            Log.e(TAG, "Unable to read the current WiFi calling status", e);
+            return getNonActionableWifiCallingSlice(
+                    mContext.getString(R.string.wifi_calling_settings_title),
+                    mContext.getString(R.string.wifi_calling_turn_on),
+                    sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY));
+        }
+    }
+
+    private boolean isWifiCallingEnabled(ImsManager imsManager)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        final FutureTask<Boolean> isWifiOnTask = new FutureTask<>(new Callable<Boolean>() {
+            @Override
+            public Boolean call() {
+                return imsManager.isWfcEnabledByUser();
+            }
+        });
+        final ExecutorService executor = Executors.newSingleThreadExecutor();
+        executor.execute(isWifiOnTask);
+
+        Boolean isWifiEnabledByUser = false;
+        isWifiEnabledByUser = isWifiOnTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+
+        return isWifiEnabledByUser && imsManager.isNonTtyOrTtyOnVolteEnabled();
+    }
+
+    /**
+     * Builds a toggle slice where the intent takes you to the wifi calling page and the toggle
+     * enables/disables wifi calling.
+     */
+    private Slice getWifiCallingSlice(Uri sliceUri, Context mContext,
+            boolean isWifiCallingEnabled) {
+
+        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)
+                .setColor(R.color.material_blue_500)
+                .addRow(b -> b
+                        .setTitle(title)
+                        .addEndItem(
+                                new SliceAction(
+                                        getBroadcastIntent(ACTION_WIFI_CALLING_CHANGED),
+                                        null /* actionTitle */, isWifiCallingEnabled))
+                        .setPrimaryAction(new SliceAction(
+                                getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
+                                icon,
+                                title)))
+                .build();
+    }
+
+    protected ImsManager getImsManager(int subId) {
+        return ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(subId));
+    }
+
+    private Integer getWfcMode(ImsManager imsManager)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        FutureTask<Integer> wfcModeTask = new FutureTask<>(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return imsManager.getWfcMode(false);
+            }
+        });
+        ExecutorService executor = Executors.newSingleThreadExecutor();
+        executor.execute(wfcModeTask);
+        return wfcModeTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Handles wifi calling setting change from wifi calling slice and posts notification. Should be
+     * called when intent action is ACTION_WIFI_CALLING_CHANGED. Executed in @WorkerThread
+     *
+     * @param intent action performed
+     */
+    public void handleWifiCallingChanged(Intent intent) {
+        final int subId = getDefaultVoiceSubId();
+
+        if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            final ImsManager imsManager = getImsManager(subId);
+            if (imsManager.isWfcEnabledByPlatform()
+                    || imsManager.isWfcProvisionedOnDevice()) {
+                final boolean currentValue = imsManager.isWfcEnabledByUser()
+                        && imsManager.isNonTtyOrTtyOnVolteEnabled();
+                final boolean newValue = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
+                        currentValue);
+                final Intent activationAppIntent =
+                        getWifiCallingCarrierActivityIntent(subId);
+                if (!newValue || activationAppIntent == null) {
+                    // If either the action is to turn off wifi calling setting
+                    // or there is no activation involved - Update the setting
+                    if (newValue != currentValue) {
+                        imsManager.setWfcSetting(newValue);
+                    }
+                }
+            }
+        }
+        // notify change in slice in any case to get re-queried. This would result in displaying
+        // appropriate message with the updated setting.
+        final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING, false /*isPlatformSlice*/);
+        mContext.getContentResolver().notifyChange(uri, null);
+    }
+
+    /**
+     * Returns Slice with the title and subtitle provided as arguments with wifi signal Icon.
+     *
+     * @param title Title of the slice
+     * @param subtitle Subtitle of the slice
+     * @param sliceUri slice uri
+     * @return Slice with title and subtitle
+     */
+    // TODO(b/79548264) asses different scenarios and return null instead of non-actionable slice
+    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)
+                .setColor(R.color.material_blue_500)
+                .addRow(b -> b
+                        .setTitle(title)
+                        .setSubtitle(subtitle)
+                        .setPrimaryAction(new SliceAction(
+                                primaryActionIntent, icon,
+                                title)))
+                .build();
+    }
+
+    /**
+     * Returns {@code true} when the key is enabled for the carrier, and {@code false} otherwise.
+     */
+    private boolean isCarrierConfigManagerKeyEnabled(Context mContext, String key,
+            int subId, boolean defaultValue) {
+        final CarrierConfigManager configManager = getCarrierConfigManager(mContext);
+        boolean ret = false;
+        if (configManager != null) {
+            final PersistableBundle bundle = configManager.getConfigForSubId(subId);
+            if (bundle != null) {
+                ret = bundle.getBoolean(key, defaultValue);
+            }
+        }
+        return ret;
+    }
+
+    protected CarrierConfigManager getCarrierConfigManager(Context mContext) {
+        return mContext.getSystemService(CarrierConfigManager.class);
+    }
+
+    /**
+     * Returns the current default voice subId obtained from SubscriptionManager
+     */
+    protected int getDefaultVoiceSubId() {
+        if (mSubscriptionManager == null) {
+            mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+        }
+        return SubscriptionManager.getDefaultVoiceSubscriptionId();
+    }
+
+    /**
+     * Returns Intent of the activation app required to activate wifi calling or null if there is no
+     * need for activation.
+     */
+    protected Intent getWifiCallingCarrierActivityIntent(int subId) {
+        final CarrierConfigManager configManager = getCarrierConfigManager(mContext);
+        if (configManager == null) {
+            return null;
+        }
+
+        final PersistableBundle bundle = configManager.getConfigForSubId(subId);
+        if (bundle == null) {
+            return null;
+        }
+
+        final String carrierApp = bundle.getString(
+                CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING);
+        if (TextUtils.isEmpty(carrierApp)) {
+            return null;
+        }
+
+        final ComponentName componentName = ComponentName.unflattenFromString(carrierApp);
+        if (componentName == null) {
+            return null;
+        }
+
+        final Intent intent = new Intent();
+        intent.setComponent(componentName);
+        return intent;
+    }
+
+    private PendingIntent getBroadcastIntent(String action) {
+        final Intent intent = new Intent(action);
+        intent.setClass(mContext, SliceBroadcastReceiver.class);
+        return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent,
+                PendingIntent.FLAG_CANCEL_CURRENT);
+    }
+
+    /**
+     * Returns PendingIntent to start activity specified by action
+     */
+    private PendingIntent getActivityIntent(String action) {
+        final Intent intent = new Intent(action);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
+    }
+
+    /**
+     * Returns carrier id name of the current Subscription
+     */
+    private String getSimCarrierName() {
+        final TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+        final CharSequence carrierName = telephonyManager.getSimCarrierIdName();
+        if (carrierName == null) {
+            return mContext.getString(R.string.carrier);
+        }
+        return carrierName.toString();
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
index ed95015..ced8fc4 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
@@ -73,6 +73,7 @@
     private AvailableMediaBluetoothDeviceUpdater mBluetoothDeviceUpdater;
     private Collection<CachedBluetoothDevice> cachedDevices;
     private ShadowAudioManager mShadowAudioManager;
+    private BluetoothDevicePreference mPreference;
 
     @Before
     public void setUp() {
@@ -93,6 +94,7 @@
         mBluetoothDeviceUpdater = spy(new AvailableMediaBluetoothDeviceUpdater(mDashboardFragment,
                 mDevicePreferenceCallback, mLocalManager));
         mBluetoothDeviceUpdater.setPrefContext(mContext);
+        mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, false);
         doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
         doNothing().when(mBluetoothDeviceUpdater).removePreference(any());
     }
@@ -208,5 +210,12 @@
 
         verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
     }
+
+    @Test
+    public void onClick_Preference_setActive() {
+        mBluetoothDeviceUpdater.onPreferenceClick(mPreference);
+
+        verify(mCachedBluetoothDevice).setActive();
+    }
 }
 
diff --git a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
index fae014f..547727b 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
@@ -57,7 +57,8 @@
     private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
 
     private Context mContext;
-    private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
+    private SavedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
+    private BluetoothDevicePreference mPreference;
 
     @Before
     public void setUp() {
@@ -71,6 +72,7 @@
         mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mDashboardFragment,
                 mDevicePreferenceCallback, mLocalManager));
         mBluetoothDeviceUpdater.setPrefContext(mContext);
+        mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, false);
         doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
         doNothing().when(mBluetoothDeviceUpdater).removePreference(any());
     }
@@ -110,4 +112,11 @@
 
         verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
     }
+
+    @Test
+    public void onClick_Preference_setConnect() {
+        mBluetoothDeviceUpdater.onPreferenceClick(mPreference);
+
+        verify(mCachedBluetoothDevice).connect(true);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogPreferenceTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogPreferenceTest.java
index e9ffa8a..dfea6fb 100644
--- a/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogPreferenceTest.java
@@ -28,7 +28,10 @@
 
 import android.app.AlertDialog;
 import android.app.Fragment;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.net.ConnectivityManager;
 import android.provider.Settings;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -150,4 +153,36 @@
             assertThat(mSaveButton.isEnabled()).named("provider: " + invalid).isFalse();
         }
     }
+
+    @Test
+    public void testOnClick_positiveButtonClicked_saveData() {
+        // Set the default settings to OFF
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        Settings.Global.putString(contentResolver, Settings.Global.PRIVATE_DNS_MODE,
+                ConnectivityManager.PRIVATE_DNS_MODE_OFF);
+
+        mPreference.mMode = ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+        mPreference.onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+        // Change to OPPORTUNISTIC
+        assertThat(Settings.Global.getString(contentResolver,
+                Settings.Global.PRIVATE_DNS_MODE)).isEqualTo(
+                ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC);
+    }
+
+    @Test
+    public void testOnClick_negativeButtonClicked_doNothing() {
+        // Set the default settings to OFF
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        Settings.Global.putString(contentResolver, Settings.Global.PRIVATE_DNS_MODE,
+                ConnectivityManager.PRIVATE_DNS_MODE_OFF);
+
+        mPreference.mMode = ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+        mPreference.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+        // Still equal to OFF
+        assertThat(Settings.Global.getString(contentResolver,
+                Settings.Global.PRIVATE_DNS_MODE)).isEqualTo(
+                ConnectivityManager.PRIVATE_DNS_MODE_OFF);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java b/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
index 286676d..8b03376 100644
--- a/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
+++ b/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
@@ -19,7 +19,10 @@
 import static com.android.settings.support.NewDeviceIntroSuggestionActivity.PERMANENT_DISMISS_THRESHOLD;
 import static com.android.settings.support.NewDeviceIntroSuggestionActivity.PREF_KEY_SUGGGESTION_COMPLETE;
 import static com.android.settings.support.NewDeviceIntroSuggestionActivity.PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME;
+
+import static com.android.settings.support.NewDeviceIntroSuggestionActivity.TIPS_PACKAGE_NAME;
 import static com.android.settings.support.NewDeviceIntroSuggestionActivity.isSuggestionComplete;
+
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.when;
@@ -27,6 +30,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
 import android.content.pm.ResolveInfo;
 
 import com.android.settings.R;
@@ -65,6 +69,40 @@
     }
 
     @Test
+    public void isSuggestionComplete_TipsNotExistsAndNotExpiredAndCanOpenUrl_shouldReturnFalse() {
+        mShadowPackageManager.removePackage(TIPS_PACKAGE_NAME);
+
+        when(mMockContext.getResources()
+                .getBoolean(R.bool.config_new_device_intro_suggestion_supported))
+                .thenReturn(true);
+
+        when(mFeatureFactory.supportFeatureProvider.getNewDeviceIntroUrl(any(Context.class)))
+                .thenReturn("https://com.android.settings");
+        final Intent intent = NewDeviceIntroSuggestionActivity.getLaunchIntent(mContext);
+        mShadowPackageManager.addResolveInfoForIntent(intent, new ResolveInfo());
+
+        assertThat(isSuggestionComplete(mContext)).isFalse();
+    }
+
+    @Test
+    public void isSuggestionComplete_TipsExistsAndNotExpiredAndCanOpenUrl_shouldReturnTrue() {
+        final PackageInfo mockInfo = new PackageInfo();
+        mockInfo.packageName = TIPS_PACKAGE_NAME;
+        mShadowPackageManager.addPackage(mockInfo);
+
+        when(mMockContext.getResources()
+                .getBoolean(R.bool.config_new_device_intro_suggestion_supported))
+                .thenReturn(true);
+
+        when(mFeatureFactory.supportFeatureProvider.getNewDeviceIntroUrl(any(Context.class)))
+                .thenReturn("https://com.android.settings");
+        final Intent intent = NewDeviceIntroSuggestionActivity.getLaunchIntent(mContext);
+        mShadowPackageManager.addResolveInfoForIntent(intent, new ResolveInfo());
+
+        assertThat(isSuggestionComplete(mContext)).isTrue();
+    }
+
+    @Test
     public void isSuggestionComplete_notSupported_shouldReturnTrue() {
         when(mMockContext.getResources()
                 .getBoolean(R.bool.config_new_device_intro_suggestion_supported))
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
new file mode 100644
index 0000000..ac3ff3f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -0,0 +1,316 @@
+/*
+ * 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.calling;
+
+import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
+import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+
+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 static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.telephony.CarrierConfigManager;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.core.SliceQuery;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.ims.ImsManager;
+import com.android.settings.R;
+import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.SliceBroadcastReceiver;
+import com.android.settings.slices.SliceBuilderUtils;
+import com.android.settings.slices.SliceData;
+import com.android.settings.slices.SlicesFeatureProvider;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class WifiCallingSliceHelperTest {
+
+    private Context mContext;
+    @Mock
+    private CarrierConfigManager mMockCarrierConfigManager;
+
+    @Mock
+    private ImsManager mMockImsManager;
+
+    private final Uri mWfcURI = Uri.parse("content://com.android.settings.slices/wifi_calling");
+
+    private FakeWifiCallingSliceHelper mWfcSliceHelper;
+    private SettingsSliceProvider mProvider;
+    private SliceBroadcastReceiver mReceiver;
+    private FakeFeatureFactory mFeatureFactory;
+    private SlicesFeatureProvider mSlicesFeatureProvider;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+
+        //setup for SettingsSliceProvider tests
+        mProvider = spy(new SettingsSliceProvider());
+        doReturn(mContext).when(mProvider).getContext();
+
+        //setup for SliceBroadcastReceiver test
+        mReceiver = spy(new SliceBroadcastReceiver());
+
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider();
+
+        // Prevent crash in SliceMetadata.
+        Resources resources = spy(mContext.getResources());
+        doReturn(60).when(resources).getDimensionPixelSize(anyInt());
+        doReturn(resources).when(mContext).getResources();
+
+        mWfcSliceHelper = new FakeWifiCallingSliceHelper(mContext);
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+    }
+
+    @Test
+    public void test_CreateWifiCallingSlice_invalidSubId() {
+        mWfcSliceHelper.setDefaultVoiceSubId(-1);
+
+        final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI);
+
+        testWifiCallingSettingsUnavailableSlice(slice, null,
+                SliceBuilderUtils.getSettingsIntent(mContext));
+    }
+
+    @Test
+    public void test_CreateWifiCallingSlice_wfcNotSupported() {
+        doReturn(false).when(mMockImsManager).isWfcEnabledByPlatform();
+
+        final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI);
+
+        assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
+        testWifiCallingSettingsUnavailableSlice(slice, null,
+                SliceBuilderUtils.getSettingsIntent(mContext));
+    }
+
+    @Test
+    public void test_CreateWifiCallingSlice_needsActivation() {
+        /* In cases where activation is needed and the user action
+        would be turning on the wifi calling (i.e. if wifi calling is
+        turned off) we need to guide the user to wifi calling settings
+        activity so the user can perform the activation there.(PrimaryAction)
+         */
+        doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform();
+        doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice();
+        doReturn(false).when(mMockImsManager).isWfcEnabledByUser();
+        doReturn(false).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1);
+        mWfcSliceHelper.setActivationAppIntent(new Intent()); // dummy Intent
+
+        final Slice slice  = mWfcSliceHelper.createWifiCallingSlice(mWfcURI);
+
+        assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
+        testWifiCallingSettingsUnavailableSlice(slice, null,
+                getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY));
+    }
+
+    @Test
+    public void test_CreateWifiCallingSlice_success() {
+        doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform();
+        doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice();
+        doReturn(true).when(mMockImsManager).isWfcEnabledByUser();
+        doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1);
+
+        final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI);
+
+        assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
+        testWifiCallingSettingsToggleSlice(slice, null);
+    }
+
+    @Test
+    public void test_SettingSliceProvider_getsRightSliceWifiCalling() {
+        doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform();
+        doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice();
+        doReturn(true).when(mMockImsManager).isWfcEnabledByUser();
+        doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1);
+        doReturn(mWfcSliceHelper).when(mSlicesFeatureProvider)
+              .getNewWifiCallingSliceHelper(mContext);
+
+        final Slice slice = mProvider.onBindSlice(mWfcURI);
+
+        assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
+        testWifiCallingSettingsToggleSlice(slice, null);
+    }
+
+    @Test
+    public void test_SliceBroadcastReceiver_toggleOffWifiCalling() {
+        doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform();
+        doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice();
+        doReturn(false).when(mMockImsManager).isWfcEnabledByUser();
+        doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(mWfcSliceHelper).when(mSlicesFeatureProvider)
+              .getNewWifiCallingSliceHelper(mContext);
+        mWfcSliceHelper.setActivationAppIntent(null);
+
+        ArgumentCaptor<Boolean> mWfcSettingCaptor = ArgumentCaptor.forClass(Boolean.class);
+
+        // turn on Wifi calling setting
+        Intent intent = new Intent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED);
+        intent.putExtra(EXTRA_TOGGLE_STATE, true);
+
+        // change the setting
+        mReceiver.onReceive(mContext, intent);
+
+        verify((mMockImsManager)).setWfcSetting(mWfcSettingCaptor.capture());
+
+        // assert the change
+        assertThat(mWfcSettingCaptor.getValue()).isTrue();
+    }
+
+    private void testWifiCallingSettingsUnavailableSlice(Slice slice,
+            SliceData sliceData, PendingIntent expectedPrimaryAction) {
+        final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+
+        //Check there is no toggle action
+        final List<SliceAction> toggles = metadata.getToggles();
+        assertThat(toggles).isEmpty();
+
+        // Check whether the primary action is to open wifi calling settings activity
+        final PendingIntent primaryPendingIntent =
+                metadata.getPrimaryAction().getAction();
+        assertThat(primaryPendingIntent).isEqualTo(expectedPrimaryAction);
+
+        // Check the title
+        final List<SliceItem> sliceItems = slice.getItems();
+        assertTitle(sliceItems, mContext.getString(R.string.wifi_calling_settings_title));
+    }
+
+    private void testWifiCallingSettingsToggleSlice(Slice slice,
+            SliceData sliceData) {
+        final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+
+        final List<SliceAction> toggles = metadata.getToggles();
+        assertThat(toggles).hasSize(1);
+
+        final SliceAction mainToggleAction = toggles.get(0);
+
+        // Check intent in Toggle Action
+        final PendingIntent togglePendingIntent = mainToggleAction.getAction();
+        final PendingIntent expectedToggleIntent = getBroadcastIntent(
+                WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED);
+        assertThat(togglePendingIntent).isEqualTo(expectedToggleIntent);
+
+        // Check primary intent
+        final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
+        final PendingIntent expectedPendingIntent =
+                getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY);
+        assertThat(primaryPendingIntent).isEqualTo(expectedPendingIntent);
+
+        // Check the title
+        final List<SliceItem> sliceItems = slice.getItems();
+        assertTitle(sliceItems, mContext.getString(R.string.wifi_calling_settings_title));
+    }
+
+    private PendingIntent getBroadcastIntent(String action) {
+        final Intent intent = new Intent(action);
+        intent.setClass(mContext, SliceBroadcastReceiver.class);
+        return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent,
+                PendingIntent.FLAG_CANCEL_CURRENT);
+    }
+
+    private PendingIntent getActivityIntent(String action) {
+        final Intent intent = new Intent(action);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
+    }
+
+    private void assertTitle(List<SliceItem> sliceItems, String title) {
+        boolean hasTitle = false;
+        for (SliceItem item : sliceItems) {
+            List<SliceItem> titleItems = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE,
+                    null /* non-hints */);
+            if (titleItems == null) {
+                continue;
+            }
+
+            hasTitle = true;
+            for (SliceItem subTitleItem : titleItems) {
+                assertThat(subTitleItem.getText()).isEqualTo(title);
+            }
+        }
+        assertThat(hasTitle).isTrue();
+    }
+    private class FakeWifiCallingSliceHelper extends WifiCallingSliceHelper {
+        int mSubId = 1;
+
+        private Intent mActivationAppIntent;
+        FakeWifiCallingSliceHelper(Context context) {
+            super(context);
+            mActivationAppIntent = null;
+        }
+
+        @Override
+        protected CarrierConfigManager getCarrierConfigManager(Context mContext) {
+            return mMockCarrierConfigManager;
+        }
+
+        @Override
+        protected ImsManager getImsManager(int subId) {
+            return mMockImsManager;
+        }
+
+        protected int getDefaultVoiceSubId() {
+            return mSubId;
+        }
+
+        protected void setDefaultVoiceSubId(int id) {
+            mSubId = id;
+        }
+
+        @Override
+        protected Intent getWifiCallingCarrierActivityIntent(int subId) {
+            return mActivationAppIntent;
+        }
+
+        public void setActivationAppIntent(Intent intent) {
+            mActivationAppIntent = intent;
+        }
+    }
+}