Merge "Update phone vibrate icon in condition card."
diff --git a/res/values/config.xml b/res/values/config.xml
index 284b653..8e55ea9 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -38,9 +38,6 @@
     <!-- When true enable color temperature setting. -->
     <bool name="config_enableColorTemperature">false</bool>
 
-    <!-- Whether to show Connectivity Monitor switch in Developer Options -->
-    <bool name="config_show_connectivity_monitor">false</bool>
-
     <!-- Whether to show Camera laser sensor switch in Developer Options -->
     <bool name="config_show_camera_laser_sensor">false</bool>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e9efa48..e0e1a30 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9095,15 +9095,6 @@
     <!-- Toast message letting the user know the color temperature setting is not immediate -->
     <string name="color_temperature_toast">To apply color change, turn off screen</string>
 
-    <!-- UI debug setting: title for ConnectivityMonitor switch [CHAR LIMIT=50] -->
-    <string name="connectivity_monitor_switch">Connectivity Monitor</string>
-
-    <!-- UI debug setting: summary for switch of ConnectivityMonitor [CHAR LIMIT=500] -->
-    <string name="connectivity_monitor_switch_summary">ConnectivityMonitor will collect logs when it detects a connectivity problem and prompt notification to user to file a bug</string>
-
-    <!-- Toast message letting the user know the how to apply connectivity monitor change -->
-    <string name="connectivity_monitor_toast">To apply connectivity monitor change, reboot device</string>
-
     <!-- Title for Camera laser sensor switch [CHAR LIMIT=NONE] -->
     <string name="camera_laser_sensor_switch">Camera Laser Sensor</string>
 
diff --git a/res/xml/battery_saver_settings.xml b/res/xml/battery_saver_settings.xml
index 116079d..0460459 100644
--- a/res/xml/battery_saver_settings.xml
+++ b/res/xml/battery_saver_settings.xml
@@ -18,32 +18,35 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/battery_saver"
-    android:key="battery_saver">
+    android:key="battery_saver_page">
 
     <!-- Turn on automatically -->
     <SwitchPreference
         android:key="auto_battery_saver"
         android:title="@string/battery_saver_auto_title"
-        settings:controller="com.android.settings.fuelgauge.batterysaver.AutoBatterySaverPreferenceController"/>
+        settings:controller="com.android.settings.fuelgauge.batterysaver.AutoBatterySaverPreferenceController" />
 
     <com.android.settings.widget.SeekBarPreference
         android:key="battery_saver_seek_bar"
         android:title="@string/battery_saver_seekbar_title_placeholder"
         android:max="75"
-        android:min="5"/>
+        android:min="5" />
 
     <com.android.settings.widget.TwoStateButtonPreference
-        android:key="battery_saver_button_container"
+        android:key="battery_saver"
+        android:title="@string/battery_saver"
         android:selectable="false"
         settings:textOn="@string/battery_saver_button_turn_on"
-        settings:textOff="@string/battery_saver_button_turn_off"/>
+        settings:textOff="@string/battery_saver_button_turn_off"
+        settings:platform_slice="true"
+        settings:controller="com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceController" />
 
     <PreferenceCategory
         android:key="battery_saver_footer">
         <com.android.settingslib.widget.FooterPreference
             android:key="battery_saver_footer_preference"
             android:title="@*android:string/battery_saver_description"
-            android:selectable="false"/>
+            android:selectable="false" />
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index f81fd79..41d3e9b 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -32,12 +32,14 @@
         android:title="@string/nfc_quick_toggle_title"
         android:icon="@drawable/ic_nfc"
         android:summary="@string/nfc_quick_toggle_summary"
+        settings:controller="com.android.settings.nfc.NfcPreferenceController"
         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"
+        settings:controller="com.android.settings.nfc.AndroidBeamPreferenceController"
         android:icon="@drawable/ic_android"
         android:order="-6"/>
 
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 615d693..55386a2 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -184,11 +184,6 @@
             android:entryValues="@array/select_logpersist_values" />
 
         <SwitchPreference
-            android:key="connectivity_monitor_switch"
-            android:title="@string/connectivity_monitor_switch"
-            android:summary="@string/connectivity_monitor_switch_summary" />
-
-        <SwitchPreference
             android:key="camera_laser_sensor_switch"
             android:title="@string/camera_laser_sensor_switch" />
 
diff --git a/res/xml/network_and_internet.xml b/res/xml/network_and_internet.xml
index 69d8fca..6eda0b0 100644
--- a/res/xml/network_and_internet.xml
+++ b/res/xml/network_and_internet.xml
@@ -68,12 +68,13 @@
         settings:useAdminDisabledSummary="true" />
 
     <com.android.settingslib.RestrictedSwitchPreference
-        android:key="toggle_airplane"
+        android:key="airplane_mode"
         android:title="@string/airplane_mode"
         android:icon="@drawable/ic_airplanemode_active"
         android:disableDependentsState="true"
         android:order="5"
         settings:controller="com.android.settings.network.AirplaneModePreferenceController"
+        settings:platform_slice="true"
         settings:userRestriction="no_airplane_mode"/>
 
     <Preference
diff --git a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
index 1de04f9..5ec193c 100644
--- a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
+++ b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
@@ -17,6 +17,8 @@
 
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+
 import android.annotation.ColorInt;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
index 76e7901..2ff96a7 100644
--- a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
+++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
@@ -51,7 +51,7 @@
      */
     public static int getConnectedDevicesSummaryResourceId(Context context) {
         final NfcPreferenceController nfcPreferenceController =
-                new NfcPreferenceController(context);
+                new NfcPreferenceController(context, NfcPreferenceController.KEY_TOGGLE_NFC);
 
         return getConnectedDevicesSummaryResourceId(nfcPreferenceController,
                 isDrivingModeAvailable(context));
diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java
index e437b76..1b46963 100644
--- a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragment.java
@@ -24,7 +24,6 @@
 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;
@@ -72,25 +71,15 @@
             Lifecycle lifecycle) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
 
-        final AndroidBeamPreferenceController beamPreferenceController =
-                new AndroidBeamPreferenceController(context);
-        controllers.add(beamPreferenceController);
-
         controllers.add(new BluetoothFilesPreferenceController(context));
         controllers.add(new BluetoothOnWhileDrivingPreferenceController(context));
 
         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/core/BasePreferenceController.java b/src/com/android/settings/core/BasePreferenceController.java
index 4c4d74d..b18581a 100644
--- a/src/com/android/settings/core/BasePreferenceController.java
+++ b/src/com/android/settings/core/BasePreferenceController.java
@@ -252,6 +252,16 @@
     }
 
     /**
+     * @return {@code true} if the setting update asynchronously.
+     * <p>
+     * For example, a Wifi controller would return true, because it needs to update the radio
+     * and wait for it to turn on.
+     */
+    public boolean hasAsyncUpdate() {
+        return false;
+    }
+
+    /**
      * Updates non-indexable keys for search provider.
      *
      * Called by SearchIndexProvider#getNonIndexableKeys
diff --git a/src/com/android/settings/development/ConnectivityMonitorPreferenceController.java b/src/com/android/settings/development/ConnectivityMonitorPreferenceController.java
deleted file mode 100644
index de5b2cc..0000000
--- a/src/com/android/settings/development/ConnectivityMonitorPreferenceController.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development;
-
-import android.content.Context;
-import android.os.SystemProperties;
-import androidx.preference.SwitchPreference;
-import androidx.preference.Preference;
-import android.text.TextUtils;
-import android.widget.Toast;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.development.DeveloperOptionsPreferenceController;
-
-public class ConnectivityMonitorPreferenceController extends DeveloperOptionsPreferenceController
-        implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
-
-    private static final String KEY_CONNECTIVITY_MONITOR_SWITCH = "connectivity_monitor_switch";
-    @VisibleForTesting
-    static final String BUILD_TYPE = "ro.build.type";
-    @VisibleForTesting
-    static final String PROPERTY_CONNECTIVITY_MONITOR = "persist.radio.enable_tel_mon";
-
-    @VisibleForTesting
-    static final String ENABLED_STATUS = "enabled";
-    @VisibleForTesting
-    static final String DISABLED_STATUS = "disabled";
-    @VisibleForTesting
-    static final String USER_ENABLED_STATUS = "user_enabled";
-    @VisibleForTesting
-    static final String USER_DISABLED_STATUS = "user_disabled";
-
-    @VisibleForTesting
-    static final String USERDEBUG_BUILD = "userdebug";
-    @VisibleForTesting
-    static final String ENG_BUILD = "eng";
-
-    public ConnectivityMonitorPreferenceController(Context context) {
-        super(context);
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_CONNECTIVITY_MONITOR_SWITCH;
-    }
-
-    @Override
-    public boolean isAvailable() {
-        final String buildType = SystemProperties.get(BUILD_TYPE);
-        return mContext.getResources().getBoolean(R.bool.config_show_connectivity_monitor)
-                && (TextUtils.equals(buildType, USERDEBUG_BUILD)
-                || TextUtils.equals(buildType, ENG_BUILD));
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        final boolean isEnabled = (Boolean) newValue;
-        SystemProperties.set(PROPERTY_CONNECTIVITY_MONITOR,
-                isEnabled ? USER_ENABLED_STATUS : USER_DISABLED_STATUS);
-        Toast.makeText(mContext, R.string.connectivity_monitor_toast,
-                Toast.LENGTH_LONG).show();
-        return true;
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        final boolean enabled = isConnectivityMonitorEnabled();
-        ((SwitchPreference) mPreference).setChecked(enabled);
-    }
-
-    @Override
-    protected void onDeveloperOptionsSwitchDisabled() {
-        super.onDeveloperOptionsSwitchDisabled();
-        SystemProperties.set(PROPERTY_CONNECTIVITY_MONITOR, USER_DISABLED_STATUS);
-        ((SwitchPreference) mPreference).setChecked(false);
-    }
-
-    private boolean isConnectivityMonitorEnabled() {
-        final String cmStatus = SystemProperties.get(PROPERTY_CONNECTIVITY_MONITOR,
-                DISABLED_STATUS);
-        return TextUtils.equals(ENABLED_STATUS, cmStatus) || TextUtils.equals(USER_ENABLED_STATUS,
-                cmStatus);
-    }
-}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index ecc78e6..0b5cfff 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -405,7 +405,6 @@
         controllers.add(new VerifyAppsOverUsbPreferenceController(context));
         controllers.add(new LogdSizePreferenceController(context));
         controllers.add(new LogPersistPreferenceController(context, fragment, lifecycle));
-        controllers.add(new ConnectivityMonitorPreferenceController(context));
         controllers.add(new CameraLaserSensorPreferenceController(context));
         controllers.add(new LogicalCameraDefaultPreferenceController(context));
         controllers.add(new WifiDisplayCertificationPreferenceController(context));
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceController.java
index f5d3a97..00b890d 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceController.java
@@ -18,36 +18,45 @@
 
 import android.content.Context;
 import android.os.PowerManager;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
 
+import com.android.settings.core.TogglePreferenceController;
 import com.android.settings.fuelgauge.BatterySaverReceiver;
-import com.android.settings.widget.TwoStateButtonPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settings.widget.TwoStateButtonPreference;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
 import com.android.settingslib.fuelgauge.BatterySaverUtils;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 /**
  * Controller to update the battery saver button
  */
 public class BatterySaverButtonPreferenceController extends
-        TwoStateButtonPreferenceController implements
+        TogglePreferenceController implements
         LifecycleObserver, OnStart, OnStop, BatterySaverReceiver.BatterySaverListener {
-    private static final String KEY = "battery_saver_button_container";
-    private BatterySaverReceiver mBatterySaverReceiver;
-    @VisibleForTesting
-    PowerManager mPowerManager;
 
-    public BatterySaverButtonPreferenceController(Context context, Lifecycle lifecycle) {
-        super(context, KEY);
+    private final BatterySaverReceiver mBatterySaverReceiver;
+    private final PowerManager mPowerManager;
+
+    private TwoStateButtonPreference mPreference;
+
+    public BatterySaverButtonPreferenceController(Context context, String key) {
+        super(context, key);
         mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mBatterySaverReceiver = new BatterySaverReceiver(context);
         mBatterySaverReceiver.setBatterySaverListener(this);
-        if (lifecycle != null) {
-            lifecycle.addObserver(this);
-        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public boolean isSliceable() {
+        return true;
     }
 
     @Override
@@ -61,29 +70,43 @@
     }
 
     @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = (TwoStateButtonPreference) screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public boolean isChecked() {
+        return mPowerManager.isPowerSaveMode();
+    }
+
+    @Override
+    public boolean setChecked(boolean stateOn) {
+        // This screen already shows a warning, so we don't need another warning.
+        return BatterySaverUtils.setPowerSaveMode(mContext, stateOn,
+                false /* needFirstTimeWarning */);
+    }
+
+    @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
-        setButtonVisibility(!mPowerManager.isPowerSaveMode());
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return AVAILABLE;
-    }
-
-    @Override
-    public void onButtonClicked(boolean stateOn) {
-        // This screen already shows a warning, so we don't need another warning.
-        BatterySaverUtils.setPowerSaveMode(mContext,  stateOn, /*needFirstTimeWarning*/ false);
+        if (mPreference != null) {
+            mPreference.setChecked(isChecked());
+        }
     }
 
     @Override
     public void onPowerSaveModeChanged() {
-        setButtonVisibility(!mPowerManager.isPowerSaveMode());
+        final boolean isChecked = isChecked();
+        if (mPreference != null && mPreference.isChecked() != isChecked) {
+            mPreference.setChecked(isChecked);
+        }
     }
 
     @Override
     public void onBatteryChanged(boolean pluggedIn) {
-        setButtonEnabled(!pluggedIn);
+        if (mPreference != null) {
+            mPreference.setButtonEnabled(!pluggedIn);
+        }
     }
 }
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
index aa16fc9..5288970 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
@@ -75,7 +75,6 @@
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         controllers.add(new AutoBatterySaverPreferenceController(context));
         controllers.add(new AutoBatterySeekBarPreferenceController(context, lifecycle));
-        controllers.add(new BatterySaverButtonPreferenceController(context, lifecycle));
         return controllers;
     }
 
diff --git a/src/com/android/settings/location/LocationSliceBuilder.java b/src/com/android/settings/location/LocationSliceBuilder.java
new file mode 100644
index 0000000..fe24cee
--- /dev/null
+++ b/src/com/android/settings/location/LocationSliceBuilder.java
@@ -0,0 +1,93 @@
+/*
+ * 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.location;
+
+import static android.provider.SettingsSlicesContract.KEY_LOCATION;
+
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+
+import android.annotation.ColorInt;
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+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 androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+/**
+ * Utility class to build an intent-based Location Slice.
+ */
+public class LocationSliceBuilder {
+
+    /**
+     * Backing Uri for the Location Slice.
+     */
+    public static final Uri LOCATION_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSlicesContract.AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath(KEY_LOCATION)
+            .build();
+
+    private LocationSliceBuilder() {
+    }
+
+    /**
+     * Return a Location Slice bound to {@link #LOCATION_URI}.
+     */
+    public static Slice getSlice(Context context) {
+        final IconCompat icon = IconCompat.createWithResource(context,
+                R.drawable.ic_signal_location);
+        final String title = context.getString(R.string.location_settings_title);
+        @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
+        final PendingIntent primaryAction = getPrimaryAction(context);
+        final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
+
+        return new ListBuilder(context, LOCATION_URI, ListBuilder.INFINITY)
+                .setAccentColor(color)
+                .addRow(b -> b
+                        .setTitle(title)
+                        .setTitleItem(icon, ICON_IMAGE)
+                        .setPrimaryAction(primarySliceAction))
+                .build();
+    }
+
+    private static PendingIntent getPrimaryAction(Context context) {
+        final String screenTitle = context.getText(R.string.location_settings_title).toString();
+        final Uri contentUri = new Uri.Builder().appendPath(KEY_LOCATION).build();
+        final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
+                LocationSettings.class.getName(), KEY_LOCATION, screenTitle,
+                MetricsEvent.LOCATION)
+                .setClassName(context.getPackageName(), SubSettings.class.getName())
+                .setData(contentUri);
+
+        return PendingIntent.getActivity(context, 0 /* requestCode */,
+                intent, 0 /* flags */);
+    }
+}
diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java
index b88ebeb..0eddd9e 100644
--- a/src/com/android/settings/network/AirplaneModePreferenceController.java
+++ b/src/com/android/settings/network/AirplaneModePreferenceController.java
@@ -15,14 +15,13 @@
  */
 package com.android.settings.network;
 
+import static android.provider.SettingsSlicesContract.KEY_AIRPLANE_MODE;
+
 import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.SystemProperties;
-import androidx.preference.SwitchPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.TelephonyIntents;
@@ -36,14 +35,16 @@
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
 
+import androidx.preference.SwitchPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 public class AirplaneModePreferenceController extends TogglePreferenceController
         implements LifecycleObserver, OnResume, OnPause,
         AirplaneModeEnabler.OnAirplaneModeChangedListener {
 
     public static final int REQUEST_CODE_EXIT_ECM = 1;
 
-    public static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane";
-
     private static final String EXIT_ECM_RESULT = "exit_ecm_result";
 
     private Fragment mFragment;
@@ -51,7 +52,6 @@
     private AirplaneModeEnabler mAirplaneModeEnabler;
     private SwitchPreference mAirplaneModePreference;
 
-
     public AirplaneModePreferenceController(Context context, String key) {
         super(context, key);
         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
@@ -64,7 +64,7 @@
 
     @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
-        if (KEY_TOGGLE_AIRPLANE.equals(preference.getKey()) && Boolean.parseBoolean(
+        if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && Boolean.parseBoolean(
                 SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
             // In ECM mode launch ECM app dialog
             if (mFragment != null) {
diff --git a/src/com/android/settings/network/VpnPreferenceController.java b/src/com/android/settings/network/VpnPreferenceController.java
index 5213a71..cb68d27 100644
--- a/src/com/android/settings/network/VpnPreferenceController.java
+++ b/src/com/android/settings/network/VpnPreferenceController.java
@@ -28,9 +28,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
+import android.provider.SettingsSlicesContract;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -47,6 +45,10 @@
 
 import java.util.List;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 
 public class VpnPreferenceController extends AbstractPreferenceController
         implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
@@ -83,7 +85,7 @@
         // Manually set dependencies for Wifi when not toggleable.
         if (mToggleable == null || !mToggleable.contains(Settings.Global.RADIO_WIFI)) {
             if (mPreference != null) {
-                mPreference.setDependency(AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE);
+                mPreference.setDependency(SettingsSlicesContract.KEY_AIRPLANE_MODE);
             }
         }
     }
diff --git a/src/com/android/settings/nfc/AndroidBeamEnabler.java b/src/com/android/settings/nfc/AndroidBeamEnabler.java
index 5041a3e..1808775 100644
--- a/src/com/android/settings/nfc/AndroidBeamEnabler.java
+++ b/src/com/android/settings/nfc/AndroidBeamEnabler.java
@@ -20,7 +20,6 @@
 import android.nfc.NfcAdapter;
 import android.os.UserHandle;
 import android.os.UserManager;
-import androidx.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settingslib.RestrictedLockUtils;
@@ -36,18 +35,14 @@
 
     public AndroidBeamEnabler(Context context, RestrictedPreference preference) {
         super(context);
-
         mPreference = preference;
-
         mBeamDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(context,
                 UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId());
-
         if (!isNfcAvailable()) {
             // NFC is not supported
             mPreference.setEnabled(false);
             return;
         }
-
         if (mBeamDisallowedBySystem) {
             mPreference.setEnabled(false);
         }
diff --git a/src/com/android/settings/nfc/AndroidBeamPreferenceController.java b/src/com/android/settings/nfc/AndroidBeamPreferenceController.java
index 739f00e..12ab1b7 100644
--- a/src/com/android/settings/nfc/AndroidBeamPreferenceController.java
+++ b/src/com/android/settings/nfc/AndroidBeamPreferenceController.java
@@ -16,34 +16,75 @@
 package com.android.settings.nfc;
 
 import android.content.Context;
+import android.nfc.NfcAdapter;
+import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
 
-public class AndroidBeamPreferenceController extends BaseNfcPreferenceController {
+import java.util.List;
+
+public class AndroidBeamPreferenceController extends BasePreferenceController
+        implements LifecycleObserver, OnResume, OnPause {
 
     public static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
+    private final NfcAdapter mNfcAdapter;
+    private AndroidBeamEnabler mAndroidBeamEnabler;
+    private NfcAirplaneModeObserver mAirplaneModeObserver;
 
-    public AndroidBeamPreferenceController(Context context) {
-        super(context);
+    public AndroidBeamPreferenceController(Context context, String key) {
+        super(context, key);
+        mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         if (!isAvailable()) {
+            mAndroidBeamEnabler = null;
             return;
         }
 
-        mNfcEnabler = new AndroidBeamEnabler(mContext, (RestrictedPreference) mPreference);
+        final RestrictedPreference restrictedPreference =
+                (RestrictedPreference) screen.findPreference(getPreferenceKey());
+        mAndroidBeamEnabler = new AndroidBeamEnabler(mContext, restrictedPreference);
+
+        // Manually set dependencies for NFC when not toggleable.
+        if (!NfcPreferenceController.isToggleableInAirplaneMode(mContext)) {
+            mAirplaneModeObserver = new NfcAirplaneModeObserver(mContext, mNfcAdapter,
+                    (Preference) restrictedPreference);
+        }
     }
 
     @Override
-    public String getPreferenceKey() {
-        return KEY_ANDROID_BEAM_SETTINGS;
+    @AvailabilityStatus
+    public int getAvailabilityStatus() {
+        return mNfcAdapter != null
+                ? AVAILABLE
+                : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public void onResume() {
+        if (mAirplaneModeObserver != null) {
+            mAirplaneModeObserver.register();
+        }
+        if (mAndroidBeamEnabler != null) {
+            mAndroidBeamEnabler.resume();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mAirplaneModeObserver != null) {
+            mAirplaneModeObserver.unregister();
+        }
+        if (mAndroidBeamEnabler != null) {
+            mAndroidBeamEnabler.pause();
+        }
     }
 }
diff --git a/src/com/android/settings/nfc/BaseNfcPreferenceController.java b/src/com/android/settings/nfc/BaseNfcPreferenceController.java
deleted file mode 100644
index e8e7dfd..0000000
--- a/src/com/android/settings/nfc/BaseNfcPreferenceController.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.nfc;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.nfc.NfcAdapter;
-import android.os.Handler;
-import android.provider.Settings;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-public abstract class BaseNfcPreferenceController extends AbstractPreferenceController
-        implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
-
-    protected BaseNfcEnabler mNfcEnabler;
-    private NfcAdapter mNfcAdapter;
-    private int mAirplaneMode;
-    private AirplaneModeObserver mAirplaneModeObserver;
-    protected Preference mPreference;
-
-    public BaseNfcPreferenceController(Context context) {
-        super(context);
-        mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-
-        if (!isAvailable()) {
-            mNfcEnabler = null;
-            return;
-        }
-
-        mPreference = screen.findPreference(getPreferenceKey());
-
-        // Manually set dependencies for NFC when not toggleable.
-        if (!isToggleableInAirplaneMode(mContext)) {
-            mAirplaneModeObserver = new AirplaneModeObserver();
-            updateNfcPreference();
-        }
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return mNfcAdapter != null;
-    }
-
-    public abstract String getPreferenceKey();
-
-    @Override
-    public void onResume() {
-        if (mAirplaneModeObserver != null) {
-            mAirplaneModeObserver.register();
-        }
-        if (mNfcEnabler != null) {
-            mNfcEnabler.resume();
-        }
-    }
-
-    @Override
-    public void onPause() {
-        if (mAirplaneModeObserver != null) {
-            mAirplaneModeObserver.unregister();
-        }
-        if (mNfcEnabler != null) {
-            mNfcEnabler.pause();
-        }
-    }
-
-    private void updateNfcPreference() {
-        final int airplaneMode = Settings.Global.getInt(
-                mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, mAirplaneMode);
-        if (airplaneMode == mAirplaneMode) {
-            return;
-        }
-        mAirplaneMode = airplaneMode;
-        boolean toggleable = mAirplaneMode != 1;
-        if (toggleable) {
-            mNfcAdapter.enable();
-        } else {
-            mNfcAdapter.disable();
-        }
-        mPreference.setEnabled(toggleable);
-    }
-
-    public static boolean isToggleableInAirplaneMode(Context context) {
-        String toggleable = Settings.Global.getString(context.getContentResolver(),
-                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
-        return toggleable != null && toggleable.contains(Settings.Global.RADIO_NFC);
-    }
-
-    private final class AirplaneModeObserver extends ContentObserver {
-        private final Uri AIRPLANE_MODE_URI =
-                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
-
-        private AirplaneModeObserver() {
-            super(new Handler());
-        }
-
-        public void register() {
-            mContext.getContentResolver().registerContentObserver(AIRPLANE_MODE_URI, false, this);
-        }
-
-        public void unregister() {
-            mContext.getContentResolver().unregisterContentObserver(this);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            super.onChange(selfChange, uri);
-            updateNfcPreference();
-        }
-    }
-
-}
diff --git a/src/com/android/settings/nfc/NfcAirplaneModeObserver.java b/src/com/android/settings/nfc/NfcAirplaneModeObserver.java
new file mode 100644
index 0000000..d0ce045
--- /dev/null
+++ b/src/com/android/settings/nfc/NfcAirplaneModeObserver.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.nfc;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.nfc.NfcAdapter;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+/**
+ * NfcAirplaneModeObserver is a helper to manage the Nfc on/off when airplane mode status
+ * is changed.
+ */
+public class NfcAirplaneModeObserver extends ContentObserver {
+
+    private final Context mContext;
+    private final NfcAdapter mNfcAdapter;
+    private final Preference mPreference;
+    private int mAirplaneMode;
+
+    @VisibleForTesting
+    final static Uri AIRPLANE_MODE_URI =
+            Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
+
+    public NfcAirplaneModeObserver(Context context, NfcAdapter nfcAdapter, Preference preference) {
+        super(new Handler(Looper.getMainLooper()));
+        mContext = context;
+        mNfcAdapter = nfcAdapter;
+        mPreference = preference;
+        updateNfcPreference();
+    }
+
+    public void register() {
+        mContext.getContentResolver().registerContentObserver(AIRPLANE_MODE_URI, false, this);
+    }
+
+    public void unregister() {
+        mContext.getContentResolver().unregisterContentObserver(this);
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        super.onChange(selfChange, uri);
+        updateNfcPreference();
+    }
+
+    private void updateNfcPreference() {
+        final int airplaneMode = Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, mAirplaneMode);
+        if (airplaneMode == mAirplaneMode) {
+            return;
+        }
+
+        mAirplaneMode = airplaneMode;
+        boolean toggleable = mAirplaneMode != 1;
+        if (toggleable) {
+            mNfcAdapter.enable();
+        } else {
+            mNfcAdapter.disable();
+        }
+        mPreference.setEnabled(toggleable);
+    }
+}
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 82011a0..507a053 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -18,52 +18,21 @@
 
 import android.content.Context;
 import android.nfc.NfcAdapter;
-import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
 
+
 /**
  * NfcEnabler is a helper to manage the Nfc on/off checkbox preference. It turns on/off Nfc
  * and ensures the summary of the preference reflects the current state.
  */
-public class NfcEnabler extends BaseNfcEnabler implements Preference.OnPreferenceChangeListener {
+public class NfcEnabler extends BaseNfcEnabler {
     private final SwitchPreference mPreference;
 
     public NfcEnabler(Context context, SwitchPreference preference) {
         super(context);
-
         mPreference = preference;
     }
 
-    public void resume() {
-        super.resume();
-        if (isNfcAvailable()) {
-            mPreference.setOnPreferenceChangeListener(this);
-        }
-    }
-
-    public void pause() {
-        super.pause();
-        if (isNfcAvailable()) {
-            mPreference.setOnPreferenceChangeListener(null);
-        }
-    }
-
-    public boolean onPreferenceChange(Preference preference, Object value) {
-        // Turn NFC on/off
-
-        final boolean desiredState = (Boolean) value;
-        mPreference.setChecked(desiredState);
-        mPreference.setEnabled(false);
-
-        if (desiredState) {
-            mNfcAdapter.enable();
-        } else {
-            mNfcAdapter.disable();
-        }
-
-        return false;
-    }
-
     @Override
     protected void handleNfcStateChanged(int newState) {
         switch (newState) {
diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java
index a00aa32..e1fa1b3 100644
--- a/src/com/android/settings/nfc/NfcPreferenceController.java
+++ b/src/com/android/settings/nfc/NfcPreferenceController.java
@@ -16,35 +16,118 @@
 package com.android.settings.nfc;
 
 import android.content.Context;
+import android.content.IntentFilter;
+import android.nfc.NfcAdapter;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 
-import com.android.settings.core.PreferenceControllerMixin;
+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 java.util.List;
 
-public class NfcPreferenceController extends BaseNfcPreferenceController {
+public class NfcPreferenceController extends TogglePreferenceController
+        implements LifecycleObserver, OnResume, OnPause {
 
     public static final String KEY_TOGGLE_NFC = "toggle_nfc";
+    private final NfcAdapter mNfcAdapter;
+    private NfcEnabler mNfcEnabler;
+    private NfcAirplaneModeObserver mAirplaneModeObserver;
 
-    public NfcPreferenceController(Context context) {
-        super(context);
+    public NfcPreferenceController(Context context, String key) {
+        super(context, key);
+        mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         if (!isAvailable()) {
+            mNfcEnabler = null;
             return;
         }
 
-        mNfcEnabler = new NfcEnabler(mContext, (SwitchPreference) mPreference);
+        final SwitchPreference switchPreference =
+                (SwitchPreference) screen.findPreference(getPreferenceKey());
+
+        mNfcEnabler = new NfcEnabler(mContext, switchPreference);
+
+        // Manually set dependencies for NFC when not toggleable.
+        if (!isToggleableInAirplaneMode(mContext)) {
+            mAirplaneModeObserver = new NfcAirplaneModeObserver(mContext,
+                    mNfcAdapter, (Preference) switchPreference);
+        }
     }
 
     @Override
-    public String getPreferenceKey() {
-        return KEY_TOGGLE_NFC;
+    public boolean isChecked() {
+        return mNfcAdapter.isEnabled();
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        if (isChecked) {
+            mNfcAdapter.enable();
+        } else {
+            mNfcAdapter.disable();
+        }
+        return true;
+    }
+
+    @Override
+    @AvailabilityStatus
+    public int getAvailabilityStatus() {
+        return mNfcAdapter != null
+                ? AVAILABLE
+                : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public IntentFilter getIntentFilter() {
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+        filter.addAction(NfcAdapter.EXTRA_ADAPTER_STATE);
+        return filter;
+    }
+
+    @Override
+    public boolean hasAsyncUpdate() {
+        return true;
+    }
+
+    @Override
+    public boolean isSliceable() {
+        return true;
+    }
+
+    @Override
+    public void onResume() {
+        if (mAirplaneModeObserver != null) {
+            mAirplaneModeObserver.register();
+        }
+        if (mNfcEnabler != null) {
+            mNfcEnabler.resume();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mAirplaneModeObserver != null) {
+            mAirplaneModeObserver.unregister();
+        }
+        if (mNfcEnabler != null) {
+            mNfcEnabler.pause();
+        }
+    }
+
+    public static boolean isToggleableInAirplaneMode(Context context) {
+        final String toggleable = Settings.Global.getString(context.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+        return toggleable != null && toggleable.contains(Settings.Global.RADIO_NFC);
     }
 }
diff --git a/src/com/android/settings/notification/ZenModeSliceBuilder.java b/src/com/android/settings/notification/ZenModeSliceBuilder.java
index 7e6c11e..a7388fe 100644
--- a/src/com/android/settings/notification/ZenModeSliceBuilder.java
+++ b/src/com/android/settings/notification/ZenModeSliceBuilder.java
@@ -18,6 +18,8 @@
 
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+
 import android.annotation.ColorInt;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 6a03ea0..e8e2e1d 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -31,6 +31,7 @@
 import android.util.Log;
 import android.util.Pair;
 
+import com.android.settings.location.LocationSliceBuilder;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.wifi.WifiSliceBuilder;
@@ -189,6 +190,8 @@
             return ZenModeSliceBuilder.getSlice(getContext());
         } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
             return BluetoothSliceBuilder.getSlice(getContext());
+        } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
+            return LocationSliceBuilder.getSlice(getContext());
         }
 
         SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
@@ -290,10 +293,17 @@
     void loadSlice(Uri uri) {
         long startBuildTime = System.currentTimeMillis();
 
-        final SliceData sliceData = mSlicesDatabaseAccessor.getSliceDataFromUri(uri);
+        final SliceData sliceData;
+        try {
+             sliceData = mSlicesDatabaseAccessor.getSliceDataFromUri(uri);
+        } catch (IllegalStateException e) {
+            Log.d(TAG, "Could not create slicedata for uri: " + uri);
+            return;
+        }
 
         final BasePreferenceController controller = SliceBuilderUtils.getPreferenceController(
-                getContext(), sliceData);
+                    getContext(), sliceData);
+
         final IntentFilter filter = controller.getIntentFilter();
         if (filter != null) {
             registerIntentToUri(filter, uri);
@@ -337,7 +347,8 @@
     private List<Uri> getSpecialCasePlatformUris() {
         return Arrays.asList(
                 WifiSliceBuilder.WIFI_URI,
-                BluetoothSliceBuilder.BLUETOOTH_URI
+                BluetoothSliceBuilder.BLUETOOTH_URI,
+                LocationSliceBuilder.LOCATION_URI
         );
     }
 
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 80e3e3c..213bf00 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -106,7 +106,9 @@
 
         if (!controller.isAvailable()) {
             Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
-            updateUri(context, key, isPlatformSlice);
+            if (!controller.hasAsyncUpdate()) {
+                updateUri(context, key, isPlatformSlice);
+            }
             return;
         }
 
@@ -115,7 +117,9 @@
         final TogglePreferenceController toggleController = (TogglePreferenceController) controller;
         toggleController.setChecked(isChecked);
         logSliceValueChange(context, key, isChecked ? 1 : 0);
-        updateUri(context, key, isPlatformSlice);
+        if (!controller.hasAsyncUpdate()) {
+            updateUri(context, key, isPlatformSlice);
+        }
     }
 
     private void handleSliderAction(Context context, String key, int newPosition,
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index 0913e2a..80c288f 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -86,8 +86,13 @@
         FeatureFactory.getFactory(context).getMetricsFeatureProvider()
                 .action(context, MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED, sliceNamePair);
 
-        if (controller.getAvailabilityStatus() != AVAILABLE) {
-            return buildUnavailableSlice(context, sliceData, controller);
+        if (!controller.isAvailable()) {
+            // Cannot guarantee setting page is accessible, let the presenter handle error case.
+            return null;
+        }
+
+        if (controller.getAvailabilityStatus() == DISABLED_DEPENDENT_SETTING) {
+            return buildUnavailableSlice(context, sliceData);
         }
 
         switch (sliceData.getSliceType()) {
@@ -177,14 +182,6 @@
     }
 
     /**
-     * @return {@link PendingIntent} to the Settings home page.
-     */
-    public static PendingIntent getSettingsIntent(Context context) {
-        final Intent intent = new Intent(Settings.ACTION_SETTINGS);
-        return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
-    }
-
-    /**
      * @return the summary text for a {@link Slice} built for {@param sliceData}.
      */
     public static CharSequence getSubtitleText(Context context,
@@ -283,18 +280,21 @@
         final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
         final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource());
         @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
+        final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
         final SliceAction primaryAction = new SliceAction(contentIntent, icon,
                 sliceData.getTitle());
         final List<String> keywords = buildSliceKeywords(sliceData);
 
         return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
                 .setAccentColor(color)
-                .addInputRange(builder -> builder
+                .setHeader(builder -> builder
                         .setTitle(sliceData.getTitle())
+                        .setSubtitle(subtitleText)
+                        .setPrimaryAction(primaryAction))
+                .addInputRange(builder -> builder
                         .setMax(sliderController.getMaxSteps())
                         .setValue(sliderController.getSliderPosition())
-                        .setInputAction(actionIntent)
-                        .setPrimaryAction(primaryAction))
+                        .setInputAction(actionIntent))
                 .setKeywords(keywords)
                 .build();
     }
@@ -355,40 +355,20 @@
         return keywords;
     }
 
-    private static Slice buildUnavailableSlice(Context context, SliceData data,
-            BasePreferenceController controller) {
+    private static Slice buildUnavailableSlice(Context context, SliceData data) {
         final String title = data.getTitle();
         final List<String> keywords = buildSliceKeywords(data);
         @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
-        final String summary;
-        final SliceAction primaryAction;
+        final CharSequence summary = context.getText(R.string.disabled_dependent_setting_summary);
         final IconCompat icon = IconCompat.createWithResource(context, data.getIconResource());
-
-        switch (controller.getAvailabilityStatus()) {
-            case UNSUPPORTED_ON_DEVICE:
-                summary = context.getString(R.string.unsupported_setting_summary);
-                primaryAction = new SliceAction(getSettingsIntent(context), icon, title);
-                break;
-            case DISABLED_FOR_USER:
-                summary = context.getString(R.string.disabled_for_user_setting_summary);
-                primaryAction = new SliceAction(getContentPendingIntent(context, data), icon,
-                        title);
-                break;
-            case DISABLED_DEPENDENT_SETTING:
-                summary = context.getString(R.string.disabled_dependent_setting_summary);
-                primaryAction = new SliceAction(getContentPendingIntent(context, data), icon,
-                        title);
-                break;
-            case CONDITIONALLY_UNAVAILABLE:
-            default:
-                summary = context.getString(R.string.unknown_unavailability_setting_summary);
-                primaryAction = new SliceAction(getSettingsIntent(context), icon, title);
-        }
+        final SliceAction primaryAction = new SliceAction(getContentPendingIntent(context, data),
+                icon, title);
 
         return new ListBuilder(context, data.getUri(), ListBuilder.INFINITY)
                 .setAccentColor(color)
                 .addRow(builder -> builder
                         .setTitle(title)
+                        .setTitleItem(icon)
                         .setSubtitle(summary)
                         .setPrimaryAction(primaryAction))
                 .setKeywords(keywords)
diff --git a/src/com/android/settings/widget/TwoStateButtonPreference.java b/src/com/android/settings/widget/TwoStateButtonPreference.java
index 35877a0..ae3e495 100644
--- a/src/com/android/settings/widget/TwoStateButtonPreference.java
+++ b/src/com/android/settings/widget/TwoStateButtonPreference.java
@@ -18,22 +18,34 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
-import androidx.core.content.res.TypedArrayUtils;
 import android.util.AttributeSet;
+import android.view.View;
 import android.widget.Button;
 
 import com.android.settings.R;
 import com.android.settings.applications.LayoutPreference;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.core.content.res.TypedArrayUtils;
+
 /**
  * Preference that presents a button with two states(On vs Off)
  */
-public class TwoStateButtonPreference extends LayoutPreference {
+public class TwoStateButtonPreference extends LayoutPreference implements
+        View.OnClickListener {
+
+    private boolean mIsChecked;
+    private final Button mButtonOn;
+    private final Button mButtonOff;
+
     public TwoStateButtonPreference(Context context, AttributeSet attrs) {
         super(context, attrs, TypedArrayUtils.getAttr(
                 context, R.attr.twoStateButtonPreferenceStyle, android.R.attr.preferenceStyle));
 
-        if (attrs != null) {
+        if (attrs == null) {
+            mButtonOn = null;
+            mButtonOff = null;
+        } else {
             final TypedArray styledAttrs = context.obtainStyledAttributes(attrs,
                     R.styleable.TwoStateButtonPreference);
             final int textOnId = styledAttrs.getResourceId(
@@ -44,19 +56,52 @@
                     R.string.summary_placeholder);
             styledAttrs.recycle();
 
-            final Button buttonOn = getStateOnButton();
-            buttonOn.setText(textOnId);
-            final Button buttonOff = getStateOffButton();
-            buttonOff.setText(textOffId);
+            mButtonOn = findViewById(R.id.state_on_button);
+            mButtonOn.setText(textOnId);
+            mButtonOn.setOnClickListener(this);
+            mButtonOff = findViewById(R.id.state_off_button);
+            mButtonOff.setText(textOffId);
+            mButtonOff.setOnClickListener(this);
+            setChecked(isChecked());
         }
     }
 
-    public Button getStateOnButton() {
-        return findViewById(R.id.state_on_button);
+    @Override
+    public void onClick(View v) {
+        final boolean stateOn = v.getId() == R.id.state_on_button;
+        setChecked(stateOn);
+        callChangeListener(stateOn);
     }
 
+    public void setChecked(boolean checked) {
+        // Update state
+        mIsChecked = checked;
+        // And update UI
+        if (checked) {
+            mButtonOn.setVisibility(View.GONE);
+            mButtonOff.setVisibility(View.VISIBLE);
+        } else {
+            mButtonOn.setVisibility(View.VISIBLE);
+            mButtonOff.setVisibility(View.GONE);
+        }
+    }
 
+    public boolean isChecked() {
+        return mIsChecked;
+    }
+
+    public void setButtonEnabled(boolean enabled) {
+        mButtonOn.setEnabled(enabled);
+        mButtonOff.setEnabled(enabled);
+    }
+
+    @VisibleForTesting
+    public Button getStateOnButton() {
+        return mButtonOn;
+    }
+
+    @VisibleForTesting
     public Button getStateOffButton() {
-        return findViewById(R.id.state_off_button);
+        return mButtonOff;
     }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/widget/TwoStateButtonPreferenceController.java b/src/com/android/settings/widget/TwoStateButtonPreferenceController.java
deleted file mode 100644
index 72bf45e..0000000
--- a/src/com/android/settings/widget/TwoStateButtonPreferenceController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.widget;
-
-import android.content.Context;
-import androidx.preference.PreferenceScreen;
-import android.view.View;
-import android.widget.Button;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-
-/**
- * Controller to update the button with two states(On vs Off).
- */
-public abstract class TwoStateButtonPreferenceController extends BasePreferenceController
-        implements View.OnClickListener {
-    private Button mButtonOn;
-    private Button mButtonOff;
-
-    public TwoStateButtonPreferenceController(Context context, String key) {
-        super(context, key);
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        final TwoStateButtonPreference preference =
-                (TwoStateButtonPreference) screen.findPreference(getPreferenceKey());
-        mButtonOn = preference.getStateOnButton();
-        mButtonOn.setOnClickListener(this);
-        mButtonOff = preference.getStateOffButton();
-        mButtonOff.setOnClickListener(this);
-    }
-
-    protected void setButtonVisibility(boolean stateOn) {
-        if (stateOn) {
-            mButtonOff.setVisibility(View.GONE);
-            mButtonOn.setVisibility(View.VISIBLE);
-        } else {
-            mButtonOff.setVisibility(View.VISIBLE);
-            mButtonOn.setVisibility(View.GONE);
-        }
-    }
-
-    protected void setButtonEnabled(boolean enabled) {
-        mButtonOn.setEnabled(enabled);
-        mButtonOff.setEnabled(enabled);
-    }
-
-    @Override
-    public void onClick(View v) {
-        final boolean stateOn = v.getId() == R.id.state_on_button;
-        onButtonClicked(stateOn);
-    }
-
-    /**
-     * Callback when button is clicked
-     *
-     * @param stateOn {@code true} if stateOn button is clicked, otherwise it means stateOff
-     *                button is clicked
-     */
-    public abstract void onButtonClicked(boolean stateOn);
-}
\ No newline at end of file
diff --git a/src/com/android/settings/wifi/WifiSliceBuilder.java b/src/com/android/settings/wifi/WifiSliceBuilder.java
index 312f01b..3b065d0 100644
--- a/src/com/android/settings/wifi/WifiSliceBuilder.java
+++ b/src/com/android/settings/wifi/WifiSliceBuilder.java
@@ -19,6 +19,8 @@
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 import static android.provider.SettingsSlicesContract.KEY_WIFI;
 
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+
 import android.annotation.ColorInt;
 import android.app.PendingIntent;
 import android.content.ContentResolver;
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
index 9847d4a..e8e33ef 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
@@ -25,13 +25,14 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.PersistableBundle;
-import androidx.core.graphics.drawable.IconCompat;
+import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
 import androidx.slice.builders.ListBuilder;
 import androidx.slice.builders.SliceAction;
@@ -121,7 +122,7 @@
             return getNonActionableWifiCallingSlice(
                     mContext.getString(R.string.wifi_calling_settings_title),
                     mContext.getString(R.string.wifi_calling_not_supported, carrierName),
-                    sliceUri, SliceBuilderUtils.getSettingsIntent(mContext));
+                    sliceUri, getSettingsIntent(mContext));
         }
 
         final ImsManager imsManager = getImsManager(subId);
@@ -132,7 +133,7 @@
             return getNonActionableWifiCallingSlice(
                     mContext.getString(R.string.wifi_calling_settings_title),
                     mContext.getString(R.string.wifi_calling_not_supported, carrierName),
-                    sliceUri, SliceBuilderUtils.getSettingsIntent(mContext));
+                    sliceUri, getSettingsIntent(mContext));
         }
 
         try {
@@ -338,6 +339,14 @@
         return intent;
     }
 
+    /**
+     * @return {@link PendingIntent} to the Settings home page.
+     */
+    public static PendingIntent getSettingsIntent(Context context) {
+        final Intent intent = new Intent(Settings.ACTION_SETTINGS);
+        return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
+    }
+
     private PendingIntent getBroadcastIntent(String action) {
         final Intent intent = new Intent(action);
         intent.setClass(mContext, SliceBroadcastReceiver.class);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
index ceea81e..ce55802 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
@@ -55,7 +55,8 @@
 
         mContext = spy(RuntimeEnvironment.application);
         mContentResolver = mContext.getContentResolver();
-        mNfcController = new NfcPreferenceController(mContext);
+        mNfcController = new NfcPreferenceController(mContext,
+                NfcPreferenceController.KEY_TOGGLE_NFC);
         mShadowNfcAdapter = shadowOf(ShadowNfcAdapter.getNfcAdapter(mContext));
     }
 
diff --git a/tests/robotests/src/com/android/settings/core/BasePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/core/BasePreferenceControllerTest.java
index d5e8e15..237e69a 100644
--- a/tests/robotests/src/com/android/settings/core/BasePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/core/BasePreferenceControllerTest.java
@@ -144,6 +144,11 @@
     }
 
     @Test
+    public void hasAsyncUpdate_shouldReturnFalse() {
+        assertThat(mPreferenceController.hasAsyncUpdate()).isFalse();
+    }
+
+    @Test
     public void settingAvailable_disabledOnDisplayPreference_preferenceEnabled() {
         final PreferenceScreen screen = mock(PreferenceScreen.class);
         final Preference preference = new Preference(mContext);
diff --git a/tests/robotests/src/com/android/settings/development/ConnectivityMonitorPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/ConnectivityMonitorPreferenceControllerTest.java
deleted file mode 100644
index f0e5825..0000000
--- a/tests/robotests/src/com/android/settings/development/ConnectivityMonitorPreferenceControllerTest.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development;
-
-import static com.android.settings.development.ConnectivityMonitorPreferenceController.ENG_BUILD;
-import static com.android.settings.development.ConnectivityMonitorPreferenceController.USERDEBUG_BUILD;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.SystemProperties;
-import androidx.preference.SwitchPreference;
-import androidx.preference.PreferenceScreen;
-
-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.annotation.Config;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class ConnectivityMonitorPreferenceControllerTest {
-
-    private static final String USER_BUILD = "user";
-
-    @Mock
-    private PreferenceScreen mScreen;
-    @Mock
-    private SwitchPreference mPreference;
-
-    private Context mContext;
-    private ConnectivityMonitorPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mController = new ConnectivityMonitorPreferenceController(mContext);
-        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        mController.displayPreference(mScreen);
-    }
-
-    @Test
-    public void isAvailable_trueShowFlagWithUserdebugBuild_shouldReturnTrue() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
-
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void isAvailable_trueShowFlagWithEngBuild_shouldReturnTrue() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, ENG_BUILD);
-
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void isAvailable_trueShowFlagWithUserBuild_shouldReturnFalse() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, USER_BUILD);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    @Config(qualifiers = "mcc999")
-    public void isAvailable_falseShowFlagWithUserdebugBuild_shouldReturnFalse() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    @Config(qualifiers = "mcc999")
-    public void isAvailable_falseShowFlagWithEngBuild_shouldReturnFalse() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, ENG_BUILD);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    @Config(qualifiers = "mcc999")
-    public void isAvailable_falseShowFlagWithUserBuild_shouldReturnFalse() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, USER_BUILD);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void updateState_connectivityMonitorEnabled_shouldCheckedPreference() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                ConnectivityMonitorPreferenceController.ENABLED_STATUS);
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
-
-        mController.updateState(mPreference);
-
-        verify(mPreference).setChecked(true);
-    }
-
-    @Test
-    public void updateState_connectivityMonitorUserEnabled_shouldCheckedPreference() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                ConnectivityMonitorPreferenceController.USER_ENABLED_STATUS);
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
-
-        mController.updateState(mPreference);
-
-        verify(mPreference).setChecked(true);
-    }
-
-    @Test
-    public void updateState_connectivityMonitorDisabled_shouldUncheckedPreference() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                ConnectivityMonitorPreferenceController.DISABLED_STATUS);
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
-
-        mController.updateState(mPreference);
-
-        verify(mPreference).setChecked(false);
-    }
-
-    @Test
-    public void updateState_connectivityMonitorUserDisabled_shouldUncheckedPreference() {
-        SystemProperties.set(ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                ConnectivityMonitorPreferenceController.USER_DISABLED_STATUS);
-        SystemProperties.set(ConnectivityMonitorPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
-
-        mController.updateState(mPreference);
-
-        verify(mPreference).setChecked(false);
-    }
-
-    @Test
-    public void onPreferenceChange_preferenceChecked_shouldEnableConnectivityMonitor() {
-        SystemProperties.set(
-                ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                ConnectivityMonitorPreferenceController.USER_ENABLED_STATUS);
-
-        mController.handlePreferenceTreeClick(mPreference);
-
-        assertThat(ConnectivityMonitorPreferenceController.USER_ENABLED_STATUS).isEqualTo(
-                SystemProperties.get(
-                        ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                        ConnectivityMonitorPreferenceController.DISABLED_STATUS));
-    }
-
-    @Test
-    public void onPreferenceChange_preferenceUnchecked_shouldDisableConnectivityMonitor() {
-        SystemProperties.set(
-                ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                ConnectivityMonitorPreferenceController.USER_DISABLED_STATUS);
-
-        mController.handlePreferenceTreeClick(mPreference);
-
-        assertThat(ConnectivityMonitorPreferenceController.USER_DISABLED_STATUS).isEqualTo(
-                SystemProperties.get(
-                        ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                        ConnectivityMonitorPreferenceController.DISABLED_STATUS));
-    }
-
-    @Test
-    public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
-        mController.onDeveloperOptionsSwitchDisabled();
-
-        String mode = SystemProperties.get(
-                ConnectivityMonitorPreferenceController.PROPERTY_CONNECTIVITY_MONITOR,
-                null /* default */);
-
-        assertThat(mode).isEqualTo(ConnectivityMonitorPreferenceController.USER_DISABLED_STATUS);
-        verify(mPreference).setEnabled(false);
-        verify(mPreference).setChecked(false);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
index fbe6cf8..a4e8a7e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
@@ -21,17 +21,12 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
-import androidx.lifecycle.LifecycleOwner;
 import android.content.Context;
 import android.os.PowerManager;
-import androidx.preference.PreferenceScreen;
-import android.view.View;
 import android.widget.Button;
 
-import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.widget.TwoStateButtonPreference;
-import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -41,6 +36,9 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowPowerManager;
+import org.robolectric.util.ReflectionHelpers;
+
+import androidx.preference.PreferenceScreen;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = ShadowPowerManager.class)
@@ -48,67 +46,58 @@
 
     private BatterySaverButtonPreferenceController mController;
     private Context mContext;
-    private Lifecycle mLifecycle;
-    private LifecycleOwner mLifecycleOwner;
     private Button mButtonOn;
     private Button mButtonOff;
     private PowerManager mPowerManager;
-    @Mock
     private TwoStateButtonPreference mPreference;
+
     @Mock
     private PreferenceScreen mPreferenceScreen;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
         mContext = spy(RuntimeEnvironment.application);
+        mButtonOn = new Button(mContext);
+        mButtonOff = new Button(mContext);
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mPreference = spy(new TwoStateButtonPreference(mContext, null /* AttributeSet */));
+        ReflectionHelpers.setField(mPreference, "mButtonOn", mButtonOn);
+        ReflectionHelpers.setField(mPreference, "mButtonOff", mButtonOff);
         doReturn(mPreference).when(mPreferenceScreen).findPreference(anyString());
 
-        mButtonOn = new Button(mContext);
-        mButtonOn.setId(R.id.state_on_button);
-        doReturn(mButtonOn).when(mPreference).getStateOnButton();
-        mButtonOff = new Button(mContext);
-        mButtonOff.setId(R.id.state_off_button);
-        doReturn(mButtonOff).when(mPreference).getStateOffButton();
-
-        mController = new BatterySaverButtonPreferenceController(mContext, mLifecycle);
+        mController = new BatterySaverButtonPreferenceController(mContext, "test_key");
         mController.displayPreference(mPreferenceScreen);
     }
 
     @Test
-    public void testUpdateState_lowPowerOn_displayButtonOff() {
+    public void updateState_lowPowerOn_preferenceIsChecked() {
         mPowerManager.setPowerSaveMode(true);
 
         mController.updateState(mPreference);
 
-        assertThat(mButtonOn.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mButtonOff.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mPreference.isChecked()).isTrue();
     }
 
     @Test
-    public void testUpdateState_lowPowerOff_displayButtonOn() {
+    public void testUpdateState_lowPowerOff_preferenceIsUnchecked() {
         mPowerManager.setPowerSaveMode(false);
 
         mController.updateState(mPreference);
 
-        assertThat(mButtonOn.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mButtonOff.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mPreference.isChecked()).isFalse();
     }
 
     @Test
-    public void testOnClick_clickButtonOn_setPowerSaveMode() {
-        mController.onClick(mButtonOn);
+    public void setChecked_on_setPowerSaveMode() {
+        mController.setChecked(true);
 
         assertThat(mPowerManager.isPowerSaveMode()).isTrue();
     }
 
     @Test
-    public void testOnClick_clickButtonOff_clearPowerSaveMode() {
-        mController.onClick(mButtonOff);
+    public void setChecked_off_unsetPowerSaveMode() {
+        mController.setChecked(false);
 
         assertThat(mPowerManager.isPowerSaveMode()).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java b/tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java
new file mode 100644
index 0000000..2f51470
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java
@@ -0,0 +1,65 @@
+package com.android.settings.location;
+
+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 android.content.res.Resources;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.SliceTester;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class LocationSliceBuilderTest {
+
+    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 getLocationSlice_correctSliceContent() {
+        final Slice LocationSlice = LocationSliceBuilder.getSlice(mContext);
+        final SliceMetadata metadata = SliceMetadata.from(mContext, LocationSlice);
+
+        final List<SliceAction> toggles = metadata.getToggles();
+        assertThat(toggles).isEmpty();
+
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+        final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_signal_location);
+        assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString());
+
+        final List<SliceItem> sliceItems = LocationSlice.getItems();
+        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.location_settings_title));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java
index 7613021..4eaffbb 100644
--- a/tests/robotests/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java
@@ -21,13 +21,11 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
-import androidx.lifecycle.LifecycleOwner;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.provider.Settings;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
+import android.provider.SettingsSlicesContract;
 
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -43,6 +41,10 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 public class AirplaneModePreferenceControllerTest {
 
@@ -69,12 +71,12 @@
         mResolver = RuntimeEnvironment.application.getContentResolver();
         doReturn(mPackageManager).when(mContext).getPackageManager();
         mController = new AirplaneModePreferenceController(mContext,
-                AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE);
+                SettingsSlicesContract.KEY_AIRPLANE_MODE);
 
         mPreferenceManager = new PreferenceManager(mContext);
         mScreen = mPreferenceManager.createPreferenceScreen(mContext);
         mPreference = new RestrictedSwitchPreference(mContext);
-        mPreference.setKey("toggle_airplane");
+        mPreference.setKey(SettingsSlicesContract.KEY_AIRPLANE_MODE);
         mScreen.addPreference(mPreference);
         mController.setFragment(null);
         mLifecycleOwner = () -> mLifecycle;
diff --git a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
index 850f46f..6d0dd28 100644
--- a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
@@ -33,13 +33,15 @@
 import android.net.NetworkRequest;
 import android.os.IBinder;
 import android.os.UserHandle;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
+import android.provider.SettingsSlicesContract;
 
 import com.android.internal.net.VpnConfig;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -88,7 +90,7 @@
         doReturn(true).when(mController).isAvailable();
         mController.displayPreference(mScreen);
 
-        verify(mPreference).setDependency(AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE);
+        verify(mPreference).setDependency(SettingsSlicesContract.KEY_AIRPLANE_MODE);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java
index 0fb041b..71f94fd 100644
--- a/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java
@@ -72,7 +72,8 @@
                 UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId())).thenReturn(false);
         when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter);
 
-        mAndroidBeamController = new AndroidBeamPreferenceController(mContext);
+        mAndroidBeamController = new AndroidBeamPreferenceController(mContext,
+                AndroidBeamPreferenceController.KEY_ANDROID_BEAM_SETTINGS);
         mAndroidBeamPreference = new RestrictedPreference(RuntimeEnvironment.application);
         when(mScreen.findPreference(mAndroidBeamController.getPreferenceKey())).thenReturn(
                 mAndroidBeamPreference);
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcAirplaneModeObserverTest.java b/tests/robotests/src/com/android/settings/nfc/NfcAirplaneModeObserverTest.java
new file mode 100644
index 0000000..5efa94a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/nfc/NfcAirplaneModeObserverTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.nfc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.nfc.NfcAdapter;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowNfcAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowNfcAdapter.class})
+public class NfcAirplaneModeObserverTest {
+
+    Context mContext;
+    private NfcAdapter mNfcAdapter;
+    private SwitchPreference mNfcPreference;
+    private NfcAirplaneModeObserver mNfcAirplaneModeObserver;
+
+    @Before
+    public void setUp() {
+        mContext = ShadowApplication.getInstance().getApplicationContext();
+        mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
+
+        mNfcPreference = new SwitchPreference(RuntimeEnvironment.application);
+
+        mNfcAirplaneModeObserver = new NfcAirplaneModeObserver(mContext, mNfcAdapter,
+                (Preference) mNfcPreference);
+    }
+
+    @Test
+    public void NfcAirplaneModeObserver_airplaneOn_shouldDisableNfc() {
+        ReflectionHelpers.setField(mNfcAirplaneModeObserver,
+                "mAirplaneMode", 0);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 1);
+
+        mNfcAirplaneModeObserver.onChange(false,
+                NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
+
+        assertThat(mNfcAdapter.isEnabled()).isFalse();
+        assertThat(mNfcPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void NfcAirplaneModeObserver_airplaneOff_shouldEnableNfc() {
+        ReflectionHelpers.setField(mNfcAirplaneModeObserver,
+                "mAirplaneMode", 1);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0);
+
+        mNfcAirplaneModeObserver.onChange(false,
+                NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
+
+        assertThat(mNfcAdapter.isEnabled()).isTrue();
+        assertThat(mNfcPreference.isEnabled()).isTrue();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
index 9ddcc69..eaf6425 100644
--- a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -26,6 +27,9 @@
 import android.os.UserManager;
 import android.provider.Settings;
 
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -39,9 +43,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 public class NfcPreferenceControllerTest {
 
@@ -69,8 +70,10 @@
         when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mManager);
         when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter);
 
-        mNfcController = new NfcPreferenceController(mContext);
+        mNfcController = new NfcPreferenceController(mContext,
+                NfcPreferenceController.KEY_TOGGLE_NFC);
         mNfcPreference = new SwitchPreference(RuntimeEnvironment.application);
+
         when(mScreen.findPreference(mNfcController.getPreferenceKey())).thenReturn(mNfcPreference);
 
         Settings.Global.putString(mContext.getContentResolver(),
@@ -84,15 +87,17 @@
     }
 
     @Test
-    public void isAvailable_hasNfc_shouldReturnTrue() {
+    public void getAvailabilityStatus_hasNfc_shouldReturnAvailable() {
         when(mNfcAdapter.isEnabled()).thenReturn(true);
-        assertThat(mNfcController.isAvailable()).isTrue();
+        assertThat(mNfcController.getAvailabilityStatus())
+                .isEqualTo(NfcPreferenceController.AVAILABLE);
     }
 
     @Test
-    public void isAvailable_noNfcAdapter_shouldReturnFalse() {
+    public void getAvailabilityStatus_noNfcAdapter_shouldReturnDisabledUnsupported() {
         ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null);
-        assertThat(mNfcController.isAvailable()).isFalse();
+        assertThat(mNfcController.getAvailabilityStatus())
+                .isEqualTo(NfcPreferenceController.UNSUPPORTED_ON_DEVICE);
     }
 
     @Test
@@ -158,4 +163,46 @@
 
         assertThat(keys).hasSize(1);
     }
+    @Test
+    public void setChecked_True_nfcShouldEnable() {
+        mNfcController.setChecked(true);
+        mNfcController.onResume();
+
+        verify(mNfcAdapter).enable();
+    }
+
+    @Test
+    public void setChecked_False_nfcShouldDisable() {
+        mNfcController.setChecked(false);
+        mNfcController.onResume();
+
+        verify(mNfcAdapter).disable();
+    }
+
+    @Test
+    public void hasAsyncUpdate_shouldReturnTrue() {
+        assertThat(mNfcController.hasAsyncUpdate()).isTrue();
+    }
+
+    @Test
+    public void isToggleableInAirplaneMode_containNfc_shouldReturnTrue() {
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
+                Settings.Global.RADIO_NFC);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 1);
+
+        assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isTrue();
+    }
+
+    @Test
+    public void isToggleableInAirplaneMode_withoutNfc_shouldReturnFalse() {
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
+                "null");
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 1);
+
+        assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isFalse();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 722f481..bb064d1 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -28,6 +28,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.slice.SliceManager;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.sqlite.SQLiteDatabase;
@@ -35,6 +36,7 @@
 import android.os.StrictMode;
 import android.provider.SettingsSlicesContract;
 
+import com.android.settings.location.LocationSliceBuilder;
 import com.android.settings.wifi.WifiSliceBuilder;
 import com.android.settings.bluetooth.BluetoothSliceBuilder;
 import com.android.settings.notification.ZenModeSliceBuilder;
@@ -81,7 +83,8 @@
 
     private static final List<Uri> SPECIAL_CASE_PLATFORM_URIS = Arrays.asList(
             WifiSliceBuilder.WIFI_URI,
-            BluetoothSliceBuilder.BLUETOOTH_URI
+            BluetoothSliceBuilder.BLUETOOTH_URI,
+            LocationSliceBuilder.LOCATION_URI
     );
 
     private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
@@ -401,6 +404,18 @@
         assertThat(wifiSlice.getUri()).isEqualTo(WifiSliceBuilder.WIFI_URI);
     }
 
+    @Test
+    public void onSlicePinned_noIntentRegistered_specialCaseUri_doesNotCrash() {
+        final Uri uri = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(SettingsSlicesContract.AUTHORITY)
+                .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+                .appendPath(SettingsSlicesContract.KEY_LOCATION)
+                .build();
+
+        mProvider.onSlicePinned(uri);
+    }
+
     private void insertSpecialCase(String key) {
         insertSpecialCase(key, true);
     }
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
index f03f88e..5f0bc96 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
@@ -126,6 +127,60 @@
     }
 
     @Test
+    public void toggleUpdate_synchronously_notifyChange_should_be_called() {
+        // Monitor the ContentResolver
+        final ContentResolver resolver = spy(mContext.getContentResolver());
+        doReturn(resolver).when(mContext).getContentResolver();
+
+        final String key = "key";
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+        insertSpecialCase(key);
+
+        FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
+        fakeToggleController.setChecked(true);
+        // Set the toggle setting update synchronously.
+        fakeToggleController.setAsyncUpdate(false);
+        Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
+        intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+        assertThat(fakeToggleController.isChecked()).isTrue();
+
+        // Toggle setting
+        mReceiver.onReceive(mContext, intent);
+
+        assertThat(fakeToggleController.isChecked()).isFalse();
+
+        final Uri expectedUri = SliceBuilderUtils.getUri(
+                SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
+        verify(resolver).notifyChange(eq(expectedUri), eq(null));
+    }
+
+    @Test
+    public void toggleUpdate_asynchronously_notifyChange_should_not_be_called() {
+        // Monitor the ContentResolver
+        final ContentResolver resolver = spy(mContext.getContentResolver());
+        doReturn(resolver).when(mContext).getContentResolver();
+
+        final String key = "key";
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+        insertSpecialCase(key);
+
+        FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
+        fakeToggleController.setChecked(true);
+        // Set the toggle setting update asynchronously.
+        fakeToggleController.setAsyncUpdate(true);
+        Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
+        intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+        assertThat(fakeToggleController.isChecked()).isTrue();
+
+        // Toggle setting
+        mReceiver.onReceive(mContext, intent);
+
+        verify(resolver, never()).notifyChange(null, null);
+    }
+
+    @Test
     public void onReceive_sliderChanged() {
         final String key = "key";
         final int position = FakeSliderController.MAX_STEPS - 1;
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 00e8fe1..96e475e 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -336,7 +336,7 @@
 
         final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
 
-        SliceTester.testSettingsUnavailableSlice(mContext, slice, data);
+        assertThat(slice).isNull();
     }
 
     @Test
@@ -349,7 +349,7 @@
 
         final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
 
-        SliceTester.testSettingsUnavailableSlice(mContext, slice, data);
+        assertThat(slice).isNull();
     }
 
     @Test
@@ -394,7 +394,7 @@
                 .isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
         assertThat(capturedLoggingPair.second)
                 .isEqualTo(data.getKey());
-        SliceTester.testSettingsUnavailableSlice(mContext, slice, data);
+        assertThat(slice).isNull();
     }
 
     @Test
@@ -408,16 +408,6 @@
         assertThat(intentData).isEqualTo(expectedUri);
     }
 
-    @Test
-    public void getSettingsIntent_createsIntentToSettings() {
-        final Intent intent = new Intent(Settings.ACTION_SETTINGS);
-        final PendingIntent expectedIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
-
-        final PendingIntent settingsIntent = SliceBuilderUtils.getSettingsIntent(mContext);
-
-        assertThat(expectedIntent).isEqualTo(settingsIntent);
-    }
-
     private SliceData getDummyData() {
         return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE);
     }
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java b/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
index 680a04d..8e408f0 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
@@ -36,6 +36,8 @@
     private final int ON = 1;
     private final int OFF = 0;
 
+    private boolean mIsAsyncUpdate = false;
+
     public FakeToggleController(Context context, String preferenceKey) {
         super(context, preferenceKey);
     }
@@ -67,4 +69,13 @@
     public boolean isSliceable() {
         return true;
     }
+
+    @Override
+    public boolean hasAsyncUpdate() {
+        return mIsAsyncUpdate;
+    }
+
+    public void setAsyncUpdate(boolean isAsyncUpdate) {
+        mIsAsyncUpdate = isAsyncUpdate;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index e92d2a0..a451acf 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -150,14 +150,17 @@
         final int color = colorItem.getInt();
         assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context));
 
-        final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+
+        final IconCompat expectedIcon = IconCompat.createWithResource(context,
                 sliceData.getIconResource());
+        assertThat(expectedIcon.toString()).isEqualTo(primaryAction.getIcon().toString());
 
         final long sliceTTL = metadata.getExpiry();
         assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
 
         // Check primary intent
-        final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
+        final PendingIntent primaryPendingIntent = primaryAction.getAction();
         assertThat(primaryPendingIntent).isEqualTo(
                 SliceBuilderUtils.getContentPendingIntent(context, sliceData));
 
@@ -191,20 +194,8 @@
         assertThat(toggles).isEmpty();
 
         final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
-        final int availabilityStatus = SliceBuilderUtils.getPreferenceController(context,
-                sliceData).getAvailabilityStatus();
-        switch (availabilityStatus) {
-            case UNSUPPORTED_ON_DEVICE:
-            case CONDITIONALLY_UNAVAILABLE:
-                assertThat(primaryPendingIntent).isEqualTo(
-                        SliceBuilderUtils.getSettingsIntent(context));
-                break;
-            case DISABLED_FOR_USER:
-            case DISABLED_DEPENDENT_SETTING:
-                assertThat(primaryPendingIntent).isEqualTo(
-                        SliceBuilderUtils.getContentPendingIntent(context, sliceData));
-                break;
-        }
+        assertThat(primaryPendingIntent).isEqualTo(SliceBuilderUtils.getContentPendingIntent(
+                context, sliceData));
 
         final List<SliceItem> sliceItems = slice.getItems();
         assertTitle(sliceItems, sliceData.getTitle());
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java
index e4421ee..07c8e54 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java
@@ -33,6 +33,7 @@
 @Implements(NfcAdapter.class)
 public class ShadowNfcAdapter {
     private static boolean sReaderModeEnabled;
+    private boolean mIsNfcEnabled = false;
 
     @Implementation
     public void enableReaderMode(Activity activity, NfcAdapter.ReaderCallback callback, int flags,
@@ -46,6 +47,23 @@
                 NfcAdapter.class, ClassParameter.from(Context.class, context));
     }
 
+    @Implementation
+    public boolean isEnabled() {
+        return mIsNfcEnabled;
+    }
+
+    @Implementation
+    public boolean enable() {
+        mIsNfcEnabled = true;
+        return true;
+    }
+
+    @Implementation
+    public boolean disable() {
+        mIsNfcEnabled = false;
+        return true;
+    }
+
     public static boolean isReaderModeEnabled() {
         return sReaderModeEnabled;
     }
diff --git a/tests/robotests/src/com/android/settings/widget/TwoStateButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/widget/TwoStateButtonPreferenceTest.java
similarity index 60%
rename from tests/robotests/src/com/android/settings/widget/TwoStateButtonPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/widget/TwoStateButtonPreferenceTest.java
index 5ede773..c88e7f8 100644
--- a/tests/robotests/src/com/android/settings/widget/TwoStateButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/widget/TwoStateButtonPreferenceTest.java
@@ -17,34 +17,27 @@
 package com.android.settings.widget;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import androidx.preference.PreferenceScreen;
 import android.view.View;
 import android.widget.Button;
 
+import com.android.settings.R;
 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.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-public class TwoStateButtonPreferenceControllerTest {
+public class TwoStateButtonPreferenceTest {
 
-    private static final String KEY = "pref_key";
-
-    @Mock
-    private PreferenceScreen mPreferenceScreen;
-    @Mock
     private TwoStateButtonPreference mPreference;
-    private TwoStateButtonPreferenceController mController;
     private Context mContext;
     private Button mButtonOn;
     private Button mButtonOff;
@@ -53,35 +46,34 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
-        doReturn(mPreference).when(mPreferenceScreen).findPreference(anyString());
+        mPreference = spy(new TwoStateButtonPreference(mContext, null /* AttributeSet */));
         mButtonOn = new Button(mContext);
-        doReturn(mButtonOn).when(mPreference).getStateOnButton();
+        mButtonOn.setId(R.id.state_on_button);
         mButtonOff = new Button(mContext);
-        doReturn(mButtonOff).when(mPreference).getStateOffButton();
-
-        mController = new TestButtonsPreferenceController(mContext, KEY);
-        mController.displayPreference(mPreferenceScreen);
+        mButtonOff.setId(R.id.state_off_button);
+        ReflectionHelpers.setField(mPreference, "mButtonOn", mButtonOn);
+        ReflectionHelpers.setField(mPreference, "mButtonOff", mButtonOff);
     }
 
     @Test
     public void testSetButtonVisibility_stateOn_onlyShowButtonOn() {
-        mController.setButtonVisibility(true /* stateOn */);
-
-        assertThat(mButtonOn.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mButtonOff.getVisibility()).isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void testSetButtonVisibility_stateOff_onlyShowButtonOff() {
-        mController.setButtonVisibility(false /* stateOn */);
+        mPreference.setChecked(true /* stateOn */);
 
         assertThat(mButtonOn.getVisibility()).isEqualTo(View.GONE);
         assertThat(mButtonOff.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
     @Test
+    public void testSetButtonVisibility_stateOff_onlyShowButtonOff() {
+        mPreference.setChecked(false /* stateOn */);
+
+        assertThat(mButtonOn.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mButtonOff.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
     public void testSetButtonEnabled_enabled_buttonEnabled() {
-        mController.setButtonEnabled(true /* enabled */);
+        mPreference.setButtonEnabled(true /* enabled */);
 
         assertThat(mButtonOn.isEnabled()).isTrue();
         assertThat(mButtonOff.isEnabled()).isTrue();
@@ -89,30 +81,18 @@
 
     @Test
     public void testSetButtonEnabled_disabled_buttonDisabled() {
-        mController.setButtonEnabled(false /* enabled */);
+        mPreference.setButtonEnabled(false /* enabled */);
 
         assertThat(mButtonOn.isEnabled()).isFalse();
         assertThat(mButtonOff.isEnabled()).isFalse();
     }
 
-    /**
-     * Controller to test methods in {@link TwoStateButtonPreferenceController}
-     */
-    public static class TestButtonsPreferenceController
-        extends TwoStateButtonPreferenceController {
+    @Test
+    public void onClick_shouldPropagateChangeToListener() {
+        mPreference.onClick(mButtonOn);
+        verify(mPreference).callChangeListener(true);
 
-        TestButtonsPreferenceController(Context context, String key) {
-            super(context, key);
-        }
-
-        @Override
-        public void onButtonClicked(boolean stateOn) {
-            //do nothing
-        }
-
-        @Override
-        public int getAvailabilityStatus() {
-            return AVAILABLE;
-        }
+        mPreference.onClick(mButtonOff);
+        verify(mPreference).callChangeListener(false);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSliceBuilderTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSliceBuilderTest.java
index a196bb8..b761806 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSliceBuilderTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSliceBuilderTest.java
@@ -26,7 +26,6 @@
 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;
 
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
index ac3ff3f..21f6daa 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -114,7 +114,7 @@
         final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI);
 
         testWifiCallingSettingsUnavailableSlice(slice, null,
-                SliceBuilderUtils.getSettingsIntent(mContext));
+                WifiCallingSliceHelper.getSettingsIntent(mContext));
     }
 
     @Test
@@ -125,7 +125,7 @@
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testWifiCallingSettingsUnavailableSlice(slice, null,
-                SliceBuilderUtils.getSettingsIntent(mContext));
+                WifiCallingSliceHelper.getSettingsIntent(mContext));
     }
 
     @Test