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 public void setPolicyWarningBytes(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 long getPolicyLimitBytes(NetworkTemplate template) { 179 final NetworkPolicy policy = getPolicy(template); 180 return (policy != null) ? policy.limitBytes : LIMIT_DISABLED; 181 } 182 183 public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) { 184 final NetworkPolicy policy = getOrCreatePolicy(template); 185 policy.limitBytes = limitBytes; 186 policy.inferred = false; 187 policy.clearSnooze(); 188 writeAsync(); 189 } 190 191 public boolean getPolicyMetered(NetworkTemplate template) { 192 NetworkPolicy policy = getPolicy(template); 193 if (policy != null) { 194 return policy.metered; 195 } else { 196 return false; 197 } 198 } 199 200 public void setPolicyMetered(NetworkTemplate template, boolean metered) { 201 boolean modified = false; 202 203 NetworkPolicy policy = getPolicy(template); 204 if (metered) { 205 if (policy == null) { 206 policy = buildDefaultPolicy(template); 207 policy.metered = true; 208 policy.inferred = false; 209 mPolicies.add(policy); 210 modified = true; 211 } else if (!policy.metered) { 212 policy.metered = true; 213 policy.inferred = false; 214 modified = true; 215 } 216 217 } else { 218 if (policy == null) { 219 // ignore when policy doesn't exist 220 } else if (policy.metered) { 221 policy.metered = false; 222 policy.inferred = false; 223 modified = true; 224 } 225 } 226 227 // Remove legacy unquoted policies while we're here 228 final NetworkTemplate unquoted = buildUnquotedNetworkTemplate(template); 229 final NetworkPolicy unquotedPolicy = getPolicy(unquoted); 230 if (unquotedPolicy != null) { 231 mPolicies.remove(unquotedPolicy); 232 modified = true; 233 } 234 235 if (modified) writeAsync(); 236 } 237 238 /** 239 * Build a revised {@link NetworkTemplate} that matches the same rule, but 240 * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work 241 * around legacy bugs. 242 */ 243 private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) { 244 if (template == null) return null; 245 final String networkId = template.getNetworkId(); 246 final String strippedNetworkId = WifiInfo.removeDoubleQuotes(networkId); 247 if (!TextUtils.equals(strippedNetworkId, networkId)) { 248 return new NetworkTemplate( 249 template.getMatchRule(), template.getSubscriberId(), strippedNetworkId); 250 } else { 251 return null; 252 } 253 } 254 } 255