• 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.NetworkPolicyManager;
24 import android.util.SparseIntArray;
25 
26 import com.android.settings.overlay.FeatureFactory;
27 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
28 import com.android.settingslib.utils.ThreadUtils;
29 
30 import java.util.ArrayList;
31 
32 public class DataSaverBackend {
33 
34     private static final String TAG = "DataSaverBackend";
35 
36     private final Context mContext;
37     private final MetricsFeatureProvider mMetricsFeatureProvider;
38 
39     private final NetworkPolicyManager mPolicyManager;
40     private final ArrayList<Listener> mListeners = new ArrayList<>();
41     private SparseIntArray mUidPolicies = new SparseIntArray();
42     private boolean mAllowlistInitialized;
43     private boolean mDenylistInitialized;
44 
45     // TODO: Staticize into only one.
DataSaverBackend(Context context)46     public DataSaverBackend(Context context) {
47         mContext = context;
48         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
49         mPolicyManager = NetworkPolicyManager.from(context);
50     }
51 
addListener(Listener listener)52     public void addListener(Listener listener) {
53         mListeners.add(listener);
54         if (mListeners.size() == 1) {
55             mPolicyManager.registerListener(mPolicyListener);
56         }
57         listener.onDataSaverChanged(isDataSaverEnabled());
58     }
59 
remListener(Listener listener)60     public void remListener(Listener listener) {
61         mListeners.remove(listener);
62         if (mListeners.size() == 0) {
63             mPolicyManager.unregisterListener(mPolicyListener);
64         }
65     }
66 
isDataSaverEnabled()67     public boolean isDataSaverEnabled() {
68         return mPolicyManager.getRestrictBackground();
69     }
70 
setDataSaverEnabled(boolean enabled)71     public void setDataSaverEnabled(boolean enabled) {
72         mPolicyManager.setRestrictBackground(enabled);
73         mMetricsFeatureProvider.action(
74                 mContext, SettingsEnums.ACTION_DATA_SAVER_MODE, enabled ? 1 : 0);
75     }
76 
refreshAllowlist()77     public void refreshAllowlist() {
78         loadAllowlist();
79     }
80 
setIsAllowlisted(int uid, String packageName, boolean allowlisted)81     public void setIsAllowlisted(int uid, String packageName, boolean allowlisted) {
82         final int policy = allowlisted ? POLICY_ALLOW_METERED_BACKGROUND : POLICY_NONE;
83         mPolicyManager.setUidPolicy(uid, policy);
84         mUidPolicies.put(uid, policy);
85         if (allowlisted) {
86             mMetricsFeatureProvider.action(
87                     mContext, SettingsEnums.ACTION_DATA_SAVER_WHITELIST, packageName);
88         }
89     }
90 
isAllowlisted(int uid)91     public boolean isAllowlisted(int uid) {
92         loadAllowlist();
93         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_ALLOW_METERED_BACKGROUND;
94     }
95 
loadAllowlist()96     private void loadAllowlist() {
97         if (mAllowlistInitialized) {
98             return;
99         }
100 
101         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND)) {
102             mUidPolicies.put(uid, POLICY_ALLOW_METERED_BACKGROUND);
103         }
104         mAllowlistInitialized = true;
105     }
106 
refreshDenylist()107     public void refreshDenylist() {
108         loadDenylist();
109     }
110 
setIsDenylisted(int uid, String packageName, boolean denylisted)111     public void setIsDenylisted(int uid, String packageName, boolean denylisted) {
112         final int policy = denylisted ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE;
113         mPolicyManager.setUidPolicy(uid, policy);
114         mUidPolicies.put(uid, policy);
115         if (denylisted) {
116             mMetricsFeatureProvider.action(
117                     mContext, SettingsEnums.ACTION_DATA_SAVER_BLACKLIST, packageName);
118         }
119     }
120 
isDenylisted(int uid)121     public boolean isDenylisted(int uid) {
122         loadDenylist();
123         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_REJECT_METERED_BACKGROUND;
124     }
125 
loadDenylist()126     private void loadDenylist() {
127         if (mDenylistInitialized) {
128             return;
129         }
130         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
131             mUidPolicies.put(uid, POLICY_REJECT_METERED_BACKGROUND);
132         }
133         mDenylistInitialized = true;
134     }
135 
handleRestrictBackgroundChanged(boolean isDataSaving)136     private void handleRestrictBackgroundChanged(boolean isDataSaving) {
137         for (int i = 0; i < mListeners.size(); i++) {
138             mListeners.get(i).onDataSaverChanged(isDataSaving);
139         }
140     }
141 
handleAllowlistChanged(int uid, boolean isAllowlisted)142     private void handleAllowlistChanged(int uid, boolean isAllowlisted) {
143         for (int i = 0; i < mListeners.size(); i++) {
144             mListeners.get(i).onAllowlistStatusChanged(uid, isAllowlisted);
145         }
146     }
147 
handleDenylistChanged(int uid, boolean isDenylisted)148     private void handleDenylistChanged(int uid, boolean isDenylisted) {
149         for (int i = 0; i < mListeners.size(); i++) {
150             mListeners.get(i).onDenylistStatusChanged(uid, isDenylisted);
151         }
152     }
153 
handleUidPoliciesChanged(int uid, int newPolicy)154     private void handleUidPoliciesChanged(int uid, int newPolicy) {
155         loadAllowlist();
156         loadDenylist();
157 
158         final int oldPolicy = mUidPolicies.get(uid, POLICY_NONE);
159         if (newPolicy == POLICY_NONE) {
160             mUidPolicies.delete(uid);
161         } else {
162             mUidPolicies.put(uid, newPolicy);
163         }
164 
165         final boolean wasAllowlisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
166         final boolean wasDenylisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
167         final boolean isAllowlisted = newPolicy == POLICY_ALLOW_METERED_BACKGROUND;
168         final boolean isDenylisted = newPolicy == POLICY_REJECT_METERED_BACKGROUND;
169 
170         if (wasAllowlisted != isAllowlisted) {
171             handleAllowlistChanged(uid, isAllowlisted);
172         }
173 
174         if (wasDenylisted != isDenylisted) {
175             handleDenylistChanged(uid, isDenylisted);
176         }
177 
178     }
179 
180     private final NetworkPolicyManager.Listener mPolicyListener =
181             new NetworkPolicyManager.Listener() {
182         @Override
183         public void onUidPoliciesChanged(final int uid, final int uidPolicies) {
184             ThreadUtils.postOnMainThread(() -> handleUidPoliciesChanged(uid, uidPolicies));
185         }
186 
187         @Override
188         public void onRestrictBackgroundChanged(final boolean isDataSaving) {
189             ThreadUtils.postOnMainThread(() -> handleRestrictBackgroundChanged(isDataSaving));
190         }
191     };
192 
193     public interface Listener {
onDataSaverChanged(boolean isDataSaving)194         void onDataSaverChanged(boolean isDataSaving);
195 
onAllowlistStatusChanged(int uid, boolean isAllowlisted)196         void onAllowlistStatusChanged(int uid, boolean isAllowlisted);
197 
onDenylistStatusChanged(int uid, boolean isDenylisted)198         void onDenylistStatusChanged(int uid, boolean isDenylisted);
199     }
200 }
201