• 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.content.Context;
22 import android.net.INetworkPolicyListener;
23 import android.net.NetworkPolicyManager;
24 import android.os.RemoteException;
25 import android.util.SparseIntArray;
26 
27 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
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, MetricsEvent.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, MetricsEvent.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 
getWhitelistedCount()98     public int getWhitelistedCount() {
99         int count = 0;
100         loadWhitelist();
101         for (int i = 0; i < mUidPolicies.size(); i++) {
102             if (mUidPolicies.valueAt(i) == POLICY_ALLOW_METERED_BACKGROUND) {
103                 count++;
104             }
105         }
106         return count;
107     }
108 
loadWhitelist()109     private void loadWhitelist() {
110         if (mWhitelistInitialized) return;
111 
112         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND)) {
113             mUidPolicies.put(uid, POLICY_ALLOW_METERED_BACKGROUND);
114         }
115         mWhitelistInitialized = true;
116     }
117 
refreshBlacklist()118     public void refreshBlacklist() {
119         loadBlacklist();
120     }
121 
setIsBlacklisted(int uid, String packageName, boolean blacklisted)122     public void setIsBlacklisted(int uid, String packageName, boolean blacklisted) {
123         final int policy = blacklisted ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE;
124         mPolicyManager.setUidPolicy(uid, policy);
125         mUidPolicies.put(uid, policy);
126         if (blacklisted) {
127             mMetricsFeatureProvider.action(
128                     mContext, MetricsEvent.ACTION_DATA_SAVER_BLACKLIST, packageName);
129         }
130     }
131 
isBlacklisted(int uid)132     public boolean isBlacklisted(int uid) {
133         loadBlacklist();
134         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_REJECT_METERED_BACKGROUND;
135     }
136 
loadBlacklist()137     private void loadBlacklist() {
138         if (mBlacklistInitialized) return;
139         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
140             mUidPolicies.put(uid, POLICY_REJECT_METERED_BACKGROUND);
141         }
142         mBlacklistInitialized = true;
143     }
144 
handleRestrictBackgroundChanged(boolean isDataSaving)145     private void handleRestrictBackgroundChanged(boolean isDataSaving) {
146         for (int i = 0; i < mListeners.size(); i++) {
147             mListeners.get(i).onDataSaverChanged(isDataSaving);
148         }
149     }
150 
handleWhitelistChanged(int uid, boolean isWhitelisted)151     private void handleWhitelistChanged(int uid, boolean isWhitelisted) {
152         for (int i = 0; i < mListeners.size(); i++) {
153             mListeners.get(i).onWhitelistStatusChanged(uid, isWhitelisted);
154         }
155     }
156 
handleBlacklistChanged(int uid, boolean isBlacklisted)157     private void handleBlacklistChanged(int uid, boolean isBlacklisted) {
158         for (int i = 0; i < mListeners.size(); i++) {
159             mListeners.get(i).onBlacklistStatusChanged(uid, isBlacklisted);
160         }
161     }
162 
handleUidPoliciesChanged(int uid, int newPolicy)163     private void handleUidPoliciesChanged(int uid, int newPolicy) {
164         loadWhitelist();
165         loadBlacklist();
166 
167         final int oldPolicy = mUidPolicies.get(uid, POLICY_NONE);
168         if (newPolicy == POLICY_NONE) {
169             mUidPolicies.delete(uid);
170         } else {
171             mUidPolicies.put(uid, newPolicy);
172         }
173 
174         final boolean wasWhitelisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
175         final boolean wasBlacklisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
176         final boolean isWhitelisted = newPolicy == POLICY_ALLOW_METERED_BACKGROUND;
177         final boolean isBlacklisted = newPolicy == POLICY_REJECT_METERED_BACKGROUND;
178 
179         if (wasWhitelisted != isWhitelisted) {
180             handleWhitelistChanged(uid, isWhitelisted);
181         }
182 
183         if (wasBlacklisted != isBlacklisted) {
184             handleBlacklistChanged(uid, isBlacklisted);
185         }
186 
187     }
188 
189     private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
190         @Override
191         public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
192         }
193 
194         @Override
195         public void onUidPoliciesChanged(final int uid, final int uidPolicies) {
196             ThreadUtils.postOnMainThread(() -> handleUidPoliciesChanged(uid, uidPolicies));
197         }
198 
199         @Override
200         public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
201         }
202 
203         @Override
204         public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
205             ThreadUtils.postOnMainThread(() -> handleRestrictBackgroundChanged(isDataSaving));
206         }
207 
208         @Override
209         public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
210         }
211     };
212 
213     public interface Listener {
onDataSaverChanged(boolean isDataSaving)214         void onDataSaverChanged(boolean isDataSaving);
onWhitelistStatusChanged(int uid, boolean isWhitelisted)215         void onWhitelistStatusChanged(int uid, boolean isWhitelisted);
onBlacklistStatusChanged(int uid, boolean isBlacklisted)216         void onBlacklistStatusChanged(int uid, boolean isBlacklisted);
217     }
218 }
219