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