• 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.telephony.SubscriptionPlan;
27 import android.util.SparseIntArray;
28 
29 import com.android.settings.overlay.FeatureFactory;
30 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
31 import com.android.settingslib.utils.ThreadUtils;
32 
33 import java.util.ArrayList;
34 
35 public class DataSaverBackend {
36 
37     private static final String TAG = "DataSaverBackend";
38 
39     private final Context mContext;
40     private final MetricsFeatureProvider mMetricsFeatureProvider;
41 
42     private final NetworkPolicyManager mPolicyManager;
43     private final ArrayList<Listener> mListeners = new ArrayList<>();
44     private SparseIntArray mUidPolicies = new SparseIntArray();
45     private boolean mWhitelistInitialized;
46     private boolean mBlacklistInitialized;
47 
48     // TODO: Staticize into only one.
DataSaverBackend(Context context)49     public DataSaverBackend(Context context) {
50         mContext = context;
51         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
52         mPolicyManager = NetworkPolicyManager.from(context);
53     }
54 
addListener(Listener listener)55     public void addListener(Listener listener) {
56         mListeners.add(listener);
57         if (mListeners.size() == 1) {
58             mPolicyManager.registerListener(mPolicyListener);
59         }
60         listener.onDataSaverChanged(isDataSaverEnabled());
61     }
62 
remListener(Listener listener)63     public void remListener(Listener listener) {
64         mListeners.remove(listener);
65         if (mListeners.size() == 0) {
66             mPolicyManager.unregisterListener(mPolicyListener);
67         }
68     }
69 
isDataSaverEnabled()70     public boolean isDataSaverEnabled() {
71         return mPolicyManager.getRestrictBackground();
72     }
73 
setDataSaverEnabled(boolean enabled)74     public void setDataSaverEnabled(boolean enabled) {
75         mPolicyManager.setRestrictBackground(enabled);
76         mMetricsFeatureProvider.action(
77                 mContext, SettingsEnums.ACTION_DATA_SAVER_MODE, enabled ? 1 : 0);
78     }
79 
refreshWhitelist()80     public void refreshWhitelist() {
81         loadWhitelist();
82     }
83 
setIsWhitelisted(int uid, String packageName, boolean whitelisted)84     public void setIsWhitelisted(int uid, String packageName, boolean whitelisted) {
85         final int policy = whitelisted ? POLICY_ALLOW_METERED_BACKGROUND : POLICY_NONE;
86         mPolicyManager.setUidPolicy(uid, policy);
87         mUidPolicies.put(uid, policy);
88         if (whitelisted) {
89             mMetricsFeatureProvider.action(
90                     mContext, SettingsEnums.ACTION_DATA_SAVER_WHITELIST, packageName);
91         }
92     }
93 
isWhitelisted(int uid)94     public boolean isWhitelisted(int uid) {
95         loadWhitelist();
96         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_ALLOW_METERED_BACKGROUND;
97     }
98 
loadWhitelist()99     private void loadWhitelist() {
100         if (mWhitelistInitialized) {
101             return;
102         }
103 
104         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND)) {
105             mUidPolicies.put(uid, POLICY_ALLOW_METERED_BACKGROUND);
106         }
107         mWhitelistInitialized = true;
108     }
109 
refreshBlacklist()110     public void refreshBlacklist() {
111         loadBlacklist();
112     }
113 
setIsBlacklisted(int uid, String packageName, boolean blacklisted)114     public void setIsBlacklisted(int uid, String packageName, boolean blacklisted) {
115         final int policy = blacklisted ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE;
116         mPolicyManager.setUidPolicy(uid, policy);
117         mUidPolicies.put(uid, policy);
118         if (blacklisted) {
119             mMetricsFeatureProvider.action(
120                     mContext, SettingsEnums.ACTION_DATA_SAVER_BLACKLIST, packageName);
121         }
122     }
123 
isBlacklisted(int uid)124     public boolean isBlacklisted(int uid) {
125         loadBlacklist();
126         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_REJECT_METERED_BACKGROUND;
127     }
128 
loadBlacklist()129     private void loadBlacklist() {
130         if (mBlacklistInitialized) {
131             return;
132         }
133         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
134             mUidPolicies.put(uid, POLICY_REJECT_METERED_BACKGROUND);
135         }
136         mBlacklistInitialized = true;
137     }
138 
handleRestrictBackgroundChanged(boolean isDataSaving)139     private void handleRestrictBackgroundChanged(boolean isDataSaving) {
140         for (int i = 0; i < mListeners.size(); i++) {
141             mListeners.get(i).onDataSaverChanged(isDataSaving);
142         }
143     }
144 
handleWhitelistChanged(int uid, boolean isWhitelisted)145     private void handleWhitelistChanged(int uid, boolean isWhitelisted) {
146         for (int i = 0; i < mListeners.size(); i++) {
147             mListeners.get(i).onWhitelistStatusChanged(uid, isWhitelisted);
148         }
149     }
150 
handleBlacklistChanged(int uid, boolean isBlacklisted)151     private void handleBlacklistChanged(int uid, boolean isBlacklisted) {
152         for (int i = 0; i < mListeners.size(); i++) {
153             mListeners.get(i).onBlacklistStatusChanged(uid, isBlacklisted);
154         }
155     }
156 
handleUidPoliciesChanged(int uid, int newPolicy)157     private void handleUidPoliciesChanged(int uid, int newPolicy) {
158         loadWhitelist();
159         loadBlacklist();
160 
161         final int oldPolicy = mUidPolicies.get(uid, POLICY_NONE);
162         if (newPolicy == POLICY_NONE) {
163             mUidPolicies.delete(uid);
164         } else {
165             mUidPolicies.put(uid, newPolicy);
166         }
167 
168         final boolean wasWhitelisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
169         final boolean wasBlacklisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
170         final boolean isWhitelisted = newPolicy == POLICY_ALLOW_METERED_BACKGROUND;
171         final boolean isBlacklisted = newPolicy == POLICY_REJECT_METERED_BACKGROUND;
172 
173         if (wasWhitelisted != isWhitelisted) {
174             handleWhitelistChanged(uid, isWhitelisted);
175         }
176 
177         if (wasBlacklisted != isBlacklisted) {
178             handleBlacklistChanged(uid, isBlacklisted);
179         }
180 
181     }
182 
183     private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
184         @Override
185         public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
186         }
187 
188         @Override
189         public void onUidPoliciesChanged(final int uid, final int uidPolicies) {
190             ThreadUtils.postOnMainThread(() -> handleUidPoliciesChanged(uid, uidPolicies));
191         }
192 
193         @Override
194         public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
195         }
196 
197         @Override
198         public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
199             ThreadUtils.postOnMainThread(() -> handleRestrictBackgroundChanged(isDataSaving));
200         }
201 
202         @Override
203         public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
204         }
205 
206         @Override
207         public void onSubscriptionPlansChanged(int subId, SubscriptionPlan[] plans) {
208         }
209     };
210 
211     public interface Listener {
onDataSaverChanged(boolean isDataSaving)212         void onDataSaverChanged(boolean isDataSaving);
213 
onWhitelistStatusChanged(int uid, boolean isWhitelisted)214         void onWhitelistStatusChanged(int uid, boolean isWhitelisted);
215 
onBlacklistStatusChanged(int uid, boolean isBlacklisted)216         void onBlacklistStatusChanged(int uid, boolean isBlacklisted);
217     }
218 }
219