1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.net;
18 
19 import static android.net.NetworkPolicy.CYCLE_NONE;
20 import static android.net.NetworkPolicy.LIMIT_DISABLED;
21 import static android.net.NetworkPolicy.SNOOZE_NEVER;
22 import static android.net.NetworkPolicy.WARNING_DISABLED;
23 import static android.net.NetworkTemplate.MATCH_WIFI;
24 import static com.android.internal.util.Preconditions.checkNotNull;
25 
26 import android.net.NetworkPolicy;
27 import android.net.NetworkPolicyManager;
28 import android.net.NetworkTemplate;
29 import android.net.wifi.WifiInfo;
30 import android.os.AsyncTask;
31 import android.text.TextUtils;
32 import android.text.format.Time;
33 
34 import com.google.android.collect.Lists;
35 
36 import java.util.ArrayList;
37 
38 /**
39  * Utility class to modify list of {@link NetworkPolicy}. Specifically knows
40  * about which policies can coexist. This editor offers thread safety when
41  * talking with {@link NetworkPolicyManager}.
42  */
43 public class NetworkPolicyEditor {
44     // TODO: be more robust when missing policies from service
45 
46     public static final boolean ENABLE_SPLIT_POLICIES = false;
47 
48     private NetworkPolicyManager mPolicyManager;
49     private ArrayList<NetworkPolicy> mPolicies = Lists.newArrayList();
50 
NetworkPolicyEditor(NetworkPolicyManager policyManager)51     public NetworkPolicyEditor(NetworkPolicyManager policyManager) {
52         mPolicyManager = checkNotNull(policyManager);
53     }
54 
read()55     public void read() {
56         final NetworkPolicy[] policies = mPolicyManager.getNetworkPolicies();
57 
58         boolean modified = false;
59         mPolicies.clear();
60         for (NetworkPolicy policy : policies) {
61             // TODO: find better place to clamp these
62             if (policy.limitBytes < -1) {
63                 policy.limitBytes = LIMIT_DISABLED;
64                 modified = true;
65             }
66             if (policy.warningBytes < -1) {
67                 policy.warningBytes = WARNING_DISABLED;
68                 modified = true;
69             }
70 
71             mPolicies.add(policy);
72         }
73 
74         // when we cleaned policies above, write back changes
75         if (modified) writeAsync();
76     }
77 
writeAsync()78     public void writeAsync() {
79         // TODO: consider making more robust by passing through service
80         final NetworkPolicy[] policies = mPolicies.toArray(new NetworkPolicy[mPolicies.size()]);
81         new AsyncTask<Void, Void, Void>() {
82             @Override
83             protected Void doInBackground(Void... params) {
84                 write(policies);
85                 return null;
86             }
87         }.execute();
88     }
89 
write(NetworkPolicy[] policies)90     public void write(NetworkPolicy[] policies) {
91         mPolicyManager.setNetworkPolicies(policies);
92     }
93 
hasLimitedPolicy(NetworkTemplate template)94     public boolean hasLimitedPolicy(NetworkTemplate template) {
95         final NetworkPolicy policy = getPolicy(template);
96         return policy != null && policy.limitBytes != LIMIT_DISABLED;
97     }
98 
getOrCreatePolicy(NetworkTemplate template)99     public NetworkPolicy getOrCreatePolicy(NetworkTemplate template) {
100         NetworkPolicy policy = getPolicy(template);
101         if (policy == null) {
102             policy = buildDefaultPolicy(template);
103             mPolicies.add(policy);
104         }
105         return policy;
106     }
107 
getPolicy(NetworkTemplate template)108     public NetworkPolicy getPolicy(NetworkTemplate template) {
109         for (NetworkPolicy policy : mPolicies) {
110             if (policy.template.equals(template)) {
111                 return policy;
112             }
113         }
114         return null;
115     }
116 
getPolicyMaybeUnquoted(NetworkTemplate template)117     public NetworkPolicy getPolicyMaybeUnquoted(NetworkTemplate template) {
118         NetworkPolicy policy = getPolicy(template);
119         if (policy != null) {
120             return policy;
121         } else {
122             return getPolicy(buildUnquotedNetworkTemplate(template));
123         }
124     }
125 
126     @Deprecated
buildDefaultPolicy(NetworkTemplate template)127     private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) {
128         // TODO: move this into framework to share with NetworkPolicyManagerService
129         final int cycleDay;
130         final String cycleTimezone;
131         final boolean metered;
132 
133         if (template.getMatchRule() == MATCH_WIFI) {
134             cycleDay = CYCLE_NONE;
135             cycleTimezone = Time.TIMEZONE_UTC;
136             metered = false;
137         } else {
138             final Time time = new Time();
139             time.setToNow();
140             cycleDay = time.monthDay;
141             cycleTimezone = time.timezone;
142             metered = true;
143         }
144 
145         return new NetworkPolicy(template, cycleDay, cycleTimezone, WARNING_DISABLED,
146                 LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, metered, true);
147     }
148 
getPolicyCycleDay(NetworkTemplate template)149     public int getPolicyCycleDay(NetworkTemplate template) {
150         final NetworkPolicy policy = getPolicy(template);
151         return (policy != null) ? policy.cycleDay : -1;
152     }
153 
setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone)154     public void setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone) {
155         final NetworkPolicy policy = getOrCreatePolicy(template);
156         policy.cycleDay = cycleDay;
157         policy.cycleTimezone = cycleTimezone;
158         policy.inferred = false;
159         policy.clearSnooze();
160         writeAsync();
161     }
162 
getPolicyWarningBytes(NetworkTemplate template)163     public long getPolicyWarningBytes(NetworkTemplate template) {
164         final NetworkPolicy policy = getPolicy(template);
165         return (policy != null) ? policy.warningBytes : WARNING_DISABLED;
166     }
167 
setPolicyWarningBytes(NetworkTemplate template, long warningBytes)168     public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
169         final NetworkPolicy policy = getOrCreatePolicy(template);
170         policy.warningBytes = warningBytes;
171         policy.inferred = false;
172         policy.clearSnooze();
173         writeAsync();
174     }
175 
getPolicyLimitBytes(NetworkTemplate template)176     public long getPolicyLimitBytes(NetworkTemplate template) {
177         final NetworkPolicy policy = getPolicy(template);
178         return (policy != null) ? policy.limitBytes : LIMIT_DISABLED;
179     }
180 
setPolicyLimitBytes(NetworkTemplate template, long limitBytes)181     public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
182         final NetworkPolicy policy = getOrCreatePolicy(template);
183         policy.limitBytes = limitBytes;
184         policy.inferred = false;
185         policy.clearSnooze();
186         writeAsync();
187     }
188 
getPolicyMetered(NetworkTemplate template)189     public boolean getPolicyMetered(NetworkTemplate template) {
190         NetworkPolicy policy = getPolicy(template);
191         if (policy != null) {
192             return policy.metered;
193         } else {
194             return false;
195         }
196     }
197 
setPolicyMetered(NetworkTemplate template, boolean metered)198     public void setPolicyMetered(NetworkTemplate template, boolean metered) {
199         boolean modified = false;
200 
201         NetworkPolicy policy = getPolicy(template);
202         if (metered) {
203             if (policy == null) {
204                 policy = buildDefaultPolicy(template);
205                 policy.metered = true;
206                 policy.inferred = false;
207                 mPolicies.add(policy);
208                 modified = true;
209             } else if (!policy.metered) {
210                 policy.metered = true;
211                 policy.inferred = false;
212                 modified = true;
213             }
214 
215         } else {
216             if (policy == null) {
217                 // ignore when policy doesn't exist
218             } else if (policy.metered) {
219                 policy.metered = false;
220                 policy.inferred = false;
221                 modified = true;
222             }
223         }
224 
225         // Remove legacy unquoted policies while we're here
226         final NetworkTemplate unquoted = buildUnquotedNetworkTemplate(template);
227         final NetworkPolicy unquotedPolicy = getPolicy(unquoted);
228         if (unquotedPolicy != null) {
229             mPolicies.remove(unquotedPolicy);
230             modified = true;
231         }
232 
233         if (modified) writeAsync();
234     }
235 
236     /**
237      * Build a revised {@link NetworkTemplate} that matches the same rule, but
238      * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work
239      * around legacy bugs.
240      */
buildUnquotedNetworkTemplate(NetworkTemplate template)241     private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) {
242         if (template == null) return null;
243         final String networkId = template.getNetworkId();
244         final String strippedNetworkId = WifiInfo.removeDoubleQuotes(networkId);
245         if (!TextUtils.equals(strippedNetworkId, networkId)) {
246             return new NetworkTemplate(
247                     template.getMatchRule(), template.getSubscriberId(), strippedNetworkId);
248         } else {
249             return null;
250         }
251     }
252 }
253