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