Merge "Update Slice APIs to current versions" into pi-dev
diff --git a/res/layout/hotspot_ap_band_selection_dialog.xml b/res/layout/hotspot_ap_band_selection_dialog.xml
new file mode 100644
index 0000000..e63426d
--- /dev/null
+++ b/res/layout/hotspot_ap_band_selection_dialog.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:padding="8dp"
+    android:paddingStart="@dimen/wifi_ap_band_checkbox_padding">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="8dp"
+        android:text="@string/wifi_ap_band_select_one"
+        android:textAppearance="?android:attr/textAppearanceSmall"/>
+
+    <CheckBox
+        android:id="@+id/box_2g"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="@dimen/wifi_ap_band_checkbox_padding"
+        android:layout_marginTop="@dimen/wifi_ap_band_checkbox_padding"
+        android:paddingStart="@dimen/wifi_ap_band_checkbox_padding"
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+    <CheckBox
+        android:id="@+id/box_5g"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="@dimen/wifi_ap_band_checkbox_padding"
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 78b64f2..6912bb4 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -269,7 +269,6 @@
    <!-- Wi-Fi AP band settings.  Either Auto, 2.4GHz or 5GHz. -->
    <!-- Note that adding/removing/moving the items will need wifi settings code change. -->
     <string-array name="wifi_ap_band_config_full">
-        <item>@string/wifi_ap_choose_auto</item>
         <item>@string/wifi_ap_choose_2G</item>
         <item>@string/wifi_ap_choose_5G</item>
     </string-array>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 6a052d2..f95de27 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -191,6 +191,7 @@
 
     <!-- WiFi Preferences -->
     <dimen name="wifi_divider_height">1px</dimen>
+    <dimen name="wifi_ap_band_checkbox_padding">16dp</dimen>
 
     <!-- Color picker -->
     <dimen name="color_swatch_size">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2b850e8..b3b068a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -664,6 +664,8 @@
     <string name="save">Save</string>
     <!-- Button label for generic done action [CHAR LIMIT=20] -->
     <string name="done">Done</string>
+    <!-- Button label for generic apply action [CHAR LIMIT=20] -->
+    <string name="apply">Apply</string>
 
     <!-- Title of the Settings activity shown within the application itself. -->
     <string name="settings_label">Settings</string>
@@ -9081,7 +9083,7 @@
     <!-- Data usage remaining string [CHAR LIMIT=13] -->
     <string name="data_used_formatted"><xliff:g name="value" example="500">^1</xliff:g> <xliff:g name="units" example="GB">^2</xliff:g> used</string>
 
-    <!-- Data usage over limit string [CHAR LIMIT=13] -->
+    <!-- Shows the amount of data the user has used over their data limit [CHAR LIMIT=13] -->
     <string name="data_overusage"><xliff:g name="bytes" example="2 GB">^1</xliff:g> over</string>
 
     <!-- Optional part of data usage showing the remaining amount [CHAR LIMIT=13] -->
diff --git a/res/xml/wifi_tether_settings.xml b/res/xml/wifi_tether_settings.xml
index bb9af88..f9d9596 100644
--- a/res/xml/wifi_tether_settings.xml
+++ b/res/xml/wifi_tether_settings.xml
@@ -35,8 +35,11 @@
         android:title="@string/wifi_hotspot_auto_off_title"
         android:summary="@string/wifi_hotspot_auto_off_summary"/>
 
-    <ListPreference
+    <com.android.settings.widget.HotspotApBandSelectionPreference
         android:key="wifi_tether_network_ap_band"
         android:title="@string/wifi_hotspot_ap_band_title"
-        android:summary="@string/summary_placeholder" />
+        android:dialogLayout="@layout/hotspot_ap_band_selection_dialog"
+        android:dialogTitle="@string/wifi_hotspot_ap_band_title"
+        android:negativeButtonText="@string/cancel"
+        android:positiveButtonText="@string/apply"/>
 </PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index b82e3be..c0bf16a 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -402,7 +402,6 @@
      */
     public static class ConfirmLimitFragment extends InstrumentedDialogFragment implements
             DialogInterface.OnClickListener {
-        private static final String EXTRA_MESSAGE = "message";
         @VisibleForTesting static final String EXTRA_LIMIT_BYTES = "limitBytes";
         public static final float FLOAT = 1.2f;
 
@@ -414,16 +413,13 @@
             if (policy == null) return;
 
             final Resources res = parent.getResources();
-            final CharSequence message;
             final long minLimitBytes = (long) (policy.warningBytes * FLOAT);
             final long limitBytes;
 
             // TODO: customize default limits based on network template
-            message = res.getString(R.string.data_usage_limit_dialog_mobile);
             limitBytes = Math.max(5 * GIB_IN_BYTES, minLimitBytes);
 
             final Bundle args = new Bundle();
-            args.putCharSequence(EXTRA_MESSAGE, message);
             args.putLong(EXTRA_LIMIT_BYTES, limitBytes);
 
             final ConfirmLimitFragment dialog = new ConfirmLimitFragment();
@@ -441,11 +437,9 @@
         public Dialog onCreateDialog(Bundle savedInstanceState) {
             final Context context = getActivity();
 
-            final CharSequence message = getArguments().getCharSequence(EXTRA_MESSAGE);
-
             return new AlertDialog.Builder(context)
                     .setTitle(R.string.data_usage_limit_dialog_title)
-                    .setMessage(message)
+                    .setMessage(R.string.data_usage_limit_dialog_mobile)
                     .setPositiveButton(android.R.string.ok, this)
                     .setNegativeButton(android.R.string.cancel, null)
                     .create();
diff --git a/src/com/android/settings/datausage/DataUsagePreference.java b/src/com/android/settings/datausage/DataUsagePreference.java
index 766a2a9..9d0b104 100644
--- a/src/com/android/settings/datausage/DataUsagePreference.java
+++ b/src/com/android/settings/datausage/DataUsagePreference.java
@@ -56,7 +56,7 @@
         DataUsageController.DataUsageInfo usageInfo = controller.getDataUsageInfo(mTemplate);
         if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_SETTINGS_V2)) {
             if (mTemplate.isMatchRuleMobile()) {
-                setTitle(getContext().getString(R.string.app_cellular_data_usage));
+                setTitle(R.string.app_cellular_data_usage);
             } else {
                 setTitle(mTitleRes);
                 setSummary(getContext().getString(R.string.data_usage_template,
@@ -83,7 +83,7 @@
                 .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
         if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_SETTINGS_V2)) {
             if (mTemplate.isMatchRuleMobile()) {
-                launcher.setTitle(getContext().getString(R.string.app_cellular_data_usage));
+                launcher.setTitle(R.string.app_cellular_data_usage);
             } else {
                 launcher.setTitle(mTitleRes);
             }
diff --git a/src/com/android/settings/widget/HotspotApBandSelectionPreference.java b/src/com/android/settings/widget/HotspotApBandSelectionPreference.java
new file mode 100644
index 0000000..4f127eb
--- /dev/null
+++ b/src/com/android/settings/widget/HotspotApBandSelectionPreference.java
@@ -0,0 +1,258 @@
+/*
+ * 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.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+import com.android.settingslib.CustomDialogPreference;
+
+import java.util.ArrayList;
+
+public class HotspotApBandSelectionPreference extends CustomDialogPreference implements
+        CompoundButton.OnCheckedChangeListener, DialogInterface.OnShowListener {
+    private static final int UNSET = Integer.MIN_VALUE;
+
+    @VisibleForTesting
+    static final String KEY_CHECKED_BANDS = "checked_bands";
+    @VisibleForTesting
+    static final String KEY_HOTSPOT_SUPER_STATE = "hotspot_super_state";
+
+    @VisibleForTesting
+    CheckBox mBox2G;
+    @VisibleForTesting
+    CheckBox mBox5G;
+    @VisibleForTesting
+    ArrayList<Integer> mRestoredBands;
+    @VisibleForTesting
+    boolean mShouldRestore;
+
+    private String[] mBandEntries;
+    private int mExistingConfigValue = UNSET;
+
+    public HotspotApBandSelectionPreference(Context context) {
+        super(context);
+    }
+
+    public HotspotApBandSelectionPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public HotspotApBandSelectionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public HotspotApBandSelectionPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        SavedState myState = (SavedState) state;
+
+        super.onRestoreInstanceState(myState.getSuperState());
+
+        mShouldRestore = myState.shouldRestore;
+        if (mShouldRestore) {
+            mRestoredBands = new ArrayList<>();
+            if (myState.enabled2G) {
+                mRestoredBands.add(WifiConfiguration.AP_BAND_2GHZ);
+            }
+            if (myState.enabled5G) {
+                mRestoredBands.add(WifiConfiguration.AP_BAND_5GHZ);
+            }
+        } else {
+            mRestoredBands = null;
+        }
+        updatePositiveButton();
+    }
+
+    @Override
+    protected void onBindDialogView(View view) {
+        super.onBindDialogView(view);
+        final Context context = getContext();
+
+        // Register so we can adjust the buttons if needed once the dialog is available.
+        setOnShowListener(this);
+
+        mBandEntries = context.getResources().getStringArray(R.array.wifi_ap_band_config_full);
+        // add a checkbox for every band entry.
+        addApBandViews((LinearLayout) view);
+        // try to update the button just in case we already missed the onShow call.
+        updatePositiveButton();
+        // clear any saved state so it doesn't leak across multiple rotations/dialog closings
+        mRestoredBands = null;
+        mShouldRestore = false;
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+
+        SavedState myState = new SavedState(superState);
+        myState.shouldRestore = getDialog() != null;
+        myState.enabled2G = mBox2G.isChecked();
+        myState.enabled5G = mBox5G.isChecked();
+        return myState;
+    }
+
+    @Override
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        if (!(buttonView instanceof CheckBox)) {
+            return;
+        }
+        updatePositiveButton();
+    }
+
+    @Override
+    protected void onClick(DialogInterface dialog, int which) {
+        // we only want to persist our enabled bands if apply is clicked
+        if (which == DialogInterface.BUTTON_POSITIVE) {
+            if (mBox2G.isChecked() || mBox5G.isChecked()) {
+                int wifiBand = getWifiBand();
+                mExistingConfigValue = wifiBand;
+                callChangeListener(wifiBand);
+            }
+        }
+    }
+
+    /**
+     * Used to set the band selection for the preference if one already exists
+     * @param band the band to set it to from {@link WifiConfiguration}
+     */
+    public void setExistingConfigValue(int band) {
+        mExistingConfigValue = band;
+    }
+
+    private void addApBandViews(LinearLayout view) {
+        mBox2G = view.findViewById(R.id.box_2g);
+        mBox2G.setText(mBandEntries[WifiConfiguration.AP_BAND_2GHZ]);
+        mBox2G.setChecked(restoreBandIfNeeded(WifiConfiguration.AP_BAND_2GHZ));
+        mBox2G.setOnCheckedChangeListener(this);
+
+        mBox5G = view.findViewById(R.id.box_5g);
+        mBox5G.setText(mBandEntries[WifiConfiguration.AP_BAND_5GHZ]);
+        mBox5G.setChecked(restoreBandIfNeeded(WifiConfiguration.AP_BAND_5GHZ));
+        mBox5G.setOnCheckedChangeListener(this);
+    }
+
+    private boolean restoreBandIfNeeded(int band) {
+        // Only use the provided config if we aren't restoring, restore if state available
+        return (isBandPreviouslySelected(band) && !mShouldRestore)
+                || (mShouldRestore && mRestoredBands.contains(band));
+    }
+
+    private void updatePositiveButton() {
+        AlertDialog dialog = (AlertDialog) getDialog();
+        Button button = dialog == null ? null : dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        if (button != null && mBox5G != null && mBox2G != null) {
+            button.setEnabled(mBox2G.isChecked() || mBox5G.isChecked());
+        }
+    }
+
+    @VisibleForTesting
+    int getWifiBand() {
+        final boolean checked_2g = mBox2G.isChecked();
+        final boolean checked_5g = mBox5G.isChecked();
+        if (checked_2g && checked_5g) {
+            return WifiConfiguration.AP_BAND_ANY;
+        } else if (checked_2g && !checked_5g) {
+            return WifiConfiguration.AP_BAND_2GHZ;
+        } else if (checked_5g && !checked_2g) {
+            return WifiConfiguration.AP_BAND_5GHZ;
+        } else {
+            throw new IllegalStateException("Wifi Config only supports selecting one or all bands");
+        }
+    }
+
+    private boolean isBandPreviouslySelected(int bandIndex) {
+        switch(mExistingConfigValue) {
+            case WifiConfiguration.AP_BAND_ANY:
+                return true;
+            case WifiConfiguration.AP_BAND_2GHZ:
+                return bandIndex == 0;
+            case WifiConfiguration.AP_BAND_5GHZ:
+                return bandIndex == 1;
+            case UNSET:
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public void onShow(DialogInterface dialog) {
+        updatePositiveButton();
+    }
+
+    private static class SavedState extends BaseSavedState {
+        boolean shouldRestore;
+        boolean enabled2G;
+        boolean enabled5G;
+
+        public SavedState(Parcelable source) {
+            super(source);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            shouldRestore =  in.readByte() == 1;
+            enabled2G = in.readByte() == 1;
+            enabled5G = in.readByte() == 1;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeByte((byte) (shouldRestore ? 1 : 0));
+            dest.writeByte((byte) (enabled2G ? 1: 0));
+            dest.writeByte((byte) (enabled5G ? 1 : 0));
+        }
+
+        @Override
+        public String toString() {
+            return "HotspotApBandSelectionPreference.SavedState{"
+                    + Integer.toHexString(System.identityHashCode(this))
+                    + " shouldRestore=" + shouldRestore
+                    + " enabled2G=" + enabled2G
+                    + " enabled5G=" + enabled5G + "}";
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR
+                = new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 4f1c832..7a7caf4 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -912,7 +912,7 @@
 
     private void launchNetworkDetailsFragment(ConnectedAccessPointPreference pref) {
         new SubSettingLauncher(getContext())
-                .setTitle(getContext().getString(R.string.pref_title_network_details))
+                .setTitle(R.string.pref_title_network_details)
                 .setDestination(WifiNetworkDetailsFragment.class.getName())
                 .setArguments(pref.getExtras())
                 .setSourceMetricsCategory(getMetricsCategory())
diff --git a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
index 4c47a0d..b107777 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
@@ -18,31 +18,34 @@
 
 import static android.net.wifi.WifiConfiguration.AP_BAND_2GHZ;
 import static android.net.wifi.WifiConfiguration.AP_BAND_5GHZ;
-import static android.net.wifi.WifiConfiguration.AP_BAND_ANY;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.icu.text.ListFormatter;
 import android.net.wifi.WifiConfiguration;
-import android.support.v7.preference.ListPreference;
 import android.support.v7.preference.Preference;
 import android.util.Log;
 
 import com.android.settings.R;
+import com.android.settings.widget.HotspotApBandSelectionPreference;
 
 public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferenceController {
 
     private static final String TAG = "WifiTetherApBandPref";
     private static final String PREF_KEY = "wifi_tether_network_ap_band";
-    private static final String[] BAND_VALUES =
-            {String.valueOf(AP_BAND_ANY), String.valueOf(AP_BAND_2GHZ),
-                    String.valueOf(AP_BAND_5GHZ)};
+    public static final String[] BAND_VALUES =
+            {String.valueOf(AP_BAND_2GHZ), String.valueOf(AP_BAND_5GHZ)};
 
     private final String[] mBandEntries;
+    private final String[] mBandSummaries;
     private int mBandIndex;
 
     public WifiTetherApBandPreferenceController(Context context,
             OnTetherConfigUpdateListener listener) {
         super(context, listener);
-        mBandEntries = mContext.getResources().getStringArray(R.array.wifi_ap_band_config_full);
+        Resources res = mContext.getResources();
+        mBandEntries = res.getStringArray(R.array.wifi_ap_band_config_full);
+        mBandSummaries = res.getStringArray(R.array.wifi_ap_band_summary_full);
     }
 
     @Override
@@ -60,18 +63,25 @@
             mBandIndex = config.apBand;
             Log.d(TAG, "5Ghz not supported, updating band index to " + mBandIndex);
         }
-        ListPreference preference = (ListPreference) mPreference;
+        HotspotApBandSelectionPreference preference =
+                (HotspotApBandSelectionPreference) mPreference;
+
         if (!is5GhzBandSupported()) {
             preference.setEnabled(false);
             preference.setSummary(R.string.wifi_ap_choose_2G);
         } else {
-            preference.setEntries(mBandEntries);
-            preference.setEntryValues(BAND_VALUES);
-            preference.setSummary(mBandEntries[mBandIndex + 1]);
-            preference.setValue(String.valueOf(mBandIndex));
+            preference.setExistingConfigValue(config.apBand);
+            preference.setSummary(getConfigSummary());
         }
     }
 
+    String getConfigSummary() {
+        if (mBandIndex == WifiConfiguration.AP_BAND_ANY) {
+            return ListFormatter.getInstance().format((Object[]) mBandSummaries);
+        }
+        return mBandSummaries[mBandIndex];
+    }
+
     @Override
     public String getPreferenceKey() {
         return PREF_KEY;
@@ -79,9 +89,9 @@
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        mBandIndex = Integer.parseInt((String) newValue);
+        mBandIndex = (Integer) newValue;
         Log.d(TAG, "Band preference changed, updating band index to " + mBandIndex);
-        preference.setSummary(mBandEntries[mBandIndex + 1]);
+        preference.setSummary(getConfigSummary());
         mListener.onTetherConfigUpdated();
         return true;
     }
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
index ab08fdb..bf203e6 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
@@ -36,15 +36,17 @@
 import com.android.settingslib.core.lifecycle.events.OnStop;
 
 public class WifiTetherSwitchBarController implements SwitchWidgetController.OnSwitchChangeListener,
-        LifecycleObserver, OnStart, OnStop {
+        LifecycleObserver, OnStart, OnStop, DataSaverBackend.Listener {
 
     private static final IntentFilter WIFI_INTENT_FILTER;
 
     private final Context mContext;
     private final SwitchWidgetController mSwitchBar;
     private final ConnectivityManager mConnectivityManager;
-    private final DataSaverBackend mDataSaverBackend;
     private final WifiManager mWifiManager;
+
+    @VisibleForTesting
+    final DataSaverBackend mDataSaverBackend;
     @VisibleForTesting
     final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
             new ConnectivityManager.OnStartTetheringCallback() {
@@ -75,12 +77,14 @@
 
     @Override
     public void onStart() {
+        mDataSaverBackend.addListener(this);
         mSwitchBar.startListening();
         mContext.registerReceiver(mReceiver, WIFI_INTENT_FILTER);
     }
 
     @Override
     public void onStop() {
+        mDataSaverBackend.remListener(this);
         mSwitchBar.stopListening();
         mContext.unregisterReceiver(mReceiver);
     }
@@ -157,4 +161,19 @@
             mSwitchBar.setEnabled(false);
         }
     }
+
+    @Override
+    public void onDataSaverChanged(boolean isDataSaving) {
+        updateWifiSwitch();
+    }
+
+    @Override
+    public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
+        // we don't care, since we just want to read the value
+    }
+
+    @Override
+    public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
+        // we don't care, since we just want to read the value
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java
new file mode 100644
index 0000000..6bfc968
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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 static com.android.settingslib.CustomDialogPreference.CustomPreferenceDialogFragment;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class HotspotApBandSelectionPreferenceTest {
+    private HotspotApBandSelectionPreference mPreference;
+    private Context mContext;
+    private Button mSaveButton;
+    private View mLayout;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mSaveButton = spy(new Button(mContext));
+
+        final CustomPreferenceDialogFragment fragment = mock(CustomPreferenceDialogFragment.class);
+        final AlertDialog dialog = mock(AlertDialog.class);
+        when(fragment.getDialog()).thenReturn(dialog);
+        when(dialog.getButton(anyInt())).thenReturn(mSaveButton);
+
+        mPreference = new HotspotApBandSelectionPreference(mContext);
+        ReflectionHelpers.setField(mPreference, "mFragment", fragment);
+
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        mLayout = inflater.inflate(R.layout.hotspot_ap_band_selection_dialog,
+                new LinearLayout(mContext), false);
+    }
+
+    @Test
+    public void getWifiBand_updatesBandPresetConfigProvided() {
+        mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
+        mPreference.onBindDialogView(mLayout);
+
+        // check that the boxes are set correctly when a pre-existing config is set
+        assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_ANY);
+    }
+
+    @Test
+    public void getWifiBand_updatesBandWhenBoxesToggled() {
+        mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
+        mPreference.onBindDialogView(mLayout);
+
+        assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_ANY);
+
+        // make sure we have the expected box then toggle it
+        mPreference.mBox2G.setChecked(false);
+
+        // check that band is updated
+        assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_5GHZ);
+    }
+
+    @Test
+    public void onSaveInstanceState_skipWhenDialogGone() {
+        mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ);
+        mPreference.onBindDialogView(mLayout);
+        // remove the fragment to make the dialog unavailable
+        ReflectionHelpers.setField(mPreference, "mFragment", null);
+
+        mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
+        mPreference.onBindDialogView(mLayout);
+
+        // state should only be saved when the dialog is available
+        Parcelable parcelable = mPreference.onSaveInstanceState();
+        mPreference.onRestoreInstanceState(parcelable);
+        assertThat(mPreference.mShouldRestore).isFalse();
+    }
+
+    @Test
+    public void onSaveInstanceState_presentWhenDialogPresent() {
+        mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ);
+        mPreference.onBindDialogView(mLayout);
+
+        Parcelable parcelable = mPreference.onSaveInstanceState();
+        mPreference.onRestoreInstanceState(parcelable);
+        assertThat(mPreference.mShouldRestore).isTrue();
+    }
+
+    @Test
+    public void positiveButton_updatedCorrectly() {
+        mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
+        mPreference.onBindDialogView(mLayout);
+
+        // button is enabled whole time so far since we have a pre-existing selection
+        verify(mSaveButton, never()).setEnabled(false);
+
+        // clear all boxes and make sure it stays enabled until empty
+        mPreference.mBox2G.setChecked(false);
+        mPreference.mBox5G.setChecked(false);
+
+        // button should be disabled now
+        verify(mSaveButton, times(1)).setEnabled(false);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
index 3f364f9..d9c867c 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
@@ -24,12 +24,13 @@
 
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
-import android.support.v7.preference.ListPreference;
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.widget.HotspotApBandSelectionPreference;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -42,6 +43,7 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 public class WifiTetherApBandPreferenceControllerTest {
 
+    private static final String ALL_BANDS = "2.4 GHz and 5.0 GHz";
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
     @Mock
@@ -54,18 +56,21 @@
     private PreferenceScreen mScreen;
 
     private WifiTetherApBandPreferenceController mController;
-    private ListPreference mListPreference;
+    private HotspotApBandSelectionPreference mPreference;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mListPreference = new ListPreference(RuntimeEnvironment.application);
+        mPreference = new HotspotApBandSelectionPreference(RuntimeEnvironment.application);
         when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(mConnectivityManager);
         when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
         when(mContext.getResources()).thenReturn(RuntimeEnvironment.application.getResources());
-        when(mScreen.findPreference(anyString())).thenReturn(mListPreference);
+        when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+        WifiConfiguration config = new WifiConfiguration();
+        config.apBand = WifiConfiguration.AP_BAND_ANY;
+        when(mWifiManager.getWifiApConfiguration()).thenReturn(new WifiConfiguration());
 
         mController = new WifiTetherApBandPreferenceController(mContext, mListener);
     }
@@ -76,8 +81,9 @@
         when(mWifiManager.isDualBandSupported()).thenReturn(true);
 
         mController.displayPreference(mScreen);
+        mController.onPreferenceChange(mPreference, -1);
 
-        assertThat(mListPreference.getEntries().length).isEqualTo(3);
+        assertThat(mPreference.getSummary()).isEqualTo(ALL_BANDS);
     }
 
     @Test
@@ -87,9 +93,8 @@
 
         mController.displayPreference(mScreen);
 
-        assertThat(mListPreference.getEntries()).isNull();
-        assertThat(mListPreference.isEnabled()).isFalse();
-        assertThat(mListPreference.getSummary())
+        assertThat(mPreference.isEnabled()).isFalse();
+        assertThat(mPreference.getSummary())
                 .isEqualTo(RuntimeEnvironment.application.getString(R.string.wifi_ap_choose_2G));
     }
 
@@ -99,9 +104,8 @@
 
         mController.displayPreference(mScreen);
 
-        assertThat(mListPreference.getEntries()).isNull();
-        assertThat(mListPreference.isEnabled()).isFalse();
-        assertThat(mListPreference.getSummary())
+        assertThat(mPreference.isEnabled()).isFalse();
+        assertThat(mPreference.getSummary())
                 .isEqualTo(RuntimeEnvironment.application.getString(R.string.wifi_ap_choose_2G));
     }
 
@@ -112,14 +116,17 @@
         mController.displayPreference(mScreen);
 
         // -1 is WifiConfiguration.AP_BAND_ANY, for 'Auto' option.
-        mController.onPreferenceChange(mListPreference, "-1");
+        mController.onPreferenceChange(mPreference, -1);
         assertThat(mController.getBandIndex()).isEqualTo(-1);
+        assertThat(mPreference.getSummary()).isEqualTo(ALL_BANDS);
 
-        mController.onPreferenceChange(mListPreference, "1");
+        mController.onPreferenceChange(mPreference, 1);
         assertThat(mController.getBandIndex()).isEqualTo(1);
+        assertThat(mPreference.getSummary()).isEqualTo("5.0 GHz");
 
-        mController.onPreferenceChange(mListPreference, "0");
+        mController.onPreferenceChange(mPreference, 0);
         assertThat(mController.getBandIndex()).isEqualTo(0);
+        assertThat(mPreference.getSummary()).isEqualTo("2.4 GHz");
 
         verify(mListener, times(3)).onTetherConfigUpdated();
     }
@@ -129,7 +136,7 @@
         // Set controller band index to 1 and verify is set.
         when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
         mController.displayPreference(mScreen);
-        mController.onPreferenceChange(mListPreference, "1");
+        mController.onPreferenceChange(mPreference, 1);
         assertThat(mController.getBandIndex()).isEqualTo(1);
 
         // Disable 5Ghz band
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
index db8baab..943a665 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
@@ -88,4 +88,20 @@
         assertThat(mSwitchBar.isChecked()).isFalse();
         assertThat(mSwitchBar.isEnabled()).isTrue();
     }
+
+    @Test
+    public void testOnDataSaverChanged_setsEnabledCorrectly() {
+        assertThat(mSwitchBar.isEnabled()).isTrue();
+
+        // try to turn data saver on
+        when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(true);
+        mController.onDataSaverChanged(true);
+        assertThat(mSwitchBar.isEnabled()).isFalse();
+
+        // lets turn data saver off again
+        when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
+        mController.onDataSaverChanged(false);
+        assertThat(mSwitchBar.isEnabled()).isTrue();
+
+    }
 }