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.settingslib;
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 
25 import static com.android.internal.util.Preconditions.checkNotNull;
26 
27 import android.net.NetworkPolicy;
28 import android.net.NetworkPolicyManager;
29 import android.net.NetworkTemplate;
30 import android.net.wifi.WifiInfo;
31 import android.os.AsyncTask;
32 import android.text.TextUtils;
33 import android.util.RecurrenceRule;
34 
35 import com.google.android.collect.Lists;
36 
37 import java.time.ZoneId;
38 import java.time.ZonedDateTime;
39 import java.util.ArrayList;
40 
41 /**
42  * Utility class to modify list of {@link NetworkPolicy}. Specifically knows
43  * about which policies can coexist. This editor offers thread safety when
44  * talking with {@link NetworkPolicyManager}.
45  *
46  * @hide
47  */
48 public class NetworkPolicyEditor {
49     // TODO: be more robust when missing policies from service
50 
51     public static final boolean ENABLE_SPLIT_POLICIES = false;
52 
53     private NetworkPolicyManager mPolicyManager;
54     private ArrayList<NetworkPolicy> mPolicies = Lists.newArrayList();
55 
NetworkPolicyEditor(NetworkPolicyManager policyManager)56     public NetworkPolicyEditor(NetworkPolicyManager policyManager) {
57         mPolicyManager = checkNotNull(policyManager);
58     }
59 
read()60     public void read() {
61         final NetworkPolicy[] policies = mPolicyManager.getNetworkPolicies();
62 
63         boolean modified = false;
64         mPolicies.clear();
65         for (NetworkPolicy policy : policies) {
66             // TODO: find better place to clamp these
67             if (policy.limitBytes < -1) {
68                 policy.limitBytes = LIMIT_DISABLED;
69                 modified = true;
70             }
71             if (policy.warningBytes < -1) {
72                 policy.warningBytes = WARNING_DISABLED;
73                 modified = true;
74             }
75 
76             mPolicies.add(policy);
77         }
78 
79         // when we cleaned policies above, write back changes
80         if (modified) writeAsync();
81     }
82 
writeAsync()83     public void writeAsync() {
84         // TODO: consider making more robust by passing through service
85         final NetworkPolicy[] policies = mPolicies.toArray(new NetworkPolicy[mPolicies.size()]);
86         new AsyncTask<Void, Void, Void>() {
87             @Override
88             protected Void doInBackground(Void... params) {
89                 write(policies);
90                 return null;
91             }
92         }.execute();
93     }
94 
write(NetworkPolicy[] policies)95     public void write(NetworkPolicy[] policies) {
96         mPolicyManager.setNetworkPolicies(policies);
97     }
98 
hasLimitedPolicy(NetworkTemplate template)99     public boolean hasLimitedPolicy(NetworkTemplate template) {
100         final NetworkPolicy policy = getPolicy(template);
101         return policy != null && policy.limitBytes != LIMIT_DISABLED;
102     }
103 
getOrCreatePolicy(NetworkTemplate template)104     public NetworkPolicy getOrCreatePolicy(NetworkTemplate template) {
105         NetworkPolicy policy = getPolicy(template);
106         if (policy == null) {
107             policy = buildDefaultPolicy(template);
108             mPolicies.add(policy);
109         }
110         return policy;
111     }
112 
getPolicy(NetworkTemplate template)113     public NetworkPolicy getPolicy(NetworkTemplate template) {
114         for (NetworkPolicy policy : mPolicies) {
115             if (policy.template.equals(template)) {
116                 return policy;
117             }
118         }
119         return null;
120     }
121 
getPolicyMaybeUnquoted(NetworkTemplate template)122     public NetworkPolicy getPolicyMaybeUnquoted(NetworkTemplate template) {
123         NetworkPolicy policy = getPolicy(template);
124         if (policy != null) {
125             return policy;
126         } else {
127             return getPolicy(buildUnquotedNetworkTemplate(template));
128         }
129     }
130 
131     @Deprecated
buildDefaultPolicy(NetworkTemplate template)132     private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) {
133         // TODO: move this into framework to share with NetworkPolicyManagerService
134         final RecurrenceRule cycleRule;
135         final boolean metered;
136 
137         if (template.getMatchRule() == MATCH_WIFI) {
138             cycleRule = RecurrenceRule.buildNever();
139             metered = false;
140         } else {
141             cycleRule = RecurrenceRule.buildRecurringMonthly(ZonedDateTime.now().getDayOfMonth(),
142                     ZoneId.systemDefault());
143             metered = true;
144         }
145 
146         return new NetworkPolicy(template, cycleRule, WARNING_DISABLED,
147                 LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, metered, true);
148     }
149 
150     @Deprecated
getPolicyCycleDay(NetworkTemplate template)151     public int getPolicyCycleDay(NetworkTemplate template) {
152         final NetworkPolicy policy = getPolicy(template);
153         if (policy != null && policy.cycleRule.isMonthly()) {
154             return policy.cycleRule.start.getDayOfMonth();
155         } else {
156             return CYCLE_NONE;
157         }
158     }
159 
160     @Deprecated
setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone)161     public void setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone) {
162         final NetworkPolicy policy = getOrCreatePolicy(template);
163         policy.cycleRule = NetworkPolicy.buildRule(cycleDay, ZoneId.of(cycleTimezone));
164         policy.inferred = false;
165         policy.clearSnooze();
166         writeAsync();
167     }
168 
getPolicyWarningBytes(NetworkTemplate template)169     public long getPolicyWarningBytes(NetworkTemplate template) {
170         final NetworkPolicy policy = getPolicy(template);
171         return (policy != null) ? policy.warningBytes : WARNING_DISABLED;
172     }
173 
setPolicyWarningBytesInner(NetworkTemplate template, long warningBytes)174     private void setPolicyWarningBytesInner(NetworkTemplate template, long warningBytes) {
175         final NetworkPolicy policy = getOrCreatePolicy(template);
176         policy.warningBytes = warningBytes;
177         policy.inferred = false;
178         policy.clearSnooze();
179         writeAsync();
180     }
181 
setPolicyWarningBytes(NetworkTemplate template, long warningBytes)182     public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
183         long limitBytes = getPolicyLimitBytes(template);
184 
185         warningBytes =
186             (limitBytes == LIMIT_DISABLED) ? warningBytes : Math.min(warningBytes, limitBytes);
187 
188         setPolicyWarningBytesInner(template, warningBytes);
189     }
190 
getPolicyLimitBytes(NetworkTemplate template)191     public long getPolicyLimitBytes(NetworkTemplate template) {
192         final NetworkPolicy policy = getPolicy(template);
193         return (policy != null) ? policy.limitBytes : LIMIT_DISABLED;
194     }
195 
196 
setPolicyLimitBytes(NetworkTemplate template, long limitBytes)197     public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
198         long warningBytes = getPolicyWarningBytes(template);
199 
200         if (warningBytes > limitBytes && limitBytes != LIMIT_DISABLED) {
201             setPolicyWarningBytesInner(template, limitBytes);
202         }
203 
204         final NetworkPolicy policy = getOrCreatePolicy(template);
205         policy.limitBytes = limitBytes;
206         policy.inferred = false;
207         policy.clearSnooze();
208         writeAsync();
209     }
210 
211     /**
212      * Build a revised {@link NetworkTemplate} that matches the same rule, but
213      * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work
214      * around legacy bugs.
215      */
buildUnquotedNetworkTemplate(NetworkTemplate template)216     private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) {
217         if (template == null) return null;
218         final String networkId = template.getNetworkId();
219         final String strippedNetworkId = WifiInfo.sanitizeSsid(networkId);
220         if (!TextUtils.equals(strippedNetworkId, networkId)) {
221             return new NetworkTemplate(
222                     template.getMatchRule(), template.getSubscriberId(), strippedNetworkId);
223         } else {
224             return null;
225         }
226     }
227 }
228