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 android.net; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 import android.util.BackupUtils; 22 import android.util.Range; 23 import android.util.RecurrenceRule; 24 25 import com.android.internal.util.Preconditions; 26 27 import java.io.ByteArrayOutputStream; 28 import java.io.DataInputStream; 29 import java.io.DataOutputStream; 30 import java.io.IOException; 31 import java.time.ZoneId; 32 import java.time.ZonedDateTime; 33 import java.util.Iterator; 34 import java.util.Objects; 35 36 /** 37 * Policy for networks matching a {@link NetworkTemplate}, including usage cycle 38 * and limits to be enforced. 39 * 40 * @hide 41 */ 42 public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { 43 private static final int VERSION_INIT = 1; 44 private static final int VERSION_RULE = 2; 45 private static final int VERSION_RAPID = 3; 46 47 public static final int CYCLE_NONE = -1; 48 public static final long WARNING_DISABLED = -1; 49 public static final long LIMIT_DISABLED = -1; 50 public static final long SNOOZE_NEVER = -1; 51 52 public NetworkTemplate template; 53 public RecurrenceRule cycleRule; 54 public long warningBytes = WARNING_DISABLED; 55 public long limitBytes = LIMIT_DISABLED; 56 public long lastWarningSnooze = SNOOZE_NEVER; 57 public long lastLimitSnooze = SNOOZE_NEVER; 58 public long lastRapidSnooze = SNOOZE_NEVER; 59 @Deprecated public boolean metered = true; 60 public boolean inferred = false; 61 62 private static final long DEFAULT_MTU = 1500; 63 buildRule(int cycleDay, ZoneId cycleTimezone)64 public static RecurrenceRule buildRule(int cycleDay, ZoneId cycleTimezone) { 65 if (cycleDay != NetworkPolicy.CYCLE_NONE) { 66 return RecurrenceRule.buildRecurringMonthly(cycleDay, cycleTimezone); 67 } else { 68 return RecurrenceRule.buildNever(); 69 } 70 } 71 72 @Deprecated NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone, long warningBytes, long limitBytes, boolean metered)73 public NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone, 74 long warningBytes, long limitBytes, boolean metered) { 75 this(template, cycleDay, cycleTimezone, warningBytes, limitBytes, SNOOZE_NEVER, 76 SNOOZE_NEVER, metered, false); 77 } 78 79 @Deprecated NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone, long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered, boolean inferred)80 public NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone, 81 long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze, 82 boolean metered, boolean inferred) { 83 this(template, buildRule(cycleDay, ZoneId.of(cycleTimezone)), warningBytes, 84 limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred); 85 } 86 87 @Deprecated NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered, boolean inferred)88 public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes, 89 long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered, 90 boolean inferred) { 91 this(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze, lastLimitSnooze, 92 SNOOZE_NEVER, metered, inferred); 93 } 94 NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze, long lastRapidSnooze, boolean metered, boolean inferred)95 public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes, 96 long limitBytes, long lastWarningSnooze, long lastLimitSnooze, long lastRapidSnooze, 97 boolean metered, boolean inferred) { 98 this.template = Preconditions.checkNotNull(template, "missing NetworkTemplate"); 99 this.cycleRule = Preconditions.checkNotNull(cycleRule, "missing RecurrenceRule"); 100 this.warningBytes = warningBytes; 101 this.limitBytes = limitBytes; 102 this.lastWarningSnooze = lastWarningSnooze; 103 this.lastLimitSnooze = lastLimitSnooze; 104 this.lastRapidSnooze = lastRapidSnooze; 105 this.metered = metered; 106 this.inferred = inferred; 107 } 108 NetworkPolicy(Parcel source)109 private NetworkPolicy(Parcel source) { 110 template = source.readParcelable(null); 111 cycleRule = source.readParcelable(null); 112 warningBytes = source.readLong(); 113 limitBytes = source.readLong(); 114 lastWarningSnooze = source.readLong(); 115 lastLimitSnooze = source.readLong(); 116 lastRapidSnooze = source.readLong(); 117 metered = source.readInt() != 0; 118 inferred = source.readInt() != 0; 119 } 120 121 @Override writeToParcel(Parcel dest, int flags)122 public void writeToParcel(Parcel dest, int flags) { 123 dest.writeParcelable(template, flags); 124 dest.writeParcelable(cycleRule, flags); 125 dest.writeLong(warningBytes); 126 dest.writeLong(limitBytes); 127 dest.writeLong(lastWarningSnooze); 128 dest.writeLong(lastLimitSnooze); 129 dest.writeLong(lastRapidSnooze); 130 dest.writeInt(metered ? 1 : 0); 131 dest.writeInt(inferred ? 1 : 0); 132 } 133 134 @Override describeContents()135 public int describeContents() { 136 return 0; 137 } 138 cycleIterator()139 public Iterator<Range<ZonedDateTime>> cycleIterator() { 140 return cycleRule.cycleIterator(); 141 } 142 143 /** 144 * Test if given measurement is over {@link #warningBytes}. 145 */ isOverWarning(long totalBytes)146 public boolean isOverWarning(long totalBytes) { 147 return warningBytes != WARNING_DISABLED && totalBytes >= warningBytes; 148 } 149 150 /** 151 * Test if given measurement is near enough to {@link #limitBytes} to be 152 * considered over-limit. 153 */ isOverLimit(long totalBytes)154 public boolean isOverLimit(long totalBytes) { 155 // over-estimate, since kernel will trigger limit once first packet 156 // trips over limit. 157 totalBytes += 2 * DEFAULT_MTU; 158 return limitBytes != LIMIT_DISABLED && totalBytes >= limitBytes; 159 } 160 161 /** 162 * Clear any existing snooze values, setting to {@link #SNOOZE_NEVER}. 163 */ clearSnooze()164 public void clearSnooze() { 165 lastWarningSnooze = SNOOZE_NEVER; 166 lastLimitSnooze = SNOOZE_NEVER; 167 lastRapidSnooze = SNOOZE_NEVER; 168 } 169 170 /** 171 * Test if this policy has a cycle defined, after which usage should reset. 172 */ hasCycle()173 public boolean hasCycle() { 174 return cycleRule.cycleIterator().hasNext(); 175 } 176 177 @Override compareTo(NetworkPolicy another)178 public int compareTo(NetworkPolicy another) { 179 if (another == null || another.limitBytes == LIMIT_DISABLED) { 180 // other value is missing or disabled; we win 181 return -1; 182 } 183 if (limitBytes == LIMIT_DISABLED || another.limitBytes < limitBytes) { 184 // we're disabled or other limit is smaller; they win 185 return 1; 186 } 187 return 0; 188 } 189 190 @Override hashCode()191 public int hashCode() { 192 return Objects.hash(template, cycleRule, warningBytes, limitBytes, 193 lastWarningSnooze, lastLimitSnooze, lastRapidSnooze, metered, inferred); 194 } 195 196 @Override equals(Object obj)197 public boolean equals(Object obj) { 198 if (obj instanceof NetworkPolicy) { 199 final NetworkPolicy other = (NetworkPolicy) obj; 200 return warningBytes == other.warningBytes 201 && limitBytes == other.limitBytes 202 && lastWarningSnooze == other.lastWarningSnooze 203 && lastLimitSnooze == other.lastLimitSnooze 204 && lastRapidSnooze == other.lastRapidSnooze 205 && metered == other.metered 206 && inferred == other.inferred 207 && Objects.equals(template, other.template) 208 && Objects.equals(cycleRule, other.cycleRule); 209 } 210 return false; 211 } 212 213 @Override toString()214 public String toString() { 215 return new StringBuilder("NetworkPolicy{") 216 .append("template=").append(template) 217 .append(" cycleRule=").append(cycleRule) 218 .append(" warningBytes=").append(warningBytes) 219 .append(" limitBytes=").append(limitBytes) 220 .append(" lastWarningSnooze=").append(lastWarningSnooze) 221 .append(" lastLimitSnooze=").append(lastLimitSnooze) 222 .append(" lastRapidSnooze=").append(lastRapidSnooze) 223 .append(" metered=").append(metered) 224 .append(" inferred=").append(inferred) 225 .append("}").toString(); 226 } 227 228 public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() { 229 @Override 230 public NetworkPolicy createFromParcel(Parcel in) { 231 return new NetworkPolicy(in); 232 } 233 234 @Override 235 public NetworkPolicy[] newArray(int size) { 236 return new NetworkPolicy[size]; 237 } 238 }; 239 getBytesForBackup()240 public byte[] getBytesForBackup() throws IOException { 241 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 242 DataOutputStream out = new DataOutputStream(baos); 243 244 out.writeInt(VERSION_RAPID); 245 out.write(template.getBytesForBackup()); 246 cycleRule.writeToStream(out); 247 out.writeLong(warningBytes); 248 out.writeLong(limitBytes); 249 out.writeLong(lastWarningSnooze); 250 out.writeLong(lastLimitSnooze); 251 out.writeLong(lastRapidSnooze); 252 out.writeInt(metered ? 1 : 0); 253 out.writeInt(inferred ? 1 : 0); 254 return baos.toByteArray(); 255 } 256 getNetworkPolicyFromBackup(DataInputStream in)257 public static NetworkPolicy getNetworkPolicyFromBackup(DataInputStream in) throws IOException, 258 BackupUtils.BadVersionException { 259 final int version = in.readInt(); 260 if (version < VERSION_INIT || version > VERSION_RAPID) { 261 throw new BackupUtils.BadVersionException("Unknown backup version: " + version); 262 } 263 264 final NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in); 265 final RecurrenceRule cycleRule; 266 if (version >= VERSION_RULE) { 267 cycleRule = new RecurrenceRule(in); 268 } else { 269 final int cycleDay = in.readInt(); 270 final String cycleTimezone = BackupUtils.readString(in); 271 cycleRule = buildRule(cycleDay, ZoneId.of(cycleTimezone)); 272 } 273 final long warningBytes = in.readLong(); 274 final long limitBytes = in.readLong(); 275 final long lastWarningSnooze = in.readLong(); 276 final long lastLimitSnooze = in.readLong(); 277 final long lastRapidSnooze; 278 if (version >= VERSION_RAPID) { 279 lastRapidSnooze = in.readLong(); 280 } else { 281 lastRapidSnooze = SNOOZE_NEVER; 282 } 283 final boolean metered = in.readInt() == 1; 284 final boolean inferred = in.readInt() == 1; 285 return new NetworkPolicy(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze, 286 lastLimitSnooze, lastRapidSnooze, metered, inferred); 287 } 288 } 289