Merge "Don't allow a zero-length device name to work." into pi-dev
diff --git a/res/layout/empty_printers_list_service_enabled.xml b/res/layout/empty_printers_list_service_enabled.xml
index e420d5f..8cc8db4 100644
--- a/res/layout/empty_printers_list_service_enabled.xml
+++ b/res/layout/empty_printers_list_service_enabled.xml
@@ -32,7 +32,7 @@
             android:layout_height="wrap_content"
             android:layout_marginBottom="12dip"
             android:src="@drawable/ic_grayedout_printer"
-            android:contentDescription="@string/print_searching_for_printers">
+            android:importantForAccessibility="no">
         </ImageView>
 
         <TextView
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d597966..406cac2 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -295,6 +295,8 @@
     <dimen name="storage_summary_padding_end">16dp</dimen>
     <!-- Text size of the big number in the donut. -->
     <dimen name="storage_donut_view_percent_text_size">30sp</dimen>
+    <!-- Text size of the percentage sign in the donut. -->
+    <dimen name="storage_donut_view_percent_sign_size">20sp</dimen>
     <!-- Text size of the label text in the donut. -->
     <dimen name="storage_donut_view_label_text_size">14sp</dimen>
     <!-- Text size of the label text in the donut if the label text is long. -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2d530ee..0bb3f4a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4045,7 +4045,7 @@
     <!-- [CHAR_LIMIT=NONE] Format to put together two unrelated items in a list when "and" is not an appropriate conjunction for these 2 items -->
     <string name="join_two_unrelated_items"><xliff:g id="first_item">%1$s</xliff:g>, <xliff:g id="second_item">%2$s</xliff:g></string>
     <!-- [CHAR_LIMIT=NONE] Format to put the last item at the end of a series of 3 or more items in a list -->
-    <string name="join_many_items_last"><xliff:g id="all_but_last_item">%1$s</xliff:g> and <xliff:g id="last_item">%2$s</xliff:g></string>
+    <string name="join_many_items_last"><xliff:g id="all_but_last_item">%1$s</xliff:g>, and <xliff:g id="last_item">%2$s</xliff:g></string>
     <!-- [CHAR_LIMIT=NONE] Format to put the first item at the start of a series of 3 or more items in a list -->
     <string name="join_many_items_first"><xliff:g id="first_item">%1$s</xliff:g>, <xliff:g id="all_but_first_and_last_item">%2$s</xliff:g></string>
     <!-- [CHAR_LIMIT=NONE] Format to put the middle items together in a series of 4 or more items in a list -->
@@ -9620,7 +9620,7 @@
     <string name="storage_files">Files</string>
 
     <!-- Summary of a single storage volume used space. [CHAR LIMIT=24] -->
-    <string name="storage_size_large_alternate"><xliff:g id="number" example="128">^1</xliff:g><small> <xliff:g id="unit" example="KB">^2</xliff:g></small></string>
+    <string name="storage_size_large_alternate"><xliff:g id="number" example="128">^1</xliff:g><small> <font size="20"><xliff:g id="unit" example="KB">^2</xliff:g></font></small></string>
     <!-- Summary of a single storage volume total space. [CHAR LIMIT=48]-->
     <string name="storage_volume_total">Used of <xliff:g id="total" example="32GB">%1$s</xliff:g></string>
     <!-- Follows the percent of storage used by a storage volume. Exposed inside of a donut graph. [CHAR LIMIT=7]-->
diff --git a/res/xml/ambient_display_settings.xml b/res/xml/ambient_display_settings.xml
index 306ead5..037421c 100644
--- a/res/xml/ambient_display_settings.xml
+++ b/res/xml/ambient_display_settings.xml
@@ -29,7 +29,8 @@
         <SwitchPreference
             android:key="ambient_display_always_on"
             android:title="@string/doze_always_on_title"
-            android:summary="@string/doze_always_on_summary" />
+            android:summary="@string/doze_always_on_summary"
+            settings:controller="com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController" />
 
         <Preference
             android:key="ambient_display_double_tap"
diff --git a/res/xml/network_and_internet.xml b/res/xml/network_and_internet.xml
index 6758e7e..a28b1e6 100644
--- a/res/xml/network_and_internet.xml
+++ b/res/xml/network_and_internet.xml
@@ -37,7 +37,6 @@
         android:title="@string/network_settings_title"
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_network_cell"
-        android:dependency="toggle_airplane"
         android:order="-15"
         settings:keywords="@string/keywords_more_mobile_networks"
         settings:userRestriction="no_config_mobile_networks"
diff --git a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
index 047d38e..0997e60 100644
--- a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.support.annotation.VisibleForTesting;
@@ -61,7 +62,12 @@
         if (resolved == null || resolved.isEmpty()) {
             return DISABLED_UNSUPPORTED;
         }
-        return AVAILABLE;
+        for (ResolveInfo info : resolved) {
+            if (isSystemApp(info)) {
+                return AVAILABLE;
+            }
+        }
+        return DISABLED_UNSUPPORTED;
     }
 
     @Override
@@ -72,4 +78,11 @@
             pref.setIntent(mIntent);
         }
     }
+
+    private boolean isSystemApp(ResolveInfo info) {
+        return info != null
+                && info.activityInfo != null
+                && info.activityInfo.applicationInfo != null
+                && (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
 }
diff --git a/src/com/android/settings/dashboard/conditional/RingerMutedCondition.java b/src/com/android/settings/dashboard/conditional/RingerMutedCondition.java
index bdd92e2..bf5bc36 100644
--- a/src/com/android/settings/dashboard/conditional/RingerMutedCondition.java
+++ b/src/com/android/settings/dashboard/conditional/RingerMutedCondition.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.dashboard.conditional;
 
+import static android.content.Context.NOTIFICATION_SERVICE;
+
 import android.app.NotificationManager;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
@@ -30,14 +32,19 @@
 
     RingerMutedCondition(ConditionManager manager) {
         super(manager);
-        mNotificationManager = mManager.getContext().getSystemService(NotificationManager.class);
+        mNotificationManager =
+                (NotificationManager) mManager.getContext().getSystemService(NOTIFICATION_SERVICE);
     }
 
     @Override
     public void refreshState() {
-        int zen = mNotificationManager.getZenMode();
-        boolean zenModeEnabled = zen != Settings.Global.ZEN_MODE_OFF;
-        boolean isSilent = mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT;
+        int zen = Settings.Global.ZEN_MODE_OFF;
+        if (mNotificationManager != null) {
+            zen = mNotificationManager.getZenMode();
+        }
+        final boolean zenModeEnabled = zen != Settings.Global.ZEN_MODE_OFF;
+        final boolean isSilent =
+                mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT;
         setActive(isSilent && !zenModeEnabled);
     }
 
diff --git a/src/com/android/settings/datausage/DataSaverSummary.java b/src/com/android/settings/datausage/DataSaverSummary.java
index 4ada3af..a3fc98d 100644
--- a/src/com/android/settings/datausage/DataSaverSummary.java
+++ b/src/com/android/settings/datausage/DataSaverSummary.java
@@ -68,6 +68,9 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar();
+        mSwitchBar.setSwitchBarText(
+                R.string.data_saver_switch_title,
+                R.string.data_saver_switch_title);
         mSwitchBar.show();
         mSwitchBar.addOnSwitchChangeListener(this);
     }
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 9c872a4..ead941f 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -46,6 +46,7 @@
 import com.android.settings.deviceinfo.storage.VolumeSizesLoader;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settings.wrapper.UserManagerWrapper;
 import com.android.settingslib.applications.StorageStatsSource;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -106,6 +107,13 @@
         super.onViewCreated(v, savedInstanceState);
         initializeCacheProvider();
         maybeSetLoading(isQuotaSupported());
+
+        final Activity activity = getActivity();
+        EntityHeaderController.newInstance(activity, this /*fragment*/,
+                null /* header view */)
+                .setRecyclerView(getListView(), getLifecycle())
+                .styleActionBar(activity);
+
     }
 
     @Override
diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
index aaa75e3..cf9d34b 100644
--- a/src/com/android/settings/deviceinfo/StorageSettings.java
+++ b/src/com/android/settings/deviceinfo/StorageSettings.java
@@ -36,6 +36,7 @@
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
 import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceCategory;
 import android.text.TextUtils;
@@ -71,10 +72,11 @@
 
     private static final String TAG_VOLUME_UNMOUNTED = "volume_unmounted";
     private static final String TAG_DISK_INIT = "disk_init";
+    private static final int METRICS_CATEGORY = MetricsEvent.DEVICEINFO_STORAGE;
 
     static final int COLOR_PUBLIC = Color.parseColor("#ff9e9e9e");
 
-    static final int[] COLOR_PRIVATE = new int[] {
+    static final int[] COLOR_PRIVATE = new int[]{
             Color.parseColor("#ff26a69a"),
             Color.parseColor("#ffab47bc"),
             Color.parseColor("#fff2a600"),
@@ -94,7 +96,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsEvent.DEVICEINFO_STORAGE;
+        return METRICS_CATEGORY;
     }
 
     @Override
@@ -139,7 +141,7 @@
     };
 
     private static boolean isInteresting(VolumeInfo vol) {
-        switch(vol.getType()) {
+        switch (vol.getType()) {
             case VolumeInfo.TYPE_PRIVATE:
             case VolumeInfo.TYPE_PUBLIC:
                 return true;
@@ -301,20 +303,7 @@
                 return true;
 
             } else if (vol.getType() == VolumeInfo.TYPE_PUBLIC) {
-                if (vol.isMountedReadable()) {
-                    startActivity(vol.buildBrowseIntent());
-                    return true;
-                } else {
-                    final Bundle args = new Bundle();
-                    args.putString(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
-                    new SubSettingLauncher(getContext())
-                            .setDestination(PublicVolumeSettings.class.getCanonicalName())
-                            .setTitle(-1)
-                            .setSourceMetricsCategory(getMetricsCategory())
-                            .setArguments(args)
-                            .launch();
-                    return true;
-                }
+                return handlePublicVolumeClick(getContext(), vol);
             }
 
         } else if (key.startsWith("disk:")) {
@@ -328,7 +317,7 @@
             args.putString(VolumeRecord.EXTRA_FS_UUID, key);
             new SubSettingLauncher(getContext())
                     .setDestination(PrivateVolumeForget.class.getCanonicalName())
-                            .setTitle(R.string.storage_menu_forget)
+                    .setTitle(R.string.storage_menu_forget)
                     .setSourceMetricsCategory(getMetricsCategory())
                     .setArguments(args)
                     .launch();
@@ -338,6 +327,25 @@
         return false;
     }
 
+    @VisibleForTesting
+    static boolean handlePublicVolumeClick(Context context, VolumeInfo vol) {
+        final Intent intent = vol.buildBrowseIntent();
+        if (vol.isMountedReadable() && intent != null) {
+            context.startActivity(intent);
+            return true;
+        } else {
+            final Bundle args = new Bundle();
+            args.putString(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
+            new SubSettingLauncher(context)
+                    .setDestination(PublicVolumeSettings.class.getCanonicalName())
+                    .setTitle(-1)
+                    .setSourceMetricsCategory(METRICS_CATEGORY)
+                    .setArguments(args)
+                    .launch();
+            return true;
+        }
+    }
+
     public static class MountTask extends AsyncTask<Void, Void, Exception> {
         private final Context mContext;
         private final StorageManager mStorageManager;
@@ -440,40 +448,45 @@
 
             builder.setPositiveButton(R.string.storage_menu_mount,
                     new DialogInterface.OnClickListener() {
-                /**
-                 * Check if an {@link RestrictedLockUtils#sendShowAdminSupportDetailsIntent admin
-                 * details intent} should be shown for the restriction and show it.
-                 *
-                 * @param restriction The restriction to check
-                 * @return {@code true} iff a intent was shown.
-                 */
-                private boolean wasAdminSupportIntentShown(@NonNull String restriction) {
-                    EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
-                            getActivity(), restriction, UserHandle.myUserId());
-                    boolean hasBaseUserRestriction = RestrictedLockUtils.hasBaseUserRestriction(
-                            getActivity(), restriction, UserHandle.myUserId());
-                    if (admin != null && !hasBaseUserRestriction) {
-                        RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(), admin);
-                        return true;
-                    }
+                        /**
+                         * Check if an {@link
+                         * RestrictedLockUtils#sendShowAdminSupportDetailsIntent admin
+                         * details intent} should be shown for the restriction and show it.
+                         *
+                         * @param restriction The restriction to check
+                         * @return {@code true} iff a intent was shown.
+                         */
+                        private boolean wasAdminSupportIntentShown(@NonNull String restriction) {
+                            EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+                                    getActivity(), restriction, UserHandle.myUserId());
+                            boolean hasBaseUserRestriction =
+                                    RestrictedLockUtils.hasBaseUserRestriction(
+                                            getActivity(), restriction, UserHandle.myUserId());
+                            if (admin != null && !hasBaseUserRestriction) {
+                                RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(),
+                                        admin);
+                                return true;
+                            }
 
-                    return false;
-                }
+                            return false;
+                        }
 
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    if (wasAdminSupportIntentShown(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA)) {
-                        return;
-                    }
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            if (wasAdminSupportIntentShown(
+                                    UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA)) {
+                                return;
+                            }
 
-                    if (vol.disk != null && vol.disk.isUsb() &&
-                            wasAdminSupportIntentShown(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
-                        return;
-                    }
+                            if (vol.disk != null && vol.disk.isUsb() &&
+                                    wasAdminSupportIntentShown(
+                                            UserManager.DISALLOW_USB_FILE_TRANSFER)) {
+                                return;
+                            }
 
-                    new MountTask(context, vol).execute();
-                }
-            });
+                            new MountTask(context, vol).execute();
+                        }
+                    });
             builder.setNegativeButton(R.string.cancel, null);
 
             return builder.create();
@@ -511,13 +524,13 @@
 
             builder.setPositiveButton(R.string.storage_menu_set_up,
                     new DialogInterface.OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    final Intent intent = new Intent(context, StorageWizardInit.class);
-                    intent.putExtra(DiskInfo.EXTRA_DISK_ID, diskId);
-                    startActivity(intent);
-                }
-            });
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            final Intent intent = new Intent(context, StorageWizardInit.class);
+                            intent.putExtra(DiskInfo.EXTRA_DISK_ID, diskId);
+                            startActivity(intent);
+                        }
+                    });
             builder.setNegativeButton(R.string.cancel, null);
 
             return builder.create();
@@ -586,7 +599,7 @@
                     for (VolumeInfo vol : vols) {
                         if (isInteresting(vol)) {
                             data.title = storage.getBestVolumeDescription(vol);
-                            data.key = "storage_settings_volume_" +vol.id;
+                            data.key = "storage_settings_volume_" + vol.id;
                             data.screenTitle = context.getString(R.string.storage_settings);
                             result.add(data);
                         }
diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
index 9132daa..e0efaac 100644
--- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
+++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
@@ -19,59 +19,45 @@
 import android.content.Intent;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
-import android.support.annotation.VisibleForTesting;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.TogglePreferenceController;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settings.search.InlineSwitchPayload;
 import com.android.settings.search.ResultPayload;
-import com.android.settingslib.core.AbstractPreferenceController;
 
-public class AmbientDisplayAlwaysOnPreferenceController extends
-        AbstractPreferenceController implements PreferenceControllerMixin,
-        Preference.OnPreferenceChangeListener {
+public class AmbientDisplayAlwaysOnPreferenceController extends TogglePreferenceController {
 
     private final int ON = 1;
     private final int OFF = 0;
 
-    public static final String KEY_ALWAYS_ON = "ambient_display_always_on";
     private static final int MY_USER = UserHandle.myUserId();
 
-    private final AmbientDisplayConfiguration mConfig;
-    private final OnPreferenceChangedCallback mCallback;
+    private AmbientDisplayConfiguration mConfig;
+    private OnPreferenceChangedCallback mCallback;
 
     public interface OnPreferenceChangedCallback {
         void onPreferenceChanged();
     }
 
-    public AmbientDisplayAlwaysOnPreferenceController(Context context,
-            AmbientDisplayConfiguration config, OnPreferenceChangedCallback callback) {
-        super(context);
-        mConfig = config;
-        mCallback = callback;
+    public AmbientDisplayAlwaysOnPreferenceController(Context context, String key) {
+        super(context, key);
     }
 
     @Override
-    public String getPreferenceKey() {
-        return KEY_ALWAYS_ON;
+    public int getAvailabilityStatus() {
+        return isAvailable(mConfig) ? AVAILABLE : DISABLED_UNSUPPORTED;
     }
 
     @Override
-    public void updateState(Preference preference) {
-        ((SwitchPreference) preference).setChecked(isAlwaysOnEnabled(mConfig));
-    }
-
-    public static boolean isAlwaysOnEnabled(AmbientDisplayConfiguration config) {
-        return config.alwaysOnEnabled(MY_USER);
+    public boolean isChecked() {
+        return mConfig.alwaysOnEnabled(MY_USER);
     }
 
     @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        int enabled = (boolean) newValue ? ON : OFF;
+    public boolean setChecked(boolean isChecked) {
+        int enabled = isChecked ? ON : OFF;
         Settings.Secure.putInt(
                 mContext.getContentResolver(), Settings.Secure.DOZE_ALWAYS_ON, enabled);
         if (mCallback != null) {
@@ -80,9 +66,16 @@
         return true;
     }
 
-    @Override
-    public boolean isAvailable() {
-        return alwaysOnAvailableForUser(mConfig);
+    public void setConfig(AmbientDisplayConfiguration config) {
+        mConfig = config;
+    }
+
+    public void setCallback(OnPreferenceChangedCallback callback) {
+        mCallback = callback;
+    }
+
+    public static boolean isAlwaysOnEnabled(AmbientDisplayConfiguration config) {
+        return config.alwaysOnEnabled(MY_USER);
     }
 
     public static boolean isAvailable(AmbientDisplayConfiguration config) {
@@ -96,16 +89,11 @@
     @Override
     public ResultPayload getResultPayload() {
         final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(mContext,
-                AmbientDisplaySettings.class.getName(), KEY_ALWAYS_ON,
+                AmbientDisplaySettings.class.getName(), getPreferenceKey(),
                 mContext.getString(R.string.ambient_display_screen_title));
 
         return new InlineSwitchPayload(Settings.Secure.DOZE_ALWAYS_ON,
                 ResultPayload.SettingsSource.SECURE, ON /* onValue */, intent, isAvailable(),
                 ON /* defaultValue */);
     }
-
-    @VisibleForTesting
-    boolean alwaysOnAvailableForUser(AmbientDisplayConfiguration config) {
-        return isAvailable(config);
-    }
 }
diff --git a/src/com/android/settings/display/AmbientDisplaySettings.java b/src/com/android/settings/display/AmbientDisplaySettings.java
index 02db6f1..a88d2ed 100644
--- a/src/com/android/settings/display/AmbientDisplaySettings.java
+++ b/src/com/android/settings/display/AmbientDisplaySettings.java
@@ -40,23 +40,23 @@
  */
 public class AmbientDisplaySettings extends DashboardFragment {
 
+    public static final String KEY_AMBIENT_DISPLAY_ALWAYS_ON = "ambient_display_always_on";
+
     private static final String TAG = "AmbientDisplaySettings";
     private static final int MY_USER_ID = UserHandle.myUserId();
 
-    private static final String KEY_AMBIENT_DISPLAY_ALWAYS_ON = "ambient_display_always_on";
     private static final String KEY_AMBIENT_DISPLAY_DOUBLE_TAP = "ambient_display_double_tap";
     private static final String KEY_AMBIENT_DISPLAY_PICK_UP = "ambient_display_pick_up";
     private static final String KEY_AMBIENT_DISPLAY_NOTIFICATION = "ambient_display_notification";
 
+    private AmbientDisplayConfiguration mConfig;
+
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle, AmbientDisplayConfiguration config,
-            MetricsFeatureProvider metricsFeatureProvider,
-            AmbientDisplayAlwaysOnPreferenceController.OnPreferenceChangedCallback aodCallback) {
+            MetricsFeatureProvider metricsFeatureProvider) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         controllers.add(new AmbientDisplayNotificationsPreferenceController(context, config,
                 metricsFeatureProvider));
-        controllers.add(new AmbientDisplayAlwaysOnPreferenceController(context, config,
-                aodCallback));
         controllers.add(new DoubleTapScreenPreferenceController(context, lifecycle, config,
                 MY_USER_ID, KEY_AMBIENT_DISPLAY_DOUBLE_TAP));
         controllers.add(new PickupGesturePreferenceController(context, lifecycle, config,
@@ -64,6 +64,14 @@
         return controllers;
     }
 
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        final AmbientDisplayAlwaysOnPreferenceController controller = use(
+                AmbientDisplayAlwaysOnPreferenceController.class);
+        controller.setConfig(getConfig(context));
+        controller.setCallback(this::updatePreferenceStates);
+    }
 
     @Override
     protected String getLogTag() {
@@ -78,8 +86,7 @@
     @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         return buildPreferenceControllers(context, getLifecycle(),
-                new AmbientDisplayConfiguration(context), mMetricsFeatureProvider,
-                this::updatePreferenceStates);
+                getConfig(context), mMetricsFeatureProvider);
     }
 
     @Override
@@ -104,7 +111,14 @@
                 public List<AbstractPreferenceController> createPreferenceControllers(
                         Context context) {
                     return buildPreferenceControllers(context, null,
-                            new AmbientDisplayConfiguration(context), null, null);
+                            new AmbientDisplayConfiguration(context), null);
                 }
             };
+
+    private AmbientDisplayConfiguration getConfig(Context context) {
+        if (mConfig != null) {
+            mConfig = new AmbientDisplayConfiguration(context);
+        }
+        return mConfig;
+    }
 }
diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java
index 09f0f8b..f3129dd 100644
--- a/src/com/android/settings/network/MobileNetworkPreferenceController.java
+++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java
@@ -18,8 +18,12 @@
 import static android.os.UserHandle.myUserId;
 import static android.os.UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
@@ -29,6 +33,7 @@
 
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.wrapper.RestrictedLockUtilsWrapper;
+import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.Utils;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -47,11 +52,20 @@
     @VisibleForTesting
     PhoneStateListener mPhoneStateListener;
 
+    private BroadcastReceiver mAirplanModeChangedReceiver;
+
     public MobileNetworkPreferenceController(Context context) {
         super(context);
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         mIsSecondaryUser = !mUserManager.isAdminUser();
+
+        mAirplanModeChangedReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                updateState(mPreference);
+            }
+        };
     }
 
     @Override
@@ -92,6 +106,10 @@
             }
             mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
         }
+        if (mAirplanModeChangedReceiver != null) {
+            mContext.registerReceiver(mAirplanModeChangedReceiver,
+                new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+        }
     }
 
     @Override
@@ -99,6 +117,21 @@
         if (mPhoneStateListener != null) {
             mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
         }
+        if (mAirplanModeChangedReceiver != null) {
+            mContext.unregisterReceiver(mAirplanModeChangedReceiver);
+        }
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+
+        if (preference instanceof RestrictedPreference &&
+            ((RestrictedPreference) preference).isDisabledByAdmin()) {
+                return;
+        }
+        preference.setEnabled(Settings.Global.getInt(
+            mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 0);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 2718756..5b85440 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -107,7 +107,7 @@
             } else if (numCategories == 3){
                 String secondaryText = mContext.getString(R.string.join_two_unrelated_items,
                         enabledCategories.get(0), enabledCategories.get(1).toLowerCase());
-                return mContext.getString(R.string.join_two_items, secondaryText,
+                return mContext.getString(R.string.join_many_items_last, secondaryText,
                         enabledCategories.get(2).toLowerCase());
             } else {
                 String secondaryText = mContext.getString(R.string.join_many_items_middle,
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index e5ba200..aa67b85 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -236,7 +236,8 @@
                 boolean managedProfileWithUnifiedLock =
                         UserManager.get(getActivity()).isManagedProfile(mUserId)
                         && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId);
-                if (managedProfileWithUnifiedLock
+                boolean skipConfirmation = managedProfileWithUnifiedLock && !mIsSetNewPassword;
+                if (skipConfirmation
                         || !helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
                         getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)) {
                     mPasswordConfirmed = true; // no password set, so no need to confirm
diff --git a/src/com/android/settings/widget/DonutView.java b/src/com/android/settings/widget/DonutView.java
index 330249b..4fb3c5b 100644
--- a/src/com/android/settings/widget/DonutView.java
+++ b/src/com/android/settings/widget/DonutView.java
@@ -24,9 +24,16 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Typeface;
+import android.icu.text.DecimalFormatSymbols;
 import android.support.annotation.ColorRes;
+import android.text.Layout;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.StaticLayout;
 import android.text.TextPaint;
 import android.text.TextUtils;
+import android.text.style.RelativeSizeSpan;
 import android.util.AttributeSet;
 import android.view.View;
 
@@ -124,7 +131,6 @@
         mBigNumberPaint.setAntiAlias(true);
         mBigNumberPaint.setTextSize(
                 resources.getDimension(R.dimen.storage_donut_view_percent_text_size));
-        mBigNumberPaint.setTextAlign(Paint.Align.CENTER);
         mBigNumberPaint.setTypeface(Typeface.create(
                 context.getString(com.android.internal.R.string.config_headlineFontFamily),
                 Typeface.NORMAL));
@@ -167,11 +173,25 @@
         final float centerY = getHeight() / 2;
         final float totalHeight = getTextHeight(mTextPaint) + getTextHeight(mBigNumberPaint);
         final float startY = centerY + totalHeight / 2;
+        final float fontProportion = getResources().getDimension(
+                R.dimen.storage_donut_view_percent_sign_size) /
+                getResources().getDimension(R.dimen.storage_donut_view_percent_text_size);
+        // Support from Android P
+        final String localizedPercentSign = new DecimalFormatSymbols().getPercentString();
+        final int startIndex = mPercentString.indexOf(localizedPercentSign);
+        final int endIndex = startIndex + localizedPercentSign.length();
 
-        // The first line is the height of the bottom text + its descender above the bottom line.
-        canvas.drawText(mPercentString, centerX,
-                startY - getTextHeight(mTextPaint) - mBigNumberPaint.descent(),
-                mBigNumberPaint);
+        // The first line y-coordinates start at (total height - all TextPaint height) / 2
+        canvas.save();
+        final Spannable percentStringSpan = new SpannableString(mPercentString);
+        percentStringSpan.setSpan(new RelativeSizeSpan(fontProportion),
+                startIndex, endIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        final StaticLayout percentStringLayout = new StaticLayout(percentStringSpan,
+                mBigNumberPaint, getWidth(), Layout.Alignment.ALIGN_CENTER, 1, 0, false);
+        canvas.translate(0, (getHeight() - totalHeight) / 2);
+        percentStringLayout.draw(canvas);
+        canvas.restore();
+
         // The second line starts at the bottom + room for the descender.
         canvas.drawText(mFullString, centerX, startY - mTextPaint.descent(), mTextPaint);
     }
diff --git a/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor b/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor
new file mode 100644
index 0000000..bf2f29e
--- /dev/null
+++ b/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor
@@ -0,0 +1,31 @@
+com.android.settings.applications.appinfo.AppActionButtonPreferenceController
+com.android.settings.applications.appinfo.AppBatteryPreferenceController
+com.android.settings.applications.appinfo.AppDataUsagePreferenceController
+com.android.settings.applications.appinfo.AppHeaderViewPreferenceController
+com.android.settings.applications.appinfo.AppInstallerInfoPreferenceController
+com.android.settings.applications.appinfo.AppMemoryPreferenceController
+com.android.settings.applications.appinfo.AppNotificationPreferenceController
+com.android.settings.applications.appinfo.AppOpenByDefaultPreferenceController
+com.android.settings.applications.appinfo.AppPermissionPreferenceController
+com.android.settings.applications.appinfo.AppStoragePreferenceController
+com.android.settings.applications.appinfo.AppVersionPreferenceController
+com.android.settings.applications.appinfo.DrawOverlayDetailPreferenceController
+com.android.settings.applications.appinfo.ExternalSourceDetailPreferenceController
+com.android.settings.applications.appinfo.InstantAppButtonsPreferenceController
+com.android.settings.applications.appinfo.InstantAppDomainsPreferenceController
+com.android.settings.applications.appinfo.PictureInPictureDetailPreferenceController
+com.android.settings.applications.appinfo.WriteSystemSettingsPreferenceController
+com.android.settings.bluetooth.BluetoothDeviceNamePreferenceController
+com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController
+com.android.settings.bluetooth.BluetoothSwitchPreferenceController
+com.android.settings.connecteddevice.ConnectedDeviceGroupController
+com.android.settings.connecteddevice.SavedDeviceGroupController
+com.android.settings.datausage.DataUsageSummaryPreferenceController
+com.android.settings.datetime.timezone.TimeZoneInfoPreferenceController
+com.android.settings.fuelgauge.RestrictAppPreferenceController
+com.android.settings.fuelgauge.batterysaver.AutoBatterySeekBarPreferenceController
+com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceController
+com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController
+com.android.settings.security.VisiblePatternProfilePreferenceController
+com.android.settings.security.screenlock.LockScreenPreferenceController
+com.android.settings.wifi.details.WifiMeteredPreferenceController
\ No newline at end of file
diff --git a/tests/robotests/src/android/app/admin/PasswordMetrics.java b/tests/robotests/src/android/app/admin/PasswordMetrics.java
deleted file mode 100644
index a461306..0000000
--- a/tests/robotests/src/android/app/admin/PasswordMetrics.java
+++ /dev/null
@@ -1,49 +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 android.app.admin;
-
-import android.annotation.NonNull;
-
-/**
- * Stub implementation of framework's PasswordMetrics for Robolectric tests. Otherwise Robolectric
- * is throwing ClassNotFoundError.
- *
- * TODO: Remove this class when Robolectric supports O
- */
-public class PasswordMetrics {
-
-    // Maximum allowed number of repeated or ordered characters in a sequence before we'll
-    // consider it a complex PIN/password.
-    public static final int MAX_ALLOWED_SEQUENCE = 3;
-
-    public int length = 0;
-    public int letters = 0;
-    public int upperCase = 0;
-    public int lowerCase = 0;
-    public int numeric = 0;
-    public int symbols = 0;
-    public int nonLetter = 0;
-
-    public static int maxLengthSequence(@NonNull String string) {
-        // Stub implementation
-        return 1;
-    }
-
-    public static PasswordMetrics computeForPassword(@NonNull String password) {
-        return new PasswordMetrics();
-    }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java b/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
deleted file mode 100644
index ee7bdb0..0000000
--- a/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
+++ /dev/null
@@ -1,54 +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 android.bluetooth;
-
-/**
- * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
- */
-public class BluetoothCodecConfig {
-
-    public static final int SAMPLE_RATE_NONE = 0;
-    public static final int SAMPLE_RATE_48000 = 0x1 << 1;
-    public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
-    public static final int SOURCE_CODEC_TYPE_AAC = 1;
-    public static final int CODEC_PRIORITY_DEFAULT = 0;
-    public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
-    public static final int BITS_PER_SAMPLE_NONE = 0;
-    public static final int CHANNEL_MODE_NONE = 0;
-    public static final int BITS_PER_SAMPLE_24 =  0x1 << 1;
-    public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
-
-    public int getSampleRate() {
-        return 0;
-    }
-
-    public int getCodecType() {
-        return 0;
-    }
-
-    public int getBitsPerSample() {
-        return 0;
-    }
-
-    public int getChannelMode() {
-        return 0;
-    }
-
-    public long getCodecSpecific1() {
-        return 0;
-    }
-}
diff --git a/tests/robotests/src/android/content/om/IOverlayManager.java b/tests/robotests/src/android/content/om/IOverlayManager.java
deleted file mode 100644
index 12f7f7f..0000000
--- a/tests/robotests/src/android/content/om/IOverlayManager.java
+++ /dev/null
@@ -1,36 +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 android.content.om;
-
-import android.os.IBinder;
-
-import java.util.List;
-
-public interface IOverlayManager {
-
-    OverlayInfo getOverlayInfo(String packageName, int userId);
-
-    List getOverlayInfosForTarget(String targetPackageName, int userId);
-
-    boolean setEnabled(String packageName, boolean enabled, int userId);
-
-    boolean setEnabledExclusiveInCategory(String packageName, int userId);
-
-    class Stub {
-        public static IOverlayManager asInterface(IBinder b) {
-            return null;
-        }
-    }
-}
diff --git a/tests/robotests/src/android/net/NetworkScorerAppData.java b/tests/robotests/src/android/net/NetworkScorerAppData.java
deleted file mode 100644
index f7da4d1..0000000
--- a/tests/robotests/src/android/net/NetworkScorerAppData.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package android.net;
-
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Holds metadata about a discovered network scorer/recommendation application.
- *
- * TODO: delete this class once robolectric supports Android O
- */
-public final class NetworkScorerAppData implements Parcelable {
-    /** UID of the scorer app. */
-    public final int packageUid;
-    private final ComponentName mRecommendationService;
-    /** User visible label in Settings for the recommendation service. */
-    private final String mRecommendationServiceLabel;
-    /**
-     * The {@link ComponentName} of the Activity to start before enabling the "connect to open
-     * wifi networks automatically" feature.
-     */
-    private final ComponentName mEnableUseOpenWifiActivity;
-    /**
-     * The {@link android.app.NotificationChannel} ID used by {@link #mRecommendationService} to
-     * post open network notifications.
-     */
-    private final String mNetworkAvailableNotificationChannelId;
-
-    public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
-            String recommendationServiceLabel, ComponentName enableUseOpenWifiActivity,
-            String networkAvailableNotificationChannelId) {
-        this.packageUid = packageUid;
-        this.mRecommendationService = recommendationServiceComp;
-        this.mRecommendationServiceLabel = recommendationServiceLabel;
-        this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
-        this.mNetworkAvailableNotificationChannelId = networkAvailableNotificationChannelId;
-    }
-
-    protected NetworkScorerAppData(Parcel in) {
-        packageUid = in.readInt();
-        mRecommendationService = ComponentName.readFromParcel(in);
-        mRecommendationServiceLabel = in.readString();
-        mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
-        mNetworkAvailableNotificationChannelId = in.readString();
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(packageUid);
-        ComponentName.writeToParcel(mRecommendationService, dest);
-        dest.writeString(mRecommendationServiceLabel);
-        ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
-        dest.writeString(mNetworkAvailableNotificationChannelId);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final Creator<NetworkScorerAppData> CREATOR =
-            new Creator<NetworkScorerAppData>() {
-                @Override
-                public NetworkScorerAppData createFromParcel(Parcel in) {
-                    return new NetworkScorerAppData(in);
-                }
-
-                @Override
-                public NetworkScorerAppData[] newArray(int size) {
-                    return new NetworkScorerAppData[size];
-                }
-            };
-
-    public String getRecommendationServicePackageName() {
-        return mRecommendationService.getPackageName();
-    }
-
-    public ComponentName getRecommendationServiceComponent() {
-        return mRecommendationService;
-    }
-
-    @Nullable
-    public ComponentName getEnableUseOpenWifiActivity() {
-        return mEnableUseOpenWifiActivity;
-    }
-
-    @Nullable
-    public String getRecommendationServiceLabel() {
-        return mRecommendationServiceLabel;
-    }
-
-    @Nullable
-    public String getNetworkAvailableNotificationChannelId() {
-        return mNetworkAvailableNotificationChannelId;
-    }
-
-    @Override
-    public String toString() {
-        return "NetworkScorerAppData{" +
-                "packageUid=" + packageUid +
-                ", mRecommendationService=" + mRecommendationService +
-                ", mRecommendationServiceLabel=" + mRecommendationServiceLabel +
-                ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
-                ", mNetworkAvailableNotificationChannelId=" +
-                mNetworkAvailableNotificationChannelId +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        NetworkScorerAppData that = (NetworkScorerAppData) o;
-        return packageUid == that.packageUid &&
-                Objects.equals(mRecommendationService, that.mRecommendationService) &&
-                Objects.equals(mRecommendationServiceLabel, that.mRecommendationServiceLabel) &&
-                Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity) &&
-                Objects.equals(mNetworkAvailableNotificationChannelId,
-                        that.mNetworkAvailableNotificationChannelId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(packageUid, mRecommendationService, mRecommendationServiceLabel,
-                mEnableUseOpenWifiActivity, mNetworkAvailableNotificationChannelId);
-    }
-}
diff --git a/tests/robotests/src/android/print/PrintServicesLoader.java b/tests/robotests/src/android/print/PrintServicesLoader.java
deleted file mode 100644
index e4975ed..0000000
--- a/tests/robotests/src/android/print/PrintServicesLoader.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package android.print;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.Loader;
-import android.printservice.PrintServiceInfo;
-import com.android.internal.util.Preconditions;
-
-import java.util.List;
-
-/**
- * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
- */
-public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> {
-    public PrintServicesLoader(@NonNull PrintManager printManager, @NonNull Context context,
-            int selectionFlags) {
-        super(Preconditions.checkNotNull(context));
-    }
-}
diff --git a/tests/robotests/src/com/android/internal/app/ColorDisplayController.java b/tests/robotests/src/com/android/internal/app/ColorDisplayController.java
deleted file mode 100644
index e31ba51..0000000
--- a/tests/robotests/src/com/android/internal/app/ColorDisplayController.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2016 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.internal.app;
-
-/**
- * Fake controller to make robolectric test compile. This is necessary since
- * ColorDisplayController is not part of Android's API.
- */
-public class ColorDisplayController {
-
-    public static final int AUTO_MODE_DISABLED = 0;
-    public static final int AUTO_MODE_CUSTOM = 1;
-    public static final int AUTO_MODE_TWILIGHT = 2;
-
-    public static final int COLOR_MODE_NATURAL = 0;
-    public static final int COLOR_MODE_BOOSTED = 1;
-    public static final int COLOR_MODE_SATURATED = 2;
-
-    private int mColorMode;
-
-    public void setColorMode(int colorMode) {
-        mColorMode = colorMode;
-    }
-
-    public int getColorMode() {
-        return mColorMode;
-    }
-
-    public interface Callback {
-    }
-}
diff --git a/tests/robotests/src/com/android/internal/app/LocalePickerWithRegion.java b/tests/robotests/src/com/android/internal/app/LocalePickerWithRegion.java
deleted file mode 100644
index 9edda45..0000000
--- a/tests/robotests/src/com/android/internal/app/LocalePickerWithRegion.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.android.internal.app;
-
-/**
- * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
- */
-public class LocalePickerWithRegion {
-
-    public interface LocaleSelectedListener {
-        void onLocaleSelected(LocaleStore.LocaleInfo locale);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java
index ab3e066..0a54b82 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java
@@ -22,6 +22,8 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.ResolveInfo;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
@@ -81,13 +83,26 @@
     }
 
     @Test
-    public void hasIntentHandler_shouldBeAvailable() {
+    public void hasIntentHandler_notSystemApp_shouldBeDisabled() {
         mPackageManager.addResolveInfoForIntent(TEST_INTENT, new ResolveInfo());
         mController.setPackageName(TEST_INTENT.getStringExtra(EXTRA_PACKAGE_NAME));
 
         assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
+                .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
 
+    }
+
+    @Test
+    public void hasIntentHandler_resolvedToSystemApp_shouldBeAvailable() {
+        final ResolveInfo info = new ResolveInfo();
+        info.activityInfo = new ActivityInfo();
+        info.activityInfo.applicationInfo = new ApplicationInfo();
+        info.activityInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+        mPackageManager.addResolveInfoForIntent(TEST_INTENT, info);
+        mController.setPackageName(TEST_INTENT.getStringExtra(EXTRA_PACKAGE_NAME));
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
         mController.displayPreference(mScreen);
 
         final Intent intent = mPreference.getIntent();
diff --git a/tests/robotests/src/com/android/settings/core/BasePreferenceControllerSignatureInspector.java b/tests/robotests/src/com/android/settings/core/BasePreferenceControllerSignatureInspector.java
new file mode 100644
index 0000000..a9b4f5d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/core/BasePreferenceControllerSignatureInspector.java
@@ -0,0 +1,89 @@
+/*
+ * 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.core;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.content.Context;
+
+import com.android.settings.core.codeinspection.CodeInspector;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BasePreferenceControllerSignatureInspector extends CodeInspector {
+
+    private final List<String> grandfather;
+
+    public BasePreferenceControllerSignatureInspector(List<Class<?>> classes) {
+        super(classes);
+        grandfather = new ArrayList<>();
+        initializeGrandfatherList(grandfather,
+                "grandfather_invalid_base_preference_controller_constructor");
+    }
+
+    @Override
+    public void run() {
+        StringBuilder badClasses = new StringBuilder();
+
+        for (Class c : mClasses) {
+            if (!isConcreteSettingsClass(c)) {
+                // Not a Settings class, or is abstract, don't care.
+                continue;
+            }
+            if (!BasePreferenceController.class.isAssignableFrom(c)) {
+                // Not a BasePreferenceController, don't care.
+                continue;
+            }
+            final String className = c.getName();
+            if (grandfather.remove(className)) {
+                continue;
+            }
+            final Constructor[] constructors = c.getDeclaredConstructors();
+            if (constructors == null || constructors.length == 0) {
+                badClasses.append(c.getName()).append(",");
+            }
+            for (Constructor constructor : constructors) {
+                if (!hasValidConstructorSignature(constructor)) {
+                    badClasses.append(className).append(",");
+                    continue;
+                }
+            }
+        }
+
+        assertWithMessage("All BasePreferenceController (and subclasses) constructor must either"
+                + "only take Context, or (Context, String). No other types are allowed")
+                .that(badClasses.toString())
+                .isEmpty();
+
+        assertWithMessage("Something in the grandfather list is no longer relevant. Please remove")
+                .that(grandfather)
+                .isEmpty();
+    }
+
+    private static boolean hasValidConstructorSignature(Constructor constructor) {
+        final Class[] parameterTypes = constructor.getParameterTypes();
+        if (parameterTypes.length == 1) {
+            return Context.class.isAssignableFrom(parameterTypes[0]);
+        } else if (parameterTypes.length == 2) {
+            return Context.class.isAssignableFrom(parameterTypes[0])
+                    && String.class.isAssignableFrom(parameterTypes[1]);
+        }
+        return false;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/core/codeinspection/CodeInspectionTest.java b/tests/robotests/src/com/android/settings/core/codeinspection/CodeInspectionTest.java
index 8470acb..c8ad4d6 100644
--- a/tests/robotests/src/com/android/settings/core/codeinspection/CodeInspectionTest.java
+++ b/tests/robotests/src/com/android/settings/core/codeinspection/CodeInspectionTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.android.settings.core.BasePreferenceControllerSignatureInspector;
 import com.android.settings.core.instrumentation.InstrumentableFragmentCodeInspector;
 import com.android.settings.search.SearchIndexProviderCodeInspector;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -49,6 +50,11 @@
         new InstrumentableFragmentCodeInspector(mClasses).run();
     }
 
+    @Test
+    public void runBasePreferenceControllerConstructorSignatureInspection() {
+        new BasePreferenceControllerSignatureInspector(mClasses).run();
+    }
+
     @Ignore("b/73960706")
     @Test
     public void runSearchIndexProviderCodeInspection() {
diff --git a/tests/robotests/src/com/android/settings/dashboard/conditional/RingerMutedConditionTest.java b/tests/robotests/src/com/android/settings/dashboard/conditional/RingerMutedConditionTest.java
index 13cb1c2..66ef5a0 100644
--- a/tests/robotests/src/com/android/settings/dashboard/conditional/RingerMutedConditionTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/conditional/RingerMutedConditionTest.java
@@ -22,7 +22,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.NotificationManager;
 import android.content.Context;
 import android.media.AudioManager;
 import android.provider.Settings;
@@ -59,7 +58,7 @@
         mContext = RuntimeEnvironment.application;
         mAudioManager = Shadow.extract(mContext.getSystemService(Context.AUDIO_SERVICE));
         mNotificationManager = Shadow.extract(
-                mContext.getSystemService(NotificationManager.class));
+                mContext.getSystemService(Context.NOTIFICATION_SERVICE));
         when(mConditionManager.getContext()).thenReturn(mContext);
         mCondition = spy(new RingerMutedCondition(mConditionManager));
     }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
index 0c9f313..943bd9d 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
@@ -16,14 +16,17 @@
 
 package com.android.settings.deviceinfo;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
 import android.app.usage.StorageStatsManager;
+import android.content.Intent;
 import android.icu.text.NumberFormat;
 import android.os.storage.VolumeInfo;
 import android.text.format.Formatter;
@@ -71,14 +74,14 @@
         when(volumeInfo.isMountedReadable()).thenReturn(true);
         when(volumeInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
         when(mStorageManagerVolumeProvider
-            .getTotalBytes(nullable(StorageStatsManager.class), nullable(VolumeInfo.class)))
-            .thenReturn(500L);
+                .getTotalBytes(nullable(StorageStatsManager.class), nullable(VolumeInfo.class)))
+                .thenReturn(500L);
         when(mStorageManagerVolumeProvider
-            .getFreeBytes(nullable(StorageStatsManager.class), nullable(VolumeInfo.class)))
-            .thenReturn(0L);
+                .getFreeBytes(nullable(StorageStatsManager.class), nullable(VolumeInfo.class)))
+                .thenReturn(0L);
 
         ReflectionHelpers
-            .setField(provider, "mStorageManagerVolumeProvider", mStorageManagerVolumeProvider);
+                .setField(provider, "mStorageManagerVolumeProvider", mStorageManagerVolumeProvider);
         ReflectionHelpers.setField(provider, "mContext", RuntimeEnvironment.application);
 
         provider.setListening(true);
@@ -89,4 +92,14 @@
                 RuntimeEnvironment.application.getString(
                         R.string.storage_summary, percentage, freeSpace));
     }
+
+    @Test
+    public void handlePublicVolumeClick_startsANonNullActivityWhenVolumeHasNoBrowse() {
+        VolumeInfo volumeInfo = mock(VolumeInfo.class, RETURNS_DEEP_STUBS);
+        when(volumeInfo.isMountedReadable()).thenReturn(true);
+        StorageSettings.handlePublicVolumeClick(mActivity, volumeInfo);
+
+        verify(mActivity, never()).startActivity(null);
+        verify(mActivity).startActivity(any(Intent.class));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
index d06ea2a..e1c4b70 100644
--- a/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
@@ -17,17 +17,14 @@
 package com.android.settings.display;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doReturn;
+
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.ContentResolver;
 import android.content.Context;
 import android.provider.Settings;
-import android.support.v14.preference.SwitchPreference;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.settings.search.InlinePayload;
@@ -49,8 +46,6 @@
 
     @Mock
     private AmbientDisplayConfiguration mConfig;
-    @Mock
-    private SwitchPreference mSwitchPreference;
 
     private Context mContext;
 
@@ -64,95 +59,90 @@
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         mContentResolver = mContext.getContentResolver();
-        mController = new AmbientDisplayAlwaysOnPreferenceController(mContext, mConfig,
-                () -> {
-                    mCallbackInvoked = true;
-                });
+        mController = new AmbientDisplayAlwaysOnPreferenceController(mContext, "key");
+        mController.setConfig(mConfig);
+        mController.setCallback(() -> mCallbackInvoked = true);
     }
 
     @Test
-    public void updateState_enabled() {
+    public void getAvailabilityStatus_available() {
+        when(mConfig.alwaysOnAvailableForUser(anyInt())).thenReturn(true);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                AmbientDisplayAlwaysOnPreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_disabled_unsupported() {
+        when(mConfig.alwaysOnAvailableForUser(anyInt())).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                AmbientDisplayAlwaysOnPreferenceController.DISABLED_UNSUPPORTED);
+    }
+
+    @Test
+    public void isChecked_enabled() {
         when(mConfig.alwaysOnEnabled(anyInt())).thenReturn(true);
 
-        mController.updateState(mSwitchPreference);
-
-        verify(mSwitchPreference).setChecked(true);
+        assertThat(mController.isChecked()).isTrue();
     }
 
     @Test
-    public void updateState_disabled() {
+    public void isChecked_disabled() {
         when(mConfig.alwaysOnEnabled(anyInt())).thenReturn(false);
 
-        mController.updateState(mSwitchPreference);
+        assertThat(mController.isChecked()).isFalse();
+    }
 
-        verify(mSwitchPreference).setChecked(false);
+    @Test
+    public void setChecked_enabled() {
+        mController.setChecked(true);
+
+        assertThat(Settings.Secure.getInt(mContentResolver, Settings.Secure.DOZE_ALWAYS_ON, -1))
+                .isEqualTo(1);
+    }
+
+    @Test
+    public void setChecked_disabled() {
+        mController.setChecked(false);
+
+        assertThat(Settings.Secure.getInt(mContentResolver, Settings.Secure.DOZE_ALWAYS_ON, -1))
+                .isEqualTo(0);
     }
 
     @Test
     public void onPreferenceChange_callback() {
         assertThat(mCallbackInvoked).isFalse();
-        mController.onPreferenceChange(mSwitchPreference, true);
+        mController.setChecked(true);
         assertThat(mCallbackInvoked).isTrue();
     }
 
     @Test
-    public void onPreferenceChange_enable() {
-        mController.onPreferenceChange(mSwitchPreference, true);
-
-        assertThat(Settings.Secure.getInt(mContentResolver, Settings.Secure.DOZE_ALWAYS_ON, -1))
-            .isEqualTo(1);
-    }
-
-    @Test
-    public void onPreferenceChange_disable() {
-        mController.onPreferenceChange(mSwitchPreference, false);
-
-        assertThat(Settings.Secure.getInt(mContentResolver, Settings.Secure.DOZE_ALWAYS_ON, -1))
-            .isEqualTo(0);
-    }
-
-    @Test
-    public void isAvailable_available() {
-        mController = spy(mController);
-        doReturn(true).when(mController).alwaysOnAvailableForUser(any());
-
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void isAvailable_unavailable() {
-        mController = spy(mController);
-        doReturn(false).when(mController).alwaysOnAvailableForUser(any());
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
     public void testPreferenceController_ProperResultPayloadType() {
+        when(mConfig.alwaysOnAvailableForUser(anyInt())).thenReturn(false);
         mController = spy(mController);
-        doReturn(false).when(mController).alwaysOnAvailableForUser(any());
 
         assertThat(mController.getResultPayload()).isInstanceOf(InlineSwitchPayload.class);
     }
 
     @Test
     public void testSetValue_updatesCorrectly() {
+        when(mConfig.alwaysOnAvailableForUser(anyInt())).thenReturn(false);
         mController = spy(mController);
-        doReturn(false).when(mController).alwaysOnAvailableForUser(any());
         final int newValue = 1;
         Settings.Secure.putInt(mContentResolver, Settings.Secure.DOZE_ALWAYS_ON, 0 /* value */);
 
         ((InlinePayload) mController.getResultPayload()).setValue(mContext, newValue);
         final int updatedValue = Settings.Secure.
-            getInt(mContentResolver, Settings.Secure.DOZE_ALWAYS_ON, 1 /* default */);
+                getInt(mContentResolver, Settings.Secure.DOZE_ALWAYS_ON, 1 /* default */);
 
         assertThat(updatedValue).isEqualTo(newValue);
     }
 
     @Test
     public void testGetValue_correctValueReturned() {
+        when(mConfig.alwaysOnAvailableForUser(anyInt())).thenReturn(false);
         mController = spy(mController);
-        doReturn(false).when(mController).alwaysOnAvailableForUser(any());
         final int currentValue = 1;
         Settings.Secure.putInt(mContentResolver, Settings.Secure.DOZE_ALWAYS_ON, currentValue);
 
diff --git a/tests/robotests/src/com/android/settings/display/AmbientDisplaySettingsTest.java b/tests/robotests/src/com/android/settings/display/AmbientDisplaySettingsTest.java
new file mode 100644
index 0000000..bab5d41
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/display/AmbientDisplaySettingsTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.display;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AmbientDisplaySettingsTest {
+
+    private TestFragment mTestFragment;
+
+    private Context mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mTestFragment = spy(new TestFragment());
+    }
+
+    @Test
+    public void onAttach_shouldSetConfigAndCallback() {
+        final AmbientDisplayAlwaysOnPreferenceController controller = mock(
+                AmbientDisplayAlwaysOnPreferenceController.class);
+        doReturn(controller).when(mTestFragment).use(
+                AmbientDisplayAlwaysOnPreferenceController.class);
+
+        mTestFragment.onAttach(mContext);
+
+        verify(controller).setConfig(any());
+        verify(controller).setCallback(any());
+    }
+
+    public static class TestFragment extends AmbientDisplaySettings {
+        @Override
+        protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
+            return super.use(clazz);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
index dfcd661..6b8c0f7 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
@@ -29,6 +29,8 @@
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.os.UserManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 import android.telephony.PhoneStateListener;
@@ -38,6 +40,8 @@
 import com.android.settings.testutils.shadow.ShadowConnectivityManager;
 import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsWrapper;
 import com.android.settings.testutils.shadow.ShadowUserManager;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -138,4 +142,36 @@
         // Carrier name should be set.
         verify(mPreference).setSummary(testCarrierName);
     }
+
+    @Test
+    public void airplaneModeTurnedOn_shouldDisablePreference() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+            Global.AIRPLANE_MODE_ON, 1);
+        mController = spy(new MobileNetworkPreferenceController(mContext));
+        final RestrictedPreference mPreference = new RestrictedPreference(mContext);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void airplaneModeTurnedOffAndNoUserRestriction_shouldEnablePreference() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+            Global.AIRPLANE_MODE_ON, 0);
+        mController = spy(new MobileNetworkPreferenceController(mContext));
+        final RestrictedPreference mPreference = new RestrictedPreference(mContext);
+        mPreference.setDisabledByAdmin(null);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void airplaneModeTurnedOffAndHasUserRestriction_shouldDisablePreference() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+            Global.AIRPLANE_MODE_ON, 0);
+        mController = spy(new MobileNetworkPreferenceController(mContext));
+        final RestrictedPreference mPreference = new RestrictedPreference(mContext);
+        mPreference.setDisabledByAdmin(EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
 }
diff --git a/tests/uitests/src/com/android/settings/ui/inputmethods/DataSaverSummaryUITest.java b/tests/uitests/src/com/android/settings/ui/inputmethods/DataSaverSummaryUITest.java
new file mode 100644
index 0000000..f6f5d43
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/inputmethods/DataSaverSummaryUITest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.ui.inputmethods;
+
+import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DataSaverSummaryUITest {
+
+    private Instrumentation mInstrumentation;
+    private Intent mIntent;
+    private UiDevice mUiDevice;
+
+    @Before
+    public void setUp() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mUiDevice = UiDevice.getInstance(mInstrumentation);
+        mIntent = new Intent().setClassName("com.android.settings",
+                "com.android.settings.Settings$DataUsageSummaryLegacyActivity")
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+    }
+
+    @Test
+    public void launchSettings_hasSwitchBar() throws Exception {
+        launchDataSaverSettings();
+        final UiObject2 switchBar =
+                mUiDevice.wait(Until.findObject(By.text("Use Data Saver")), TIMEOUT);
+
+        assertThat(switchBar).isNotNull();
+    }
+
+    private void launchDataSaverSettings() throws InterruptedException {
+        mInstrumentation.getContext().startActivity(mIntent);
+        final UiObject2 prefDataSaver =
+                mUiDevice.wait(Until.findObject(By.text("Data Saver")), TIMEOUT);
+
+        assertThat(prefDataSaver).isNotNull();
+        prefDataSaver.click();
+        Thread.sleep(TIMEOUT * 2);
+    }
+}