Listen to INetworkPolicyManager events and update UI accordingly.

BUG: 27481520

Change-Id: I09c4c586188d754ddd3ac3dcb3903217842ea0a5
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();
+            }
+        }
     }
 
 }