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
NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone, long warningBytes, long limitBytes, boolean metered)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 
NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone, long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered, boolean inferred)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 
NetworkPolicy(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()107     public int describeContents() {
108         return 0;
109     }
110 
111     /**
112      * Test if given measurement is over {@link #warningBytes}.
113      */
isOverWarning(long totalBytes)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      */
isOverLimit(long totalBytes)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      */
clearSnooze()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      */
hasCycle()140     public boolean hasCycle() {
141         return cycleDay != CYCLE_NONE;
142     }
143 
144     @Override
compareTo(NetworkPolicy another)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
hashCode()158     public int hashCode() {
159         return Objects.hash(template, cycleDay, cycleTimezone, warningBytes, limitBytes,
160                 lastWarningSnooze, lastLimitSnooze, metered, inferred);
161     }
162 
163     @Override
equals(Object obj)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
toString()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 
getBytesForBackup()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 
getNetworkPolicyFromBackup(DataInputStream in)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