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