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