Merge "Remove some of the unused assets" into nyc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6637d7e..f6c7957 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1885,7 +1885,8 @@
                 android:label="@string/development_settings_title"
                 android:icon="@drawable/ic_settings_development"
                 android:taskAffinity="com.android.settings"
-                android:parentActivityName="Settings">
+                android:parentActivityName="Settings"
+                android:enabled="false">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
                 <action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3eb6d3d..e061f6e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2120,7 +2120,7 @@
     <!-- Wallpaper settings fragment title [CHAR LIMIT=30] -->
     <string name="wallpaper_settings_fragment_title">Choose wallpaper from</string>
     <!-- Display settings screen, trigger for screen saver options -->
-    <string name="screensaver_settings_title">Daydream</string>
+    <string name="screensaver_settings_title">Screen saver</string>
     <!-- Display settings screen, summary fragment for screen saver options, activated when docked or asleep and charging -->
     <string name="screensaver_settings_summary_either_long">When docked or asleep and charging</string>
     <!-- Dream settings screen, dialog option, activated when docked or asleep and charging -->
@@ -2132,9 +2132,9 @@
     <!-- Display settings screen, summary for screen saver options, screen saver is turned off -->
     <string name="screensaver_settings_summary_off">Off</string>
     <!-- Dream settings screen, caption for when dreams are disabled -->
-    <string name="screensaver_settings_disabled_prompt">To control what happens when the phone is docked and/or sleeping, turn Daydream on.</string>
+    <string name="screensaver_settings_disabled_prompt">To control what happens when the phone is docked and/or sleeping, turn screen saver on.</string>
     <!-- Dream settings screen, action label, when to dream -->
-    <string name="screensaver_settings_when_to_dream">When to daydream</string>
+    <string name="screensaver_settings_when_to_dream">When to turn screen saver on</string>
     <!-- Dream settings screen, button label to start dreaming -->
     <string name="screensaver_settings_dream_start">Start now</string>
     <!-- Dream settings screen, button label for settings for a specific screensaver -->
@@ -6059,6 +6059,15 @@
         applications in virtual reality mode.
     </string>
 
+    <!-- Title for what display preferences are applied when device is in VR mode -->
+    <string name="display_vr_pref_title">When device is in VR mode</string>
+
+    <!-- [CHAR LIMIT=70] Put display into low-persistence mode, this decreases motion blur. -->
+    <string name="display_vr_pref_low_persistence">Use low motion blur settings</string>
+
+    <!-- [CHAR LIMIT=70] Do not change display settings. -->
+    <string name="display_vr_pref_off">Do nothing</string>
+
     <!-- Sound & notification > Advanced section: Title for managing Do Not Disturb access option. [CHAR LIMIT=40] -->
     <string name="manage_zen_access_title">Do Not Disturb access</string>
 
@@ -6938,7 +6947,7 @@
     <!-- Description of allowing overlay setting [CHAR LIMIT=NONE] -->
     <string name="allow_overlay_description">This permission allows an app to display on top of other apps you\u2019re using and may interfere with your use of the interface in other applications, or change what you think you are seeing in other applications.</string>
 
-    <!-- Keyword for VR settinsg -->
+    <!-- Keyword for VR setting -->
     <string name="keywords_vr_listener">vr virtual reality listener stereo helper service</string>
     <!-- Keyword for SYSTEM_ALERT_WINDOW -->
     <string name="keywords_system_alert_window">system alert window dialog draw on top other apps</string>
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index fd2f33e..40a8569 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -15,8 +15,10 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/app_notifications_title"
-        android:key="app_notification_settings">
+        android:key="app_notification_settings"
+        settings:keywords="@string/keywords_date_and_time">
 
     <!-- Importance -->
     <!-- Block -->
@@ -24,13 +26,16 @@
             android:key="block"
             android:title="@string/app_notification_block_title"
             android:summary="@string/app_notification_block_summary"
-            android:order="2" />
+            android:order="2"
+            settings:useAdditionalSummary="true"
+            settings:restrictedSwitchSummary="@string/enabled_by_admin" />
     <!-- Silent -->
     <com.android.settingslib.RestrictedSwitchPreference
             android:key="silent"
             android:title="@string/show_silently"
             android:summary="@string/show_silently_summary"
-            android:order="3" />
+            android:order="3"
+            settings:useAdditionalSummary="true" />
     <!-- Slider -->
     <com.android.settings.notification.ImportanceSeekBarPreference
             android:key="importance"
@@ -48,6 +53,7 @@
             android:key="bypass_dnd"
             android:title="@string/app_notification_override_dnd_title"
             android:summary="@string/app_notification_override_dnd_summary"
-            android:order="6" />
+            android:order="6"
+            settings:useAdditionalSummary="true" />
 
 </PreferenceScreen>
diff --git a/res/xml/date_time_prefs.xml b/res/xml/date_time_prefs.xml
index 0aec43f..e573bbd 100644
--- a/res/xml/date_time_prefs.xml
+++ b/res/xml/date_time_prefs.xml
@@ -15,7 +15,7 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/date_and_time"
         settings:keywords="@string/keywords_date_and_time">
 
@@ -23,6 +23,8 @@
         android:title="@string/date_time_auto"
         android:summaryOn="@string/date_time_auto_summaryOn"
         android:summaryOff="@string/date_time_auto_summaryOff"
+        settings:useAdditionalSummary="true"
+        settings:restrictedSwitchSummary="@string/enabled_by_admin"
         />
 
     <SwitchPreference android:key="auto_zone"
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index e737ba8..6d1a9fc 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -15,6 +15,7 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/development_settings_title">
     <com.android.settings.BugreportPreference
             android:key="bugreport"
@@ -32,10 +33,11 @@
                 android:targetClass="com.android.settings.SetFullBackupPassword" />
     </PreferenceScreen>
 
-    <SwitchPreference
+    <com.android.settingslib.RestrictedSwitchPreference
         android:key="keep_screen_on"
         android:title="@string/keep_screen_on"
-        android:summary="@string/keep_screen_on_summary"/>
+        android:summary="@string/keep_screen_on_summary"
+        settings:useAdditionalSummary="true" />
 
     <ListPreference
         android:key="hdcp_checking"
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 54b17d3..816f27b 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -106,4 +106,9 @@
                 settings:keywords="@string/keywords_display_cast_screen"
                 android:fragment="com.android.settings.wfd.WifiDisplaySettings" />
 
+        <DropDownPreference
+                android:key="vr_display_pref"
+                android:summary="%s"
+                android:title="@string/display_vr_pref_title" />
+
 </PreferenceScreen>
diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java
index 90c1d38..3ed3e82 100644
--- a/src/com/android/settings/DateTimeSettings.java
+++ b/src/com/android/settings/DateTimeSettings.java
@@ -27,8 +27,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
@@ -68,6 +66,9 @@
     // have we been launched from the setup wizard?
     protected static final String EXTRA_IS_FIRST_RUN = "firstRun";
 
+    // Minimum time is Nov 5, 2007, 0:00.
+    private static final long MIN_DATE = 1194220800000L;
+
     private RestrictedSwitchPreference mAutoTimePref;
     private Preference mTimePref;
     private Preference mTime24Pref;
@@ -320,7 +321,7 @@
         c.set(Calendar.YEAR, year);
         c.set(Calendar.MONTH, month);
         c.set(Calendar.DAY_OF_MONTH, day);
-        long when = c.getTimeInMillis();
+        long when = Math.max(c.getTimeInMillis(), MIN_DATE);
 
         if (when / 1000 < Integer.MAX_VALUE) {
             ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when);
@@ -334,7 +335,7 @@
         c.set(Calendar.MINUTE, minute);
         c.set(Calendar.SECOND, 0);
         c.set(Calendar.MILLISECOND, 0);
-        long when = c.getTimeInMillis();
+        long when = Math.max(c.getTimeInMillis(), MIN_DATE);
 
         if (when / 1000 < Integer.MAX_VALUE) {
             ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when);
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 1551bcf..5036b9f 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -84,6 +84,9 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.widget.SwitchBar;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedSwitchPreference;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -232,7 +235,7 @@
     private SwitchPreference mEnableTerminal;
     private Preference mBugreport;
     private SwitchPreference mBugreportInPower;
-    private SwitchPreference mKeepScreenOn;
+    private RestrictedSwitchPreference mKeepScreenOn;
     private SwitchPreference mBtHciSnoopLog;
     private SwitchPreference mEnableOemUnlock;
     private SwitchPreference mDebugViewAttributes;
@@ -364,7 +367,7 @@
 
         mBugreport = findPreference(BUGREPORT);
         mBugreportInPower = findAndInitSwitchPref(BUGREPORT_IN_POWER_KEY);
-        mKeepScreenOn = findAndInitSwitchPref(KEEP_SCREEN_ON);
+        mKeepScreenOn = (RestrictedSwitchPreference) findAndInitSwitchPref(KEEP_SCREEN_ON);
         mBtHciSnoopLog = findAndInitSwitchPref(BT_HCI_SNOOP_LOG);
         mEnableOemUnlock = findAndInitSwitchPref(ENABLE_OEM_UNLOCK);
         if (!showEnableOemUnlockPreference()) {
@@ -562,14 +565,17 @@
             return;
         }
 
-        if (mDpm.getMaximumTimeToLockForUserAndProfiles(UserHandle.myUserId()) > 0) {
-            // A DeviceAdmin has specified a maximum time until the device
-            // will lock...  in this case we can't allow the user to turn
-            // on "stay awake when plugged in" because that would defeat the
-            // restriction.
-            mDisabledPrefs.add(mKeepScreenOn);
-        } else {
+        // A DeviceAdmin has specified a maximum time until the device
+        // will lock...  in this case we can't allow the user to turn
+        // on "stay awake when plugged in" because that would defeat the
+        // restriction.
+        final EnforcedAdmin admin = RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
+                getActivity());
+        mKeepScreenOn.setDisabledByAdmin(admin);
+        if (admin == null) {
             mDisabledPrefs.remove(mKeepScreenOn);
+        } else {
+            mDisabledPrefs.add(mKeepScreenOn);
         }
 
         final ContentResolver cr = getActivity().getContentResolver();
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 95b2879..8e389a9 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -17,12 +17,14 @@
 package com.android.settings;
 
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.UiModeManager;
 import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.ComponentName;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.hardware.Sensor;
@@ -87,6 +89,7 @@
     private static final String KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE
             = "camera_double_tap_power_gesture";
     private static final String KEY_WALLPAPER = "wallpaper";
+    private static final String KEY_VR_DISPLAY_PREF = "vr_display_pref";
 
     private Preference mFontSizePref;
 
@@ -207,6 +210,40 @@
             removePreference(KEY_AUTO_ROTATE);
         }
 
+        if (isVrDisplayModeAvailable(activity)) {
+            DropDownPreference vrDisplayPref =
+                    (DropDownPreference) findPreference(KEY_VR_DISPLAY_PREF);
+            vrDisplayPref.setEntries(new CharSequence[] {
+                    activity.getString(R.string.display_vr_pref_low_persistence),
+                    activity.getString(R.string.display_vr_pref_off),
+            });
+            vrDisplayPref.setEntryValues(new CharSequence[] { "0", "1" });
+
+            final Context c = activity;
+            int currentUser = ActivityManager.getCurrentUser();
+            int current = Settings.Secure.getIntForUser(c.getContentResolver(),
+                            Settings.Secure.VR_DISPLAY_MODE,
+                            /*default*/Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE,
+                            currentUser);
+            vrDisplayPref.setValueIndex(current);
+            vrDisplayPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+                @Override
+                public boolean onPreferenceChange(Preference preference, Object newValue) {
+                    int i = Integer.parseInt((String) newValue);
+                    int u = ActivityManager.getCurrentUser();
+                    if (!Settings.Secure.putIntForUser(c.getContentResolver(),
+                            Settings.Secure.VR_DISPLAY_MODE,
+                            i, u)) {
+                        Log.e(TAG, "Could not change setting for " +
+                                Settings.Secure.VR_DISPLAY_MODE);
+                    }
+                    return true;
+                }
+            });
+        } else {
+            removePreference(KEY_VR_DISPLAY_PREF);
+        }
+
         mNightModePreference = (ListPreference) findPreference(KEY_NIGHT_MODE);
         if (mNightModePreference != null) {
             final UiModeManager uiManager = (UiModeManager) getSystemService(
@@ -256,6 +293,11 @@
                 com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
     }
 
+    private static boolean isVrDisplayModeAvailable(Context context) {
+        PackageManager pm = context.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
+    }
+
     private void updateTimeoutPreferenceDescription(long currentTimeout) {
         TimeoutListPreference preference = mScreenTimeoutPreference;
         String summary;
@@ -515,6 +557,9 @@
                     if (!isCameraDoubleTapPowerGestureAvailable(context.getResources())) {
                         result.add(KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE);
                     }
+                    if (!isVrDisplayModeAvailable(context)) {
+                        result.add(KEY_VR_DISPLAY_PREF);
+                    }
                     return result;
                 }
             };
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 53c97b5..616fe39 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -1096,8 +1096,7 @@
             enabled = false;
         }
         int state = pm.getComponentEnabledSetting(component);
-        boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
-                || state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+        boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
         if (isEnabled != enabled) {
             pm.setComponentEnabledSetting(component, enabled
                     ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java
index 55d97df..780d68e 100644
--- a/src/com/android/settings/dashboard/SummaryLoader.java
+++ b/src/com/android/settings/dashboard/SummaryLoader.java
@@ -16,8 +16,14 @@
 package com.android.settings.dashboard;
 
 import android.app.Activity;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.os.*;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
 import android.os.Process;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -45,6 +51,7 @@
 
     private DashboardAdapter mAdapter;
     private boolean mListening;
+    private ArrayList<BroadcastReceiver> mReceivers = new ArrayList<>();
 
     public SummaryLoader(Activity activity, List<DashboardCategory> categories) {
         mHandler = new Handler();
@@ -88,6 +95,14 @@
     }
 
     public void setListening(boolean listening) {
+        synchronized (mReceivers) {
+            // Unregister listeners immediately.
+            mListening = false;
+            for (int i = 0; i < mReceivers.size(); i++) {
+                mActivity.unregisterReceiver(mReceivers.get(i));
+            }
+            mReceivers.clear();
+        }
         mWorker.obtainMessage(Worker.MSG_SET_LISTENING, listening ? 1 : 0, 0).sendToTarget();
     }
 
@@ -128,13 +143,28 @@
         return tile.metaData;
     }
 
+    /**
+     * Registers a receiver and automatically unregisters it when the activity is stopping.
+     * This ensures that the receivers are unregistered immediately, since most summary loader
+     * operations are asynchronous.
+     */
+    public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+        synchronized (mReceivers) {
+            if (!mListening) {
+                return;
+            }
+            mReceivers.add(receiver);
+            mActivity.registerReceiver(receiver, filter);
+        }
+    }
+
     private synchronized void setListeningW(boolean listening) {
         if (mListening == listening) return;
         if (DEBUG) Log.d(TAG, "Listening " + listening);
+        mListening = listening;
         for (SummaryProvider p : mSummaryMap.keySet()) {
             p.setListening(listening);
         }
-        mListening = listening;
     }
 
     private synchronized void makeProviderW(Tile tile) {
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 037614e..0bd0615 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -54,7 +54,8 @@
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
 
-public class AppDataUsage extends DataUsageBase implements Preference.OnPreferenceChangeListener {
+public class AppDataUsage extends DataUsageBase implements Preference.OnPreferenceChangeListener,
+        DataSaverBackend.Listener {
 
     public static final String ARG_APP_ITEM = "app_item";
     public static final String ARG_NETWORK_TEMPLATE = "network_template";
@@ -207,6 +208,7 @@
     @Override
     public void onResume() {
         super.onResume();
+        mDataSaverBackend.addListener(this);
         mPolicy = services.mPolicyEditor.getPolicy(mTemplate);
         getLoaderManager().restartLoader(LOADER_CHART_DATA,
                 ChartDataLoader.buildArgs(mTemplate, mAppItem), mChartDataCallbacks);
@@ -214,10 +216,15 @@
     }
 
     @Override
+    public void onPause() {
+        super.onPause();
+        mDataSaverBackend.remListener(this);
+    }
+
+    @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         if (preference == mRestrictBackground) {
             mDataSaverBackend.setIsBlacklisted(mAppItem.key, mPackageName, !(Boolean) newValue);
-            updatePrefs();        // TODO: should have been notified by NPMS instead
             return true;
         } else if (preference == mUnrestrictedData) {
             mDataSaverBackend.setIsWhitelisted(mAppItem.key, mPackageName, (Boolean) newValue);
@@ -238,15 +245,19 @@
     }
 
     private void updatePrefs() {
+        updatePrefs(getAppRestrictBackground(), getUnrestrictData());
+    }
+
+    private void updatePrefs(boolean restrictBackground, boolean unrestrictData) {
         if (mRestrictBackground != null) {
-            mRestrictBackground.setChecked(!getAppRestrictBackground());
+            mRestrictBackground.setChecked(!restrictBackground);
         }
         if (mUnrestrictedData != null) {
-            if (getAppRestrictBackground()) {
+            if (restrictBackground) {
                 mUnrestrictedData.setVisible(false);
             } else {
                 mUnrestrictedData.setVisible(true);
-                mUnrestrictedData.setChecked(mDataSaverBackend.isWhitelisted(mAppItem.key));
+                mUnrestrictedData.setChecked(unrestrictData);
             }
         }
     }
@@ -288,6 +299,10 @@
         return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
     }
 
+    private boolean getUnrestrictData() {
+        return mDataSaverBackend.isWhitelisted(mAppItem.key);
+    }
+
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
@@ -368,4 +383,23 @@
             }
         }
     }
+
+    @Override
+    public void onDataSaverChanged(boolean isDataSaving) {
+
+    }
+
+    @Override
+    public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
+        if (mAppItem.uids.get(uid, false)) {
+            updatePrefs(getAppRestrictBackground(), isWhitelisted);
+        }
+    }
+
+    @Override
+    public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
+        if (mAppItem.uids.get(uid, false)) {
+            updatePrefs(isBlacklisted, getUnrestrictData());
+        }
+    }
 }
diff --git a/src/com/android/settings/datausage/DataSaverBackend.java b/src/com/android/settings/datausage/DataSaverBackend.java
index 55521a8..eb62ad7 100644
--- a/src/com/android/settings/datausage/DataSaverBackend.java
+++ b/src/com/android/settings/datausage/DataSaverBackend.java
@@ -160,10 +160,46 @@
         }
     }
 
+    private void handleWhitelistChanged(int uid, boolean isWhitelisted) {
+        for (int i = 0; i < mListeners.size(); i++) {
+            mListeners.get(i).onWhitelistStatusChanged(uid, isWhitelisted);
+        }
+    }
+
+    private void handleBlacklistChanged(int uid, boolean isBlacklisted) {
+        for (int i = 0; i < mListeners.size(); i++) {
+            mListeners.get(i).onBlacklistStatusChanged(uid, isBlacklisted);
+        }
+    }
+
     private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
         @Override
-        public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
-            // TODO: update UI accordingly
+        public void onUidRulesChanged(final int uid, int uidRules) throws RemoteException {
+            if (mBlacklist == null) {
+                loadBlacklist();
+            }
+            final boolean isBlacklisted = uidRules == POLICY_REJECT_METERED_BACKGROUND;
+            mBlacklist.put(uid, isBlacklisted);
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    handleBlacklistChanged(uid, isBlacklisted);
+                }
+            });
+        }
+
+        @Override
+        public void onRestrictBackgroundWhitelistChanged(final int uid, final boolean whitelisted) {
+            if (mWhitelist == null) {
+                loadWhitelist();
+            }
+            mWhitelist.put(uid, whitelisted);
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    handleWhitelistChanged(uid, whitelisted);
+                }
+            });
         }
 
         @Override
@@ -183,5 +219,7 @@
 
     public interface Listener {
         void onDataSaverChanged(boolean isDataSaving);
+        void onWhitelistStatusChanged(int uid, boolean isWhitelisted);
+        void onBlacklistStatusChanged(int uid, boolean isBlacklisted);
     }
 }
diff --git a/src/com/android/settings/datausage/DataSaverPreference.java b/src/com/android/settings/datausage/DataSaverPreference.java
index c286d95..13ef9d7 100644
--- a/src/com/android/settings/datausage/DataSaverPreference.java
+++ b/src/com/android/settings/datausage/DataSaverPreference.java
@@ -44,4 +44,12 @@
     public void onDataSaverChanged(boolean isDataSaving) {
         setSummary(isDataSaving ? R.string.data_saver_on : R.string.data_saver_off);
     }
+
+    @Override
+    public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
+    }
+
+    @Override
+    public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
+    }
 }
diff --git a/src/com/android/settings/datausage/DataSaverSummary.java b/src/com/android/settings/datausage/DataSaverSummary.java
index 591f2c5..8dfbad5 100644
--- a/src/com/android/settings/datausage/DataSaverSummary.java
+++ b/src/com/android/settings/datausage/DataSaverSummary.java
@@ -100,6 +100,14 @@
     }
 
     @Override
+    public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
+    }
+
+    @Override
+    public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
+    }
+
+    @Override
     public void onExtraInfoUpdated() {
         if (!isAdded()) {
             return;
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccess.java b/src/com/android/settings/datausage/UnrestrictedDataAccess.java
index 650b0b2..740fe06 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccess.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccess.java
@@ -41,7 +41,8 @@
 import java.util.ArrayList;
 
 public class UnrestrictedDataAccess extends SettingsPreferenceFragment
-        implements ApplicationsState.Callbacks, AppStateBaseBridge.Callback, Preference.OnPreferenceChangeListener {
+        implements ApplicationsState.Callbacks, AppStateBaseBridge.Callback,
+        Preference.OnPreferenceChangeListener {
 
     private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 42;
     private static final String EXTRA_SHOW_SYSTEM = "show_system";
@@ -214,7 +215,7 @@
         return false;
     }
 
-    private class AccessPreference extends SwitchPreference {
+    private class AccessPreference extends SwitchPreference implements DataSaverBackend.Listener {
         private final AppEntry mEntry;
         private final DataUsageState mState;
 
@@ -230,6 +231,18 @@
         }
 
         @Override
+        public void onAttached() {
+            super.onAttached();
+            mDataSaverBackend.addListener(this);
+        }
+
+        @Override
+        public void onDetached() {
+            mDataSaverBackend.remListener(this);
+            super.onDetached();
+        }
+
+        @Override
         protected void onClick() {
             if (mState.isDataSaverBlacklisted) {
                 // app is blacklisted, launch App Data Usage screen
@@ -246,17 +259,13 @@
         // Sets UI state based on whitelist/blacklist status.
         private void setState() {
             setTitle(mEntry.label);
-            // TODO: state is cached, so if blacklist/whitelist changes, it's not updated.
-            // For example, if the initial state is blacklisted, the user taps the preference,
-            // removes the blacklist, and then taps back, the state is not refreshed.
-            // The proper fix for this problem is to implement onUidRulesChanged() on
-            // DataSaverBackend and update the UI accordingly.
             if (mState != null) {
                 setChecked(mState.isDataSaverWhitelisted);
                 if (mState.isDataSaverBlacklisted) {
                     setSummary(R.string.restrict_background_blacklisted);
+                } else {
+                    setSummary("");
                 }
-                // TODO: might need to reset summary once it listens to onUidRulesChanged()
             }
         }
 
@@ -280,9 +289,30 @@
                 });
             }
             holder.findViewById(android.R.id.widget_frame)
-                    .setVisibility(mState.isDataSaverBlacklisted ? View.INVISIBLE : View.VISIBLE);
+                    .setVisibility(mState != null && mState.isDataSaverBlacklisted
+                            ? View.INVISIBLE : View.VISIBLE);
             super.onBindViewHolder(holder);
         }
+
+        @Override
+        public void onDataSaverChanged(boolean isDataSaving) {
+        }
+
+        @Override
+        public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
+            if (mState != null && mEntry.info.uid == uid) {
+                mState.isDataSaverWhitelisted = isWhitelisted;
+                reuse();
+            }
+        }
+
+        @Override
+        public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
+            if (mState != null && mEntry.info.uid == uid) {
+                mState.isDataSaverBlacklisted = isBlacklisted;
+                reuse();
+            }
+        }
     }
 
 }
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
index 5f5975d..66026eb 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
@@ -326,6 +326,12 @@
     }
 
     @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mDetached = false;
+    }
+
+    @Override
     public void onDetach() {
         super.onDetach();
         mDetached = true;
diff --git a/src/com/android/settings/deviceinfo/SimStatus.java b/src/com/android/settings/deviceinfo/SimStatus.java
index 80dfc58..0acad37 100644
--- a/src/com/android/settings/deviceinfo/SimStatus.java
+++ b/src/com/android/settings/deviceinfo/SimStatus.java
@@ -151,7 +151,7 @@
             mSir = mSelectableSubInfos.size() > 0 ? mSelectableSubInfos.get(0) : null;
 
             if (mSelectableSubInfos.size() > 1) {
-                setContentView(com.android.internal.R.layout.common_tab_settings);
+                setContentView(R.layout.icc_lock_tabs);
 
                 mTabHost = (TabHost) findViewById(android.R.id.tabhost);
                 mTabWidget = (TabWidget) findViewById(android.R.id.tabs);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 08e27ec..8eb1759 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -28,7 +28,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
@@ -39,15 +38,12 @@
 import android.os.Bundle;
 import android.os.HandlerThread;
 import android.os.Process;
-import android.os.RemoteException;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.text.Spannable;
 import android.text.style.TextAppearanceSpan;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.Menu;
@@ -58,7 +54,6 @@
 import android.widget.TextView;
 import android.widget.TextView.BufferType;
 import android.widget.Toast;
-
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settings.LinkifyUtils;
@@ -999,9 +994,7 @@
                 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
                 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
                 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
-                mContext.registerReceiver(this, filter);
-            } else {
-                mContext.unregisterReceiver(this);
+                mSummaryLoader.registerReceiver(this, filter);
             }
         }