121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey/*
221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project
321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey *
421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * you may not use this file except in compliance with the License.
621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * You may obtain a copy of the License at
721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey *
821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey *
1021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
1121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
1221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * See the License for the specific language governing permissions and
1421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * limitations under the License.
1521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey */
1621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeypackage android.net;
1821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Parcel;
2021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Parcelable;
21adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport android.util.BackupUtils;
220fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkeyimport android.util.Range;
2317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport android.util.RecurrenceRule;
2417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey
2517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport com.android.internal.util.Preconditions;
2621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
27adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport java.io.ByteArrayOutputStream;
28adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport java.io.DataInputStream;
29adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport java.io.DataOutputStream;
30adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport java.io.IOException;
3117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport java.time.ZoneId;
3217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport java.time.ZonedDateTime;
3317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport java.util.Iterator;
34e6585b32ea586743258a5457e2184ffc087f2d2fKenny Rootimport java.util.Objects;
3541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
3621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey/**
371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * Policy for networks matching a {@link NetworkTemplate}, including usage cycle
381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * and limits to be enforced.
3921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey *
4021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey * @hide
4121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey */
4221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeypublic class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
4317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    private static final int VERSION_INIT = 1;
4417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    private static final int VERSION_RULE = 2;
45bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey    private static final int VERSION_RAPID = 3;
46adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
478fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    public static final int CYCLE_NONE = -1;
481b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public static final long WARNING_DISABLED = -1;
491b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public static final long LIMIT_DISABLED = -1;
5041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final long SNOOZE_NEVER = -1;
511b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
523256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    public NetworkTemplate template;
5317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    public RecurrenceRule cycleRule;
5453313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public long warningBytes = WARNING_DISABLED;
5553313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public long limitBytes = LIMIT_DISABLED;
5653313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public long lastWarningSnooze = SNOOZE_NEVER;
5753313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public long lastLimitSnooze = SNOOZE_NEVER;
58bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey    public long lastRapidSnooze = SNOOZE_NEVER;
5953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    @Deprecated public boolean metered = true;
6053313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public boolean inferred = false;
6121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
6250e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey    private static final long DEFAULT_MTU = 1500;
6350e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey
6417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    public static RecurrenceRule buildRule(int cycleDay, ZoneId cycleTimezone) {
6517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        if (cycleDay != NetworkPolicy.CYCLE_NONE) {
6617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            return RecurrenceRule.buildRecurringMonthly(cycleDay, cycleTimezone);
6717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        } else {
6817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            return RecurrenceRule.buildNever();
6917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        }
7053313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
7153313d7e8153982f842910118371e1dc061248cdJeff Sharkey
72837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey    @Deprecated
739bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey    public NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone,
749bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey            long warningBytes, long limitBytes, boolean metered) {
759bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey        this(template, cycleDay, cycleTimezone, warningBytes, limitBytes, SNOOZE_NEVER,
76837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                SNOOZE_NEVER, metered, false);
770e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    }
780e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
7917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    @Deprecated
809bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey    public NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone,
819bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey            long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze,
82837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey            boolean metered, boolean inferred) {
8317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        this(template, buildRule(cycleDay, ZoneId.of(cycleTimezone)), warningBytes,
8417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred);
8517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    }
8617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey
87bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey    @Deprecated
8817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes,
8917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered,
9017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            boolean inferred) {
91bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        this(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze, lastLimitSnooze,
92bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey                SNOOZE_NEVER, metered, inferred);
93bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey    }
94bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey
95bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey    public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes,
96bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            long limitBytes, long lastWarningSnooze, long lastLimitSnooze, long lastRapidSnooze,
97bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            boolean metered, boolean inferred) {
9817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        this.template = Preconditions.checkNotNull(template, "missing NetworkTemplate");
9917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        this.cycleRule = Preconditions.checkNotNull(cycleRule, "missing RecurrenceRule");
10021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        this.warningBytes = warningBytes;
10121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        this.limitBytes = limitBytes;
1020e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        this.lastWarningSnooze = lastWarningSnooze;
1030e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        this.lastLimitSnooze = lastLimitSnooze;
104bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        this.lastRapidSnooze = lastRapidSnooze;
105f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey        this.metered = metered;
106837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey        this.inferred = inferred;
10721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
10821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
10917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    private NetworkPolicy(Parcel source) {
11017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        template = source.readParcelable(null);
11117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        cycleRule = source.readParcelable(null);
11217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        warningBytes = source.readLong();
11317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        limitBytes = source.readLong();
11417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        lastWarningSnooze = source.readLong();
11517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        lastLimitSnooze = source.readLong();
116bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        lastRapidSnooze = source.readLong();
11717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        metered = source.readInt() != 0;
11817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        inferred = source.readInt() != 0;
11921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
12021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1219bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey    @Override
12221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void writeToParcel(Parcel dest, int flags) {
1231b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        dest.writeParcelable(template, flags);
12417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        dest.writeParcelable(cycleRule, flags);
12521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        dest.writeLong(warningBytes);
12621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        dest.writeLong(limitBytes);
1270e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        dest.writeLong(lastWarningSnooze);
1280e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        dest.writeLong(lastLimitSnooze);
129bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        dest.writeLong(lastRapidSnooze);
130f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey        dest.writeInt(metered ? 1 : 0);
131837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey        dest.writeInt(inferred ? 1 : 0);
13221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
13321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1349bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey    @Override
13521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public int describeContents() {
13621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        return 0;
13721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
13821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1390fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey    public Iterator<Range<ZonedDateTime>> cycleIterator() {
14017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        return cycleRule.cycleIterator();
14117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    }
14217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey
14350e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey    /**
1440e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey     * Test if given measurement is over {@link #warningBytes}.
1450e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey     */
1460e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    public boolean isOverWarning(long totalBytes) {
1470e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        return warningBytes != WARNING_DISABLED && totalBytes >= warningBytes;
1480e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    }
1490e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
1500e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    /**
15150e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey     * Test if given measurement is near enough to {@link #limitBytes} to be
15250e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey     * considered over-limit.
15350e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey     */
15450e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey    public boolean isOverLimit(long totalBytes) {
15550e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey        // over-estimate, since kernel will trigger limit once first packet
15650e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey        // trips over limit.
15750e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey        totalBytes += 2 * DEFAULT_MTU;
15850e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey        return limitBytes != LIMIT_DISABLED && totalBytes >= limitBytes;
15950e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey    }
16050e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey
1610e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    /**
1620e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey     * Clear any existing snooze values, setting to {@link #SNOOZE_NEVER}.
1630e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey     */
1640e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    public void clearSnooze() {
1650e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        lastWarningSnooze = SNOOZE_NEVER;
1660e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        lastLimitSnooze = SNOOZE_NEVER;
167bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        lastRapidSnooze = SNOOZE_NEVER;
1680e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    }
1690e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
1708fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    /**
1718fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * Test if this policy has a cycle defined, after which usage should reset.
1728fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     */
1738fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    public boolean hasCycle() {
17417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        return cycleRule.cycleIterator().hasNext();
1758fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    }
1768fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey
1779bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey    @Override
17821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public int compareTo(NetworkPolicy another) {
17922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (another == null || another.limitBytes == LIMIT_DISABLED) {
18022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            // other value is missing or disabled; we win
18121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return -1;
18222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        }
18322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (limitBytes == LIMIT_DISABLED || another.limitBytes < limitBytes) {
18422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            // we're disabled or other limit is smaller; they win
18521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return 1;
18621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
18722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        return 0;
18821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
18921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
19021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
19141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public int hashCode() {
19217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        return Objects.hash(template, cycleRule, warningBytes, limitBytes,
193bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey                lastWarningSnooze, lastLimitSnooze, lastRapidSnooze, metered, inferred);
19441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
19541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
19641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
19741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public boolean equals(Object obj) {
19841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (obj instanceof NetworkPolicy) {
19941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final NetworkPolicy other = (NetworkPolicy) obj;
20017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            return warningBytes == other.warningBytes
2010e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                    && limitBytes == other.limitBytes
2020e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                    && lastWarningSnooze == other.lastWarningSnooze
203bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey                    && lastLimitSnooze == other.lastLimitSnooze
204bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey                    && lastRapidSnooze == other.lastRapidSnooze
205bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey                    && metered == other.metered
206837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                    && inferred == other.inferred
20717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                    && Objects.equals(template, other.template)
20817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                    && Objects.equals(cycleRule, other.cycleRule);
20941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
21041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        return false;
21141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
21241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
21341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
21421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public String toString() {
21517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        return new StringBuilder("NetworkPolicy{")
21617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append("template=").append(template)
21717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append(" cycleRule=").append(cycleRule)
21817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append(" warningBytes=").append(warningBytes)
21917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append(" limitBytes=").append(limitBytes)
22017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append(" lastWarningSnooze=").append(lastWarningSnooze)
22117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append(" lastLimitSnooze=").append(lastLimitSnooze)
222bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey                .append(" lastRapidSnooze=").append(lastRapidSnooze)
22317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append(" metered=").append(metered)
22417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append(" inferred=").append(inferred)
22517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append("}").toString();
22621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
22721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
22821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() {
2299bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey        @Override
23021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public NetworkPolicy createFromParcel(Parcel in) {
23121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return new NetworkPolicy(in);
23221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
23321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
2349bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey        @Override
23521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public NetworkPolicy[] newArray(int size) {
23621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return new NetworkPolicy[size];
23721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
23821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    };
239adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
240adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    public byte[] getBytesForBackup() throws IOException {
241adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        ByteArrayOutputStream baos = new ByteArrayOutputStream();
242adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        DataOutputStream out = new DataOutputStream(baos);
243adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
244bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        out.writeInt(VERSION_RAPID);
245adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.write(template.getBytesForBackup());
24617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        cycleRule.writeToStream(out);
247adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.writeLong(warningBytes);
248adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.writeLong(limitBytes);
249adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.writeLong(lastWarningSnooze);
250adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.writeLong(lastLimitSnooze);
251bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        out.writeLong(lastRapidSnooze);
252adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.writeInt(metered ? 1 : 0);
253adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.writeInt(inferred ? 1 : 0);
254adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        return baos.toByteArray();
255adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    }
256adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
257adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    public static NetworkPolicy getNetworkPolicyFromBackup(DataInputStream in) throws IOException,
258adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy            BackupUtils.BadVersionException {
25917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        final int version = in.readInt();
26047f5c9c55f791fad17c1d49703811602c75a02b6Annie Meng        if (version < VERSION_INIT || version > VERSION_RAPID) {
261bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            throw new BackupUtils.BadVersionException("Unknown backup version: " + version);
262bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        }
263bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey
264bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
265bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final RecurrenceRule cycleRule;
266bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        if (version >= VERSION_RULE) {
267bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            cycleRule = new RecurrenceRule(in);
268bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        } else {
269bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            final int cycleDay = in.readInt();
270bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            final String cycleTimezone = BackupUtils.readString(in);
271bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            cycleRule = buildRule(cycleDay, ZoneId.of(cycleTimezone));
272bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        }
273bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final long warningBytes = in.readLong();
274bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final long limitBytes = in.readLong();
275bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final long lastWarningSnooze = in.readLong();
276bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final long lastLimitSnooze = in.readLong();
277bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final long lastRapidSnooze;
278bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        if (version >= VERSION_RAPID) {
279bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            lastRapidSnooze = in.readLong();
280bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        } else {
281bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey            lastRapidSnooze = SNOOZE_NEVER;
282adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        }
283bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final boolean metered = in.readInt() == 1;
284bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        final boolean inferred = in.readInt() == 1;
285bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey        return new NetworkPolicy(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze,
286bfb43ea9e684e62644cecf7f037c4087bfaa1e0fJeff Sharkey                lastLimitSnooze, lastRapidSnooze, metered, inferred);
287adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    }
28821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey}
289