• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.settings.datausage;
16 
17 import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
18 import static android.net.NetworkPolicyManager.POLICY_NONE;
19 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
20 
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.net.INetworkPolicyListener;
24 import android.net.NetworkPolicyManager;
25 import android.os.RemoteException;
26 import android.util.SparseIntArray;
27 
28 import com.android.settings.overlay.FeatureFactory;
29 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
30 import com.android.settingslib.utils.ThreadUtils;
31 
32 import java.util.ArrayList;
33 
34 public class DataSaverBackend {
35 
36     private static final String TAG = "DataSaverBackend";
37 
38     private final Context mContext;
39     private final MetricsFeatureProvider mMetricsFeatureProvider;
40 
41     private final NetworkPolicyManager mPolicyManager;
42     private final ArrayList<Listener> mListeners = new ArrayList<>();
43     private SparseIntArray mUidPolicies = new SparseIntArray();
44     private boolean mWhitelistInitialized;
45     private boolean mBlacklistInitialized;
46 
47     // TODO: Staticize into only one.
DataSaverBackend(Context context)48     public DataSaverBackend(Context context) {
49         mContext = context;
50         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
51         mPolicyManager = NetworkPolicyManager.from(context);
52     }
53 
addListener(Listener listener)54     public void addListener(Listener listener) {
55         mListeners.add(listener);
56         if (mListeners.size() == 1) {
57             mPolicyManager.registerListener(mPolicyListener);
58         }
59         listener.onDataSaverChanged(isDataSaverEnabled());
60     }
61 
remListener(Listener listener)62     public void remListener(Listener listener) {
63         mListeners.remove(listener);
64         if (mListeners.size() == 0) {
65             mPolicyManager.unregisterListener(mPolicyListener);
66         }
67     }
68 
isDataSaverEnabled()69     public boolean isDataSaverEnabled() {
70         return mPolicyManager.getRestrictBackground();
71     }
72 
setDataSaverEnabled(boolean enabled)73     public void setDataSaverEnabled(boolean enabled) {
74         mPolicyManager.setRestrictBackground(enabled);
75         mMetricsFeatureProvider.action(
76                 mContext, SettingsEnums.ACTION_DATA_SAVER_MODE, enabled ? 1 : 0);
77     }
78 
refreshWhitelist()79     public void refreshWhitelist() {
80         loadWhitelist();
81     }
82 
setIsWhitelisted(int uid, String packageName, boolean whitelisted)83     public void setIsWhitelisted(int uid, String packageName, boolean whitelisted) {
84         final int policy = whitelisted ? POLICY_ALLOW_METERED_BACKGROUND : POLICY_NONE;
85         mPolicyManager.setUidPolicy(uid, policy);
86         mUidPolicies.put(uid, policy);
87         if (whitelisted) {
88             mMetricsFeatureProvider.action(
89                     mContext, SettingsEnums.ACTION_DATA_SAVER_WHITELIST, packageName);
90         }
91     }
92 
isWhitelisted(int uid)93     public boolean isWhitelisted(int uid) {
94         loadWhitelist();
95         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_ALLOW_METERED_BACKGROUND;
96     }
97 
loadWhitelist()98     private void loadWhitelist() {
99         if (mWhitelistInitialized) {
100             return;
101         }
102 
103         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND)) {
104             mUidPolicies.put(uid, POLICY_ALLOW_METERED_BACKGROUND);
105         }
106         mWhitelistInitialized = true;
107     }
108 
refreshBlacklist()109     public void refreshBlacklist() {
110         loadBlacklist();
111     }
112 
setIsBlacklisted(int uid, String packageName, boolean blacklisted)113     public void setIsBlacklisted(int uid, String packageName, boolean blacklisted) {
114         final int policy = blacklisted ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE;
115         mPolicyManager.setUidPolicy(uid, policy);
116         mUidPolicies.put(uid, policy);
117         if (blacklisted) {
118             mMetricsFeatureProvider.action(
119                     mContext, SettingsEnums.ACTION_DATA_SAVER_BLACKLIST, packageName);
120         }
121     }
122 
isBlacklisted(int uid)123     public boolean isBlacklisted(int uid) {
124         loadBlacklist();
125         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_REJECT_METERED_BACKGROUND;
126     }
127 
loadBlacklist()128     private void loadBlacklist() {
129         if (mBlacklistInitialized) {
130             return;
131         }
132         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
133             mUidPolicies.put(uid, POLICY_REJECT_METERED_BACKGROUND);
134         }
135         mBlacklistInitialized = true;
136     }
137 
handleRestrictBackgroundChanged(boolean isDataSaving)138     private void handleRestrictBackgroundChanged(boolean isDataSaving) {
139         for (int i = 0; i < mListeners.size(); i++) {
140             mListeners.get(i).onDataSaverChanged(isDataSaving);
141         }
142     }
143 
handleWhitelistChanged(int uid, boolean isWhitelisted)144     private void handleWhitelistChanged(int uid, boolean isWhitelisted) {
145         for (int i = 0; i < mListeners.size(); i++) {
146             mListeners.get(i).onWhitelistStatusChanged(uid, isWhitelisted);
147         }
148     }
149 
handleBlacklistChanged(int uid, boolean isBlacklisted)150     private void handleBlacklistChanged(int uid, boolean isBlacklisted) {
151         for (int i = 0; i < mListeners.size(); i++) {
152             mListeners.get(i).onBlacklistStatusChanged(uid, isBlacklisted);
153         }
154     }
155 
handleUidPoliciesChanged(int uid, int newPolicy)156     private void handleUidPoliciesChanged(int uid, int newPolicy) {
157         loadWhitelist();
158         loadBlacklist();
159 
160         final int oldPolicy = mUidPolicies.get(uid, POLICY_NONE);
161         if (newPolicy == POLICY_NONE) {
162             mUidPolicies.delete(uid);
163         } else {
164             mUidPolicies.put(uid, newPolicy);
165         }
166 
167         final boolean wasWhitelisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
168         final boolean wasBlacklisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
169         final boolean isWhitelisted = newPolicy == POLICY_ALLOW_METERED_BACKGROUND;
170         final boolean isBlacklisted = newPolicy == POLICY_REJECT_METERED_BACKGROUND;
171 
172         if (wasWhitelisted != isWhitelisted) {
173             handleWhitelistChanged(uid, isWhitelisted);
174         }
175 
176         if (wasBlacklisted != isBlacklisted) {
177             handleBlacklistChanged(uid, isBlacklisted);
178         }
179 
180     }
181 
182     private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
183         @Override
184         public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
185         }
186 
187         @Override
188         public void onUidPoliciesChanged(final int uid, final int uidPolicies) {
189             ThreadUtils.postOnMainThread(() -> handleUidPoliciesChanged(uid, uidPolicies));
190         }
191 
192         @Override
193         public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
194         }
195 
196         @Override
197         public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
198             ThreadUtils.postOnMainThread(() -> handleRestrictBackgroundChanged(isDataSaving));
199         }
200 
201         @Override
202         public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
203         }
204     };
205 
206     public interface Listener {
onDataSaverChanged(boolean isDataSaving)207         void onDataSaverChanged(boolean isDataSaving);
208 
onWhitelistStatusChanged(int uid, boolean isWhitelisted)209         void onWhitelistStatusChanged(int uid, boolean isWhitelisted);
210 
onBlacklistStatusChanged(int uid, boolean isBlacklisted)211         void onBlacklistStatusChanged(int uid, boolean isBlacklisted);
212     }
213 }
214