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 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 * @hide 44 */ 45 public class NetworkPolicyEditor { 46 // TODO: be more robust when missing policies from service 47 48 public static final boolean ENABLE_SPLIT_POLICIES = false; 49 50 private NetworkPolicyManager mPolicyManager; 51 private ArrayList<NetworkPolicy> mPolicies = Lists.newArrayList(); 52 53 public NetworkPolicyEditor(NetworkPolicyManager policyManager) { 54 mPolicyManager = checkNotNull(policyManager); 55 } 56 57 public void read() { 58 final NetworkPolicy[] policies = mPolicyManager.getNetworkPolicies(); 59 60 boolean modified = false; 61 mPolicies.clear(); 62 for (NetworkPolicy policy : policies) { 63 // TODO: find better place to clamp these 64 if (policy.limitBytes < -1) { 65 policy.limitBytes = LIMIT_DISABLED; 66 modified = true; 67 } 68 if (policy.warningBytes < -1) { 69 policy.warningBytes = WARNING_DISABLED; 70 modified = true; 71 } 72 73 mPolicies.add(policy); 74 } 75 76 // when we cleaned policies above, write back changes 77 if (modified) writeAsync(); 78 } 79 80 public void writeAsync() { 81 // TODO: consider making more robust by passing through service 82 final NetworkPolicy[] policies = mPolicies.toArray(new NetworkPolicy[mPolicies.size()]); 83 new AsyncTask<Void, Void, Void>() { 84 @Override 85 protected Void doInBackground(Void... params) { 86 write(policies); 87 return null; 88 } 89 }.execute(); 90 } 91 92 public void write(NetworkPolicy[] policies) { 93 mPolicyManager.setNetworkPolicies(policies); 94 } 95 96 public boolean hasLimitedPolicy(NetworkTemplate template) { 97 final NetworkPolicy policy = getPolicy(template); 98 return policy != null && policy.limitBytes != LIMIT_DISABLED; 99 } 100 101 public NetworkPolicy getOrCreatePolicy(NetworkTemplate template) { 102 NetworkPolicy policy = getPolicy(template); 103 if (policy == null) { 104 policy = buildDefaultPolicy(template); 105 mPolicies.add(policy); 106 } 107 return policy; 108 } 109 110 public NetworkPolicy getPolicy(NetworkTemplate template) { 111 for (NetworkPolicy policy : mPolicies) { 112 if (policy.template.equals(template)) { 113 return policy; 114 } 115 } 116 return null; 117 } 118 119 public NetworkPolicy getPolicyMaybeUnquoted(NetworkTemplate template) { 120 NetworkPolicy policy = getPolicy(template); 121 if (policy != null) { 122 return policy; 123 } else { 124 return getPolicy(buildUnquotedNetworkTemplate(template)); 125 } 126 } 127 128 @Deprecated 129 private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) { 130 // TODO: move this into framework to share with NetworkPolicyManagerService 131 final int cycleDay; 132 final String cycleTimezone; 133 final boolean metered; 134 135 if (template.getMatchRule() == MATCH_WIFI) { 136 cycleDay = CYCLE_NONE; 137 cycleTimezone = Time.TIMEZONE_UTC; 138 metered = false; 139 } else { 140 final Time time = new Time(); 141 time.setToNow(); 142 cycleDay = time.monthDay; 143 cycleTimezone = time.timezone; 144 metered = true; 145 } 146 147 return new NetworkPolicy(template, cycleDay, cycleTimezone, WARNING_DISABLED, 148 LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, metered, true); 149 } 150 151 public int getPolicyCycleDay(NetworkTemplate template) { 152 final NetworkPolicy policy = getPolicy(template); 153 return (policy != null) ? policy.cycleDay : -1; 154 } 155 156 public void setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone) { 157 final NetworkPolicy policy = getOrCreatePolicy(template); 158 policy.cycleDay = cycleDay; 159 policy.cycleTimezone = cycleTimezone; 160 policy.inferred = false; 161 policy.clearSnooze(); 162 writeAsync(); 163 } 164 165 public long getPolicyWarningBytes(NetworkTemplate template) { 166 final NetworkPolicy policy = getPolicy(template); 167 return (policy != null) ? policy.warningBytes : WARNING_DISABLED; 168 } 169 170 private void setPolicyWarningBytesInner(NetworkTemplate template, long warningBytes) { 171 final NetworkPolicy policy = getOrCreatePolicy(template); 172 policy.warningBytes = warningBytes; 173 policy.inferred = false; 174 policy.clearSnooze(); 175 writeAsync(); 176 } 177 178 public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) { 179 long limitBytes = getPolicyLimitBytes(template); 180 181 warningBytes = 182 (limitBytes == LIMIT_DISABLED) ? warningBytes : Math.min(warningBytes, limitBytes); 183 184 setPolicyWarningBytesInner(template, warningBytes); 185 } 186 187 public long getPolicyLimitBytes(NetworkTemplate template) { 188 final NetworkPolicy policy = getPolicy(template); 189 return (policy != null) ? policy.limitBytes : LIMIT_DISABLED; 190 } 191 192 193 public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) { 194 long warningBytes = getPolicyWarningBytes(template); 195 196 if (warningBytes > limitBytes && limitBytes != LIMIT_DISABLED) { 197 setPolicyWarningBytesInner(template, limitBytes); 198 } 199 200 final NetworkPolicy policy = getOrCreatePolicy(template); 201 policy.limitBytes = limitBytes; 202 policy.inferred = false; 203 policy.clearSnooze(); 204 writeAsync(); 205 } 206 207 public boolean getPolicyMetered(NetworkTemplate template) { 208 NetworkPolicy policy = getPolicy(template); 209 if (policy != null) { 210 return policy.metered; 211 } else { 212 return false; 213 } 214 } 215 216 public void setPolicyMetered(NetworkTemplate template, boolean metered) { 217 boolean modified = false; 218 219 NetworkPolicy policy = getPolicy(template); 220 if (metered) { 221 if (policy == null) { 222 policy = buildDefaultPolicy(template); 223 policy.metered = true; 224 policy.inferred = false; 225 mPolicies.add(policy); 226 modified = true; 227 } else if (!policy.metered) { 228 policy.metered = true; 229 policy.inferred = false; 230 modified = true; 231 } 232 233 } else { 234 if (policy == null) { 235 // ignore when policy doesn't exist 236 } else if (policy.metered) { 237 policy.metered = false; 238 policy.inferred = false; 239 modified = true; 240 } 241 } 242 243 // Remove legacy unquoted policies while we're here 244 final NetworkTemplate unquoted = buildUnquotedNetworkTemplate(template); 245 final NetworkPolicy unquotedPolicy = getPolicy(unquoted); 246 if (unquotedPolicy != null) { 247 mPolicies.remove(unquotedPolicy); 248 modified = true; 249 } 250 251 if (modified) writeAsync(); 252 } 253 254 /** 255 * Build a revised {@link NetworkTemplate} that matches the same rule, but 256 * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work 257 * around legacy bugs. 258 */ 259 private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) { 260 if (template == null) return null; 261 final String networkId = template.getNetworkId(); 262 final String strippedNetworkId = WifiInfo.removeDoubleQuotes(networkId); 263 if (!TextUtils.equals(strippedNetworkId, networkId)) { 264 return new NetworkTemplate( 265 template.getMatchRule(), template.getSubscriberId(), strippedNetworkId); 266 } else { 267 return null; 268 } 269 } 270 } 271