Merge "Move "metered" persistence to WifiConfiguration."
diff --git a/res/layout/data_plans_sync_time_preference.xml b/res/layout/data_plans_sync_time_preference.xml
new file mode 100644
index 0000000..bb9da90
--- /dev/null
+++ b/res/layout/data_plans_sync_time_preference.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<!-- Shows the data plans sync time -->
+<TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@android:id/title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="@dimen/preference_no_icon_padding_start"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:gravity="end"
+        android:textColor="?android:attr/textColorSecondary"/>
diff --git a/res/layout/data_usage_bytes_editor.xml b/res/layout/data_usage_bytes_editor.xml
index 2878c3e..af2d59b 100644
--- a/res/layout/data_usage_bytes_editor.xml
+++ b/res/layout/data_usage_bytes_editor.xml
@@ -37,7 +37,6 @@
         android:id="@+id/size_spinner"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        android:entries="@array/bytes_picker_sizes" />
+        android:layout_gravity="center_vertical" />
 
 </LinearLayout>
diff --git a/res/layout/manage_data_plans_preference.xml b/res/layout/manage_data_plans_preference.xml
new file mode 100644
index 0000000..1686d3f
--- /dev/null
+++ b/res/layout/manage_data_plans_preference.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<FrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="@dimen/preference_no_icon_padding_start"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:paddingTop="8dp"
+        android:paddingBottom="16dp">
+    <Button
+            android:id="@+id/manage_data_plans"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/data_plan_usage_manage_plans_button_text"
+            android:textAllCaps="true"
+            style="@style/AppActionPrimaryButton" />
+</FrameLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ad3edc1..96560a0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5526,6 +5526,9 @@
     <!--  action to select all [CHAR LIMIT=30] -->
     <string name="select_all">Select all</string>
 
+    <!-- A button that gets displayed in data plan usage preference in settings page to manage data plans [CHAR LIMIT=25] -->
+    <string name="data_plan_usage_manage_plans_button_text">Manage plans</string>
+
     <!-- Activity title for network data usage summary. [CHAR LIMIT=25] -->
     <string name="data_usage_summary_title">Data usage</string>
     <!-- Activity title for Appk data usage summary. [CHAR LIMIT=25] -->
@@ -8335,11 +8338,6 @@
     <!-- Text for the setting on whether you can type text into notifications without unlocking the device. -->
     <string name="lockscreen_remote_input">If device is locked, prevent typing replies or other text in notifications</string>
 
-    <string-array name="bytes_picker_sizes" translatable="false">
-        <item>@*android:string/megabyteShort</item>
-        <item>@*android:string/gigabyteShort</item>
-    </string-array>
-
     <!-- [CHAR LIMIT=30] Label for setting to control the default spell checker -->
     <string name="default_spell_checker">Default spell checker</string>
 
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index dc4c995..fe0111b 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -247,9 +247,8 @@
     /**
      * Whether to show the checkbox to wipe the eUICC.
      *
-     * <p>We show the checkbox on any device which supports eUICC as long as either the eUICC was
-     * ever provisioned (that is, at least one profile was ever downloaded onto it), or if the user
-     * has enabled development mode.
+     * <p>We show the checkbox on any device which supports eUICC as long as the eUICC was ever
+     * provisioned (that is, at least one profile was ever downloaded onto it).
      */
     @VisibleForTesting
     boolean showWipeEuicc() {
@@ -258,8 +257,7 @@
             return false;
         }
         ContentResolver cr = context.getContentResolver();
-        return Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) != 0
-                || Settings.Global.getInt(cr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
+        return Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) != 0;
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java b/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java
index 6f9cf40..b64da26 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java
@@ -21,6 +21,9 @@
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -30,11 +33,13 @@
     public static final String PREF_KEY = "bt_rename_device";
 
     private final Fragment mFragment;
+    private MetricsFeatureProvider mMetricsFeatureProvider;
 
     public BluetoothDeviceRenamePreferenceController(Context context, Fragment fragment,
             Lifecycle lifecycle) {
         super(context, lifecycle);
         mFragment = fragment;
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     }
 
     @VisibleForTesting
@@ -42,6 +47,7 @@
             LocalBluetoothAdapter localAdapter) {
         super(context, localAdapter);
         mFragment = fragment;
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     }
 
     @Override
@@ -57,6 +63,8 @@
     @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
         if (PREF_KEY.equals(preference.getKey())) {
+            mMetricsFeatureProvider.action(mContext,
+                    MetricsProto.MetricsEvent.ACTION_BLUETOOTH_RENAME);
             LocalDeviceNameDialogFragment.newInstance()
                     .show(mFragment.getFragmentManager(), LocalDeviceNameDialogFragment.TAG);
             return true;
diff --git a/src/com/android/settings/bluetooth/BluetoothEnabler.java b/src/com/android/settings/bluetooth/BluetoothEnabler.java
index 6c41f83..3d7c5b6 100644
--- a/src/com/android/settings/bluetooth/BluetoothEnabler.java
+++ b/src/com/android/settings/bluetooth/BluetoothEnabler.java
@@ -106,7 +106,7 @@
             mContext = context;
         }
 
-        maybeEnforceRestrictions();
+        final boolean restricted = maybeEnforceRestrictions();
 
         if (mLocalAdapter == null) {
             mSwitchWidget.setEnabled(false);
@@ -114,7 +114,9 @@
         }
 
         // Bluetooth state is not sticky, so set it manually
-        handleStateChanged(mLocalAdapter.getBluetoothState());
+        if (!restricted) {
+            handleStateChanged(mLocalAdapter.getBluetoothState());
+        }
 
         mSwitchWidget.startListening();
         mContext.registerReceiver(mReceiver, mIntentFilter);
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index 1025ad7..ea0bcf0 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -21,6 +21,8 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
+import android.icu.text.MeasureFormat;
+import android.icu.util.MeasureUnit;
 import android.net.NetworkPolicy;
 import android.net.NetworkTemplate;
 import android.os.Bundle;
@@ -31,6 +33,7 @@
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.widget.ArrayAdapter;
 import android.widget.EditText;
 import android.widget.NumberPicker;
 import android.widget.Spinner;
@@ -248,6 +251,17 @@
                     : editor.getPolicyWarningBytes(template);
             final long limitDisabled = isLimit ? LIMIT_DISABLED : WARNING_DISABLED;
 
+            final MeasureFormat formatter = MeasureFormat.getInstance(
+                    getContext().getResources().getConfiguration().locale,
+                    MeasureFormat.FormatWidth.SHORT);
+            final String[] unitNames = new String[] {
+                formatter.getUnitDisplayName(MeasureUnit.MEGABYTE),
+                formatter.getUnitDisplayName(MeasureUnit.GIGABYTE)
+            };
+            final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
+                    getContext(), android.R.layout.simple_spinner_item, unitNames);
+            type.setAdapter(adapter);
+
             if (bytes > 1.5f * GB_IN_BYTES) {
                 final String bytesText = formatText(bytes / (float) GB_IN_BYTES);
                 bytesPicker.setText(bytesText);
diff --git a/src/com/android/settings/deviceinfo/StorageItemPreference.java b/src/com/android/settings/deviceinfo/StorageItemPreference.java
index 3dcf935..d0114e3 100644
--- a/src/com/android/settings/deviceinfo/StorageItemPreference.java
+++ b/src/com/android/settings/deviceinfo/StorageItemPreference.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.icu.util.MeasureUnit;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
@@ -51,7 +52,7 @@
                 FileSizeFormatter.formatFileSize(
                         getContext(),
                         size,
-                        getGigabyteSuffix(getContext().getResources()),
+                        MeasureUnit.GIGABYTE,
                         FileSizeFormatter.GIGABYTE_IN_BYTES));
         if (total == 0) {
             mProgressPercent = 0;
@@ -75,8 +76,4 @@
         updateProgressBar();
         super.onBindViewHolder(view);
     }
-
-    private static int getGigabyteSuffix(Resources res) {
-        return res.getIdentifier("gigabyteShort", "string", "android");
-    }
 }
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 0d9c78f..6087503 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -304,11 +304,8 @@
 
             try {
                 ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
-                LoadIconTask task = new LoadIconTask(this);
-                task.execute(info);
                 setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
             } catch (PackageManager.NameNotFoundException e) {
-                setIcon(R.drawable.ic_label);
                 appExists = false;
                 return;
             }
@@ -345,29 +342,6 @@
         };
     }
 
-    private class LoadIconTask extends AsyncTask<ApplicationInfo, Void, Drawable> {
-        private final WeakReference<Preference> prefReference;
-
-        public LoadIconTask(Preference pref) {
-            prefReference = new WeakReference<>(pref);
-        }
-
-        @Override
-        protected Drawable doInBackground(ApplicationInfo... params) {
-            return params[0].loadIcon(mPm);
-        }
-
-        @Override
-        protected void onPostExecute(Drawable icon) {
-            if (icon != null) {
-                final Preference pref = prefReference.get();
-                if (pref != null) {
-                    pref.setIcon(icon);
-                }
-            }
-        }
-    }
-
     public static class SummaryBuilder {
 
         private Context mContext;
diff --git a/src/com/android/settings/utils/FileSizeFormatter.java b/src/com/android/settings/utils/FileSizeFormatter.java
index e56388a..c0d360f 100644
--- a/src/com/android/settings/utils/FileSizeFormatter.java
+++ b/src/com/android/settings/utils/FileSizeFormatter.java
@@ -16,11 +16,22 @@
 
 package com.android.settings.utils;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
+import android.icu.text.DecimalFormat;
+import android.icu.text.MeasureFormat;
+import android.icu.text.NumberFormat;
+import android.icu.util.Measure;
+import android.icu.util.MeasureUnit;
 import android.text.BidiFormatter;
+import android.text.TextUtils;
 import android.text.format.Formatter;
+import android.view.View;
+
+import java.math.BigDecimal;
+import java.util.Locale;
 
 /**
  * Utility class to aid in formatting file sizes always with the same unit. This is modified from
@@ -31,6 +42,61 @@
     public static final long MEGABYTE_IN_BYTES = KILOBYTE_IN_BYTES * 1000;
     public static final long GIGABYTE_IN_BYTES = MEGABYTE_IN_BYTES * 1000;
 
+    private static class RoundedBytesResult {
+        public final float value;
+        public final MeasureUnit units;
+        public final int fractionDigits;
+        public final long roundedBytes;
+
+        public RoundedBytesResult(
+                float value, MeasureUnit units, int fractionDigits, long roundedBytes) {
+            this.value = value;
+            this.units = units;
+            this.fractionDigits = fractionDigits;
+            this.roundedBytes = roundedBytes;
+        }
+    }
+
+    private static Locale localeFromContext(@NonNull Context context) {
+        return context.getResources().getConfiguration().locale;
+    }
+
+    private static String bidiWrap(@NonNull Context context, String source) {
+        final Locale locale = localeFromContext(context);
+        if (TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL) {
+            return BidiFormatter.getInstance(true /* RTL*/).unicodeWrap(source);
+        } else {
+            return source;
+        }
+    }
+
+    private static NumberFormat getNumberFormatter(Locale locale, int fractionDigits) {
+        final NumberFormat numberFormatter = NumberFormat.getInstance(locale);
+        numberFormatter.setMinimumFractionDigits(fractionDigits);
+        numberFormatter.setMaximumFractionDigits(fractionDigits);
+        numberFormatter.setGroupingUsed(false);
+        if (numberFormatter instanceof DecimalFormat) {
+            // We do this only for DecimalFormat, since in the general NumberFormat case, calling
+            // setRoundingMode may throw an exception.
+            numberFormatter.setRoundingMode(BigDecimal.ROUND_HALF_UP);
+        }
+        return numberFormatter;
+    }
+
+    private static String formatMeasureShort(Locale locale, NumberFormat numberFormatter,
+            float value, MeasureUnit units) {
+        final MeasureFormat measureFormatter = MeasureFormat.getInstance(
+                locale, MeasureFormat.FormatWidth.SHORT, numberFormatter);
+        return measureFormatter.format(new Measure(value, units));
+    }
+
+    private static String formatRoundedBytesResult(
+            @NonNull Context context, @NonNull RoundedBytesResult input) {
+        final Locale locale = localeFromContext(context);
+        final NumberFormat numberFormatter = getNumberFormatter(locale, input.fractionDigits);
+        return formatMeasureShort(locale, numberFormatter, input.value, input.units);
+    }
+
     /**
      * Formats a content size to be in the form of bytes, kilobytes, megabytes, etc.
      *
@@ -47,23 +113,17 @@
      *
      * @param context Context to use to load the localized units
      * @param sizeBytes size value to be formatted, in bytes
-     * @param suffix String id for the unit suffix.
-     * @param mult Amount of bytes in the unit. * @return formatted string with the number
+     * @param unit The unit used for formatting.
+     * @param mult Amount of bytes in the unit.
+     * @return formatted string with the number
      */
     public static String formatFileSize(
-            @Nullable Context context, long sizeBytes, int suffix, long mult) {
+            @Nullable Context context, long sizeBytes, MeasureUnit unit, long mult) {
         if (context == null) {
             return "";
         }
-        final Formatter.BytesResult res =
-                formatBytes(context.getResources(), sizeBytes, suffix, mult);
-        return BidiFormatter.getInstance()
-                .unicodeWrap(context.getString(getFileSizeSuffix(context), res.value, res.units));
-    }
-
-    private static int getFileSizeSuffix(Context context) {
-        final Resources res = context.getResources();
-        return res.getIdentifier("fileSizeSuffix", "string", "android");
+        final RoundedBytesResult res = formatBytes(sizeBytes, unit, mult);
+        return bidiWrap(context, formatRoundedBytesResult(context, res));
     }
 
     /**
@@ -76,8 +136,8 @@
      * @param suffix String id for the unit suffix.
      * @param mult Amount of bytes in the unit.
      */
-    private static Formatter.BytesResult formatBytes(
-            Resources res, long sizeBytes, int suffix, long mult) {
+    private static RoundedBytesResult formatBytes(
+            long sizeBytes, MeasureUnit unit, long mult) {
         final boolean isNegative = (sizeBytes < 0);
         float result = isNegative ? -sizeBytes : sizeBytes;
         result = result / mult;
@@ -85,32 +145,29 @@
         // compute the rounded value. String.format("%f", 0.1) might not return "0.1" due to
         // floating point errors.
         final int roundFactor;
-        final String roundFormat;
+        final int roundDigits;
         if (mult == 1) {
             roundFactor = 1;
-            roundFormat = "%.0f";
+            roundDigits = 0;
         } else if (result < 1) {
             roundFactor = 100;
-            roundFormat = "%.2f";
+            roundDigits = 2;
         } else if (result < 10) {
             roundFactor = 10;
-            roundFormat = "%.1f";
+            roundDigits = 1;
         } else { // 10 <= result < 100
             roundFactor = 1;
-            roundFormat = "%.0f";
+            roundDigits = 0;
         }
 
         if (isNegative) {
             result = -result;
         }
-        final String roundedString = String.format(roundFormat, result);
 
         // Note this might overflow if abs(result) >= Long.MAX_VALUE / 100, but that's like 80PB so
         // it's okay (for now)...
         final long roundedBytes = (((long) Math.round(result * roundFactor)) * mult / roundFactor);
 
-        final String units = res.getString(suffix);
-
-        return new Formatter.BytesResult(roundedString, units, roundedBytes);
+        return new RoundedBytesResult(result, unit, roundDigits, roundedBytes);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/MasterClearTest.java b/tests/robotests/src/com/android/settings/MasterClearTest.java
index d913946..8e8578f 100644
--- a/tests/robotests/src/com/android/settings/MasterClearTest.java
+++ b/tests/robotests/src/com/android/settings/MasterClearTest.java
@@ -92,55 +92,32 @@
     @Test
     public void testShowWipeEuicc_euiccDisabled() {
         prepareEuiccState(
-                false /* isEuiccEnabled */, true /* isEuiccProvisioned */,
-                true /* isDevelopmentSettingsEnabled */);
+                false /* isEuiccEnabled */, true /* isEuiccProvisioned */);
         assertThat(mMasterClear.showWipeEuicc()).isFalse();
     }
 
     @Test
     public void testShowWipeEuicc_euiccEnabled_unprovisioned() {
         prepareEuiccState(
-                true /* isEuiccEnabled */, false /* isEuiccProvisioned */,
-                false /* isDevelopmentSettingsEnabled */);
+                true /* isEuiccEnabled */, false /* isEuiccProvisioned */);
         assertThat(mMasterClear.showWipeEuicc()).isFalse();
     }
 
     @Test
     public void testShowWipeEuicc_euiccEnabled_provisioned() {
         prepareEuiccState(
-                true /* isEuiccEnabled */, true /* isEuiccProvisioned */,
-                false /* isDevelopmentSettingsEnabled */);
-        assertThat(mMasterClear.showWipeEuicc()).isTrue();
-    }
-
-    @Test
-    public void testShowWipeEuicc_euiccEnabled_developmentSettingsEnabled() {
-        prepareEuiccState(
-                true /* isEuiccEnabled */, false /* isEuiccProvisioned */,
-                true /* isDevelopmentSettingsEnabled */);
-        assertThat(mMasterClear.showWipeEuicc()).isTrue();
-    }
-
-    @Test
-    public void testShowWipeEuicc_euiccEnabled_provisioned_developmentSettingsEnabled() {
-        prepareEuiccState(
-                true /* isEuiccEnabled */, true /* isEuiccProvisioned */,
-                true /* isDevelopmentSettingsEnabled */);
+                true /* isEuiccEnabled */, true /* isEuiccProvisioned */);
         assertThat(mMasterClear.showWipeEuicc()).isTrue();
     }
 
     private void prepareEuiccState(
             boolean isEuiccEnabled,
-            boolean isEuiccProvisioned,
-            boolean isDevelopmentSettingsEnabled) {
+            boolean isEuiccProvisioned) {
         doReturn(mActivity).when(mMasterClear).getContext();
         doReturn(isEuiccEnabled).when(mMasterClear).isEuiccEnabled(any());
         ContentResolver cr = mActivity.getContentResolver();
         Settings.Global.putInt(
                 cr, android.provider.Settings.Global.EUICC_PROVISIONED, isEuiccProvisioned ? 1 : 0);
-        Settings.Global.putInt(
-                cr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
-                isDevelopmentSettingsEnabled ? 1 : 0);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothEnablerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothEnablerTest.java
index 2d64396..74c47e2 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothEnablerTest.java
@@ -24,6 +24,7 @@
 import com.android.settings.core.instrumentation.MetricsFeatureProvider;
 import com.android.settings.widget.MasterSwitchController;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 
 import org.junit.Before;
@@ -58,17 +59,22 @@
     private MasterSwitchController mMasterSwitchController;
     @Mock
     private RestrictionUtils mRestrictionUtils;
+    @Mock
+    private LocalBluetoothManager mBluetoothManager;
+    @Mock
+    private LocalBluetoothAdapter mBluetoothAdapter;
 
     private BluetoothEnabler mBluetoothEnabler;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        when(mBluetoothManager.getBluetoothAdapter()).thenReturn(mBluetoothAdapter);
         mBluetoothEnabler = new BluetoothEnabler(
                 mContext,
                 mMasterSwitchController,
                 mMetricsFeatureProvider,
-                mock(LocalBluetoothManager.class),
+                mBluetoothManager,
                 123,
                 mRestrictionUtils);
     }
@@ -136,4 +142,17 @@
         verify(mMasterSwitchController).setChecked(false);
     }
 
+    @Test
+    public void maybeEnforceRestrictions_disallowBluetoothNotOverriden() {
+        // GIVEN Bluetooth has been disallowed...
+        when(mRestrictionUtils.checkIfRestrictionEnforced(
+                mContext, UserManager.DISALLOW_BLUETOOTH)).thenReturn(FAKE_ENFORCED_ADMIN);
+        when(mRestrictionUtils.checkIfRestrictionEnforced(
+                mContext, UserManager.DISALLOW_CONFIG_BLUETOOTH)).thenReturn(null);
+
+        mBluetoothEnabler.resume(mContext);
+
+        verify(mMasterSwitchController, never()).setEnabled(true);
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/DataPlansSyncTimePreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/DataPlansSyncTimePreferenceTest.java
new file mode 100644
index 0000000..ba2d5f1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datausage/DataPlansSyncTimePreferenceTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.datausage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public final class DataPlansSyncTimePreferenceTest {
+    private static final String SYNC_TIME = "Today 12:24pm";
+
+    private Preference mPreference;
+    private PreferenceViewHolder mHolder;
+
+    @Before
+    public void setUp() {
+        Context context = RuntimeEnvironment.application;
+        mPreference = new Preference(context);
+        mPreference.setLayoutResource(R.layout.data_plans_sync_time_preference);
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        View view = inflater.inflate(mPreference.getLayoutResource(),
+                new LinearLayout(context), false);
+        mHolder = PreferenceViewHolder.createInstanceForTests(view);
+    }
+
+    @Test
+    public void shouldRender_withData() {
+        mPreference.setTitle(SYNC_TIME);
+
+        mPreference.onBindViewHolder(mHolder);
+
+        TextView syncTimeTextView = (TextView) mHolder.findViewById(android.R.id.title);
+        assertThat(syncTimeTextView.getText()).isEqualTo(SYNC_TIME);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datausage/ManageDataPlansPreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/ManageDataPlansPreferenceTest.java
new file mode 100644
index 0000000..6eff393
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datausage/ManageDataPlansPreferenceTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.datausage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public final class ManageDataPlansPreferenceTest {
+    private Preference mPreference;
+    private PreferenceViewHolder mHolder;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mPreference = new Preference(mContext);
+        mPreference.setLayoutResource(R.layout.manage_data_plans_preference);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View view = inflater.inflate(mPreference.getLayoutResource(),
+                new LinearLayout(mContext), false);
+        mHolder = PreferenceViewHolder.createInstanceForTests(view);
+    }
+
+    @Test
+    public void shouldRender_withData() {
+        mPreference.onBindViewHolder(mHolder);
+        Button managePlanButton = (Button) mHolder.findViewById(R.id.manage_data_plans);
+        assertThat(managePlanButton.getText())
+                .isEqualTo(mContext.getString(R.string.data_plan_usage_manage_plans_button_text));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageItemPreferenceTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageItemPreferenceTest.java
index a154c03..5b34c7d 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageItemPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageItemPreferenceTest.java
@@ -55,7 +55,7 @@
     @Test
     public void testAfterLoad() {
         mPreference.setStorageSize(MEGABYTE_IN_BYTES * 10, MEGABYTE_IN_BYTES * 100);
-        assertThat(((String) mPreference.getSummary())).isEqualTo("0.01GB");
+        assertThat(((String) mPreference.getSummary())).isEqualTo("0.01 GB");
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
index fcda085..a871c19 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
@@ -104,7 +104,7 @@
         verify(mGroup).addPreference(argumentCaptor.capture());
 
         Preference preference = argumentCaptor.getValue();
-        assertThat(preference.getSummary()).isEqualTo("0.01GB");
+        assertThat(preference.getSummary()).isEqualTo("0.01 GB");
     }
 
     @Test
@@ -177,7 +177,7 @@
         verify(mGroup).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
 
-        assertThat(preference.getSummary()).isEqualTo("0.03GB");
+        assertThat(preference.getSummary()).isEqualTo("0.03 GB");
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 0d6a4d7..1599440 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -84,8 +84,6 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        SettingsShadowResources.overrideResource("android:string/fileSizeSuffix", "%1$s %2$s");
-        SettingsShadowResources.overrideResource("android:string/gigabyteShort", "GB");
         mContext = spy(RuntimeEnvironment.application.getApplicationContext());
         FakeFeatureFactory.setupForTest(mContext);
         mFakeFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
@@ -287,12 +285,12 @@
         results.put(0, result);
         mController.onLoadFinished(results, 0);
 
-        assertThat(audio.getSummary().toString()).isEqualTo("0.14GB");
-        assertThat(image.getSummary().toString()).isEqualTo("0.35GB");
-        assertThat(games.getSummary().toString()).isEqualTo("0.08GB");
-        assertThat(movies.getSummary().toString()).isEqualTo("0.16GB");
-        assertThat(apps.getSummary().toString()).isEqualTo("0.09GB");
-        assertThat(files.getSummary().toString()).isEqualTo("0.05GB");
+        assertThat(audio.getSummary().toString()).isEqualTo("0.14 GB");
+        assertThat(image.getSummary().toString()).isEqualTo("0.35 GB");
+        assertThat(games.getSummary().toString()).isEqualTo("0.08 GB");
+        assertThat(movies.getSummary().toString()).isEqualTo("0.16 GB");
+        assertThat(apps.getSummary().toString()).isEqualTo("0.09 GB");
+        assertThat(files.getSummary().toString()).isEqualTo("0.05 GB");
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
index db7c9f7..a2e57b9 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
@@ -122,7 +122,7 @@
         verify(mScreen).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
 
-        assertThat(preference.getSummary()).isEqualTo("0.10GB");
+        assertThat(preference.getSummary()).isEqualTo("0.10 GB");
     }
 
     @Test
diff --git a/tests/unit/README b/tests/unit/README
index 5184b07..2544ea5 100644
--- a/tests/unit/README
+++ b/tests/unit/README
@@ -1,8 +1,8 @@
 To build the tests you can use the following command at the root of your android source tree
-$ make SettingsUnitTests
+$ make -j SettingsUnitTests
 
 The test apk then needs to be installed onto your test device via for example
-$ adb install -r out/target/product/shamu/data/app/SettingsUnitTests/SettingsUnitTests.apk
+$ adb install -r ${ANDROID_PRODUCT_OUT}/data/app/SettingsUnitTests/SettingsUnitTests.apk
 
 To run all tests:
 $ adb shell am instrument -w com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
diff --git a/tests/unit/src/com/android/settings/utils/FileSizeFormatterTest.java b/tests/unit/src/com/android/settings/utils/FileSizeFormatterTest.java
index c5b050a..41b236c 100644
--- a/tests/unit/src/com/android/settings/utils/FileSizeFormatterTest.java
+++ b/tests/unit/src/com/android/settings/utils/FileSizeFormatterTest.java
@@ -22,6 +22,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.icu.util.MeasureUnit;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -46,7 +47,7 @@
                         FileSizeFormatter.formatFileSize(
                                 mContext,
                                 0 /* size */,
-                                com.android.internal.R.string.gigabyteShort,
+                                MeasureUnit.GIGABYTE,
                                 GIGABYTE_IN_BYTES))
                 .isEqualTo("0.00 GB");
     }
@@ -57,7 +58,7 @@
                         FileSizeFormatter.formatFileSize(
                                 mContext,
                                 MEGABYTE_IN_BYTES * 11 /* size */,
-                                com.android.internal.R.string.gigabyteShort,
+                                MeasureUnit.GIGABYTE,
                                 GIGABYTE_IN_BYTES))
                 .isEqualTo("0.01 GB");
     }
@@ -68,7 +69,7 @@
                         FileSizeFormatter.formatFileSize(
                                 mContext,
                                 MEGABYTE_IN_BYTES * 155 /* size */,
-                                com.android.internal.R.string.gigabyteShort,
+                                MeasureUnit.GIGABYTE,
                                 GIGABYTE_IN_BYTES))
                 .isEqualTo("0.16 GB");
     }
@@ -79,7 +80,7 @@
                         FileSizeFormatter.formatFileSize(
                                 mContext,
                                 MEGABYTE_IN_BYTES * 1551 /* size */,
-                                com.android.internal.R.string.gigabyteShort,
+                                MeasureUnit.GIGABYTE,
                                 GIGABYTE_IN_BYTES))
                 .isEqualTo("1.6 GB");
     }
@@ -91,7 +92,7 @@
                         FileSizeFormatter.formatFileSize(
                                 mContext,
                                 GIGABYTE_IN_BYTES * 15 + MEGABYTE_IN_BYTES * 50 /* size */,
-                                com.android.internal.R.string.gigabyteShort,
+                                MeasureUnit.GIGABYTE,
                                 GIGABYTE_IN_BYTES))
                 .isEqualTo("15 GB");
     }
@@ -102,7 +103,7 @@
                         FileSizeFormatter.formatFileSize(
                                 mContext,
                                 MEGABYTE_IN_BYTES * -155 /* size */,
-                                com.android.internal.R.string.gigabyteShort,
+                                MeasureUnit.GIGABYTE,
                                 GIGABYTE_IN_BYTES))
                 .isEqualTo("-0.16 GB");
     }