153313d7e8153982f842910118371e1dc061248cdJeff Sharkey/*
253313d7e8153982f842910118371e1dc061248cdJeff Sharkey * Copyright (C) 2017 The Android Open Source Project
353313d7e8153982f842910118371e1dc061248cdJeff Sharkey *
453313d7e8153982f842910118371e1dc061248cdJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
553313d7e8153982f842910118371e1dc061248cdJeff Sharkey * you may not use this file except in compliance with the License.
653313d7e8153982f842910118371e1dc061248cdJeff Sharkey * You may obtain a copy of the License at
753313d7e8153982f842910118371e1dc061248cdJeff Sharkey *
853313d7e8153982f842910118371e1dc061248cdJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
953313d7e8153982f842910118371e1dc061248cdJeff Sharkey *
1053313d7e8153982f842910118371e1dc061248cdJeff Sharkey * Unless required by applicable law or agreed to in writing, software
1153313d7e8153982f842910118371e1dc061248cdJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
1253313d7e8153982f842910118371e1dc061248cdJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1353313d7e8153982f842910118371e1dc061248cdJeff Sharkey * See the License for the specific language governing permissions and
1453313d7e8153982f842910118371e1dc061248cdJeff Sharkey * limitations under the License.
1553313d7e8153982f842910118371e1dc061248cdJeff Sharkey */
1653313d7e8153982f842910118371e1dc061248cdJeff Sharkey
1753313d7e8153982f842910118371e1dc061248cdJeff Sharkeypackage android.telephony;
1853313d7e8153982f842910118371e1dc061248cdJeff Sharkey
1953313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport android.annotation.BytesLong;
2053313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport android.annotation.CurrentTimeMillisLong;
2153313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport android.annotation.IntDef;
2217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport android.annotation.NonNull;
2353313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport android.annotation.Nullable;
24b7479988d248add39ba6ce1fe71dea6f810fd54fJeff Sharkeyimport android.annotation.SystemApi;
2553313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport android.os.Parcel;
2653313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport android.os.Parcelable;
270fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkeyimport android.util.Range;
2817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport android.util.RecurrenceRule;
2953313d7e8153982f842910118371e1dc061248cdJeff Sharkey
3017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport com.android.internal.util.Preconditions;
3153313d7e8153982f842910118371e1dc061248cdJeff Sharkey
3253313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport java.lang.annotation.Retention;
3353313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport java.lang.annotation.RetentionPolicy;
3417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkeyimport java.time.Period;
3553313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport java.time.ZonedDateTime;
3653313d7e8153982f842910118371e1dc061248cdJeff Sharkeyimport java.util.Iterator;
37003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkeyimport java.util.Objects;
3853313d7e8153982f842910118371e1dc061248cdJeff Sharkey
3917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey/**
4017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey * Description of a billing relationship plan between a carrier and a specific
4117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey * subscriber. This information is used to present more useful UI to users, such
4217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey * as explaining how much mobile data they have remaining, and what will happen
4317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey * when they run out.
4417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey *
4517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey * @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
4617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey * @see SubscriptionManager#getSubscriptionPlans(int)
4717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey */
48b7479988d248add39ba6ce1fe71dea6f810fd54fJeff Sharkey@SystemApi
4953313d7e8153982f842910118371e1dc061248cdJeff Sharkeypublic final class SubscriptionPlan implements Parcelable {
5053313d7e8153982f842910118371e1dc061248cdJeff Sharkey    /** {@hide} */
5153313d7e8153982f842910118371e1dc061248cdJeff Sharkey    @IntDef(prefix = "LIMIT_BEHAVIOR_", value = {
5253313d7e8153982f842910118371e1dc061248cdJeff Sharkey            LIMIT_BEHAVIOR_UNKNOWN,
5353313d7e8153982f842910118371e1dc061248cdJeff Sharkey            LIMIT_BEHAVIOR_DISABLED,
5453313d7e8153982f842910118371e1dc061248cdJeff Sharkey            LIMIT_BEHAVIOR_BILLED,
5553313d7e8153982f842910118371e1dc061248cdJeff Sharkey            LIMIT_BEHAVIOR_THROTTLED,
5653313d7e8153982f842910118371e1dc061248cdJeff Sharkey    })
5753313d7e8153982f842910118371e1dc061248cdJeff Sharkey    @Retention(RetentionPolicy.SOURCE)
5853313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public @interface LimitBehavior {}
5953313d7e8153982f842910118371e1dc061248cdJeff Sharkey
6017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** When a resource limit is hit, the behavior is unknown. */
6153313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public static final int LIMIT_BEHAVIOR_UNKNOWN = -1;
6217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** When a resource limit is hit, access is disabled. */
6353313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public static final int LIMIT_BEHAVIOR_DISABLED = 0;
6417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** When a resource limit is hit, the user is billed automatically. */
6553313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public static final int LIMIT_BEHAVIOR_BILLED = 1;
6617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** When a resource limit is hit, access is throttled to a slower rate. */
6753313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public static final int LIMIT_BEHAVIOR_THROTTLED = 2;
6853313d7e8153982f842910118371e1dc061248cdJeff Sharkey
6917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** Value indicating a number of bytes is unknown. */
7053313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public static final long BYTES_UNKNOWN = -1;
7117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** Value indicating a number of bytes is unlimited. */
7217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    public static final long BYTES_UNLIMITED = Long.MAX_VALUE;
7317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey
7417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** Value indicating a timestamp is unknown. */
7553313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public static final long TIME_UNKNOWN = -1;
7653313d7e8153982f842910118371e1dc061248cdJeff Sharkey
7717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    private final RecurrenceRule cycleRule;
7853313d7e8153982f842910118371e1dc061248cdJeff Sharkey    private CharSequence title;
7953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    private CharSequence summary;
8053313d7e8153982f842910118371e1dc061248cdJeff Sharkey    private long dataLimitBytes = BYTES_UNKNOWN;
8153313d7e8153982f842910118371e1dc061248cdJeff Sharkey    private int dataLimitBehavior = LIMIT_BEHAVIOR_UNKNOWN;
8253313d7e8153982f842910118371e1dc061248cdJeff Sharkey    private long dataUsageBytes = BYTES_UNKNOWN;
8353313d7e8153982f842910118371e1dc061248cdJeff Sharkey    private long dataUsageTime = TIME_UNKNOWN;
8453313d7e8153982f842910118371e1dc061248cdJeff Sharkey
8517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    private SubscriptionPlan(RecurrenceRule cycleRule) {
8617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        this.cycleRule = Preconditions.checkNotNull(cycleRule);
8753313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
8853313d7e8153982f842910118371e1dc061248cdJeff Sharkey
8953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    private SubscriptionPlan(Parcel source) {
9017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        cycleRule = source.readParcelable(null);
9153313d7e8153982f842910118371e1dc061248cdJeff Sharkey        title = source.readCharSequence();
9253313d7e8153982f842910118371e1dc061248cdJeff Sharkey        summary = source.readCharSequence();
9353313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dataLimitBytes = source.readLong();
9453313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dataLimitBehavior = source.readInt();
9553313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dataUsageBytes = source.readLong();
9653313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dataUsageTime = source.readLong();
9753313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
9853313d7e8153982f842910118371e1dc061248cdJeff Sharkey
9953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    @Override
10053313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public int describeContents() {
10153313d7e8153982f842910118371e1dc061248cdJeff Sharkey        return 0;
10253313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
10353313d7e8153982f842910118371e1dc061248cdJeff Sharkey
10453313d7e8153982f842910118371e1dc061248cdJeff Sharkey    @Override
10553313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public void writeToParcel(Parcel dest, int flags) {
10617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        dest.writeParcelable(cycleRule, flags);
10753313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dest.writeCharSequence(title);
10853313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dest.writeCharSequence(summary);
10953313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dest.writeLong(dataLimitBytes);
11053313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dest.writeInt(dataLimitBehavior);
11153313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dest.writeLong(dataUsageBytes);
11253313d7e8153982f842910118371e1dc061248cdJeff Sharkey        dest.writeLong(dataUsageTime);
11353313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
11453313d7e8153982f842910118371e1dc061248cdJeff Sharkey
11553313d7e8153982f842910118371e1dc061248cdJeff Sharkey    @Override
11653313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public String toString() {
11717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        return new StringBuilder("SubscriptionPlan{")
11817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append("cycleRule=").append(cycleRule)
11953313d7e8153982f842910118371e1dc061248cdJeff Sharkey                .append(" title=").append(title)
12053313d7e8153982f842910118371e1dc061248cdJeff Sharkey                .append(" summary=").append(summary)
12153313d7e8153982f842910118371e1dc061248cdJeff Sharkey                .append(" dataLimitBytes=").append(dataLimitBytes)
12253313d7e8153982f842910118371e1dc061248cdJeff Sharkey                .append(" dataLimitBehavior=").append(dataLimitBehavior)
12353313d7e8153982f842910118371e1dc061248cdJeff Sharkey                .append(" dataUsageBytes=").append(dataUsageBytes)
12453313d7e8153982f842910118371e1dc061248cdJeff Sharkey                .append(" dataUsageTime=").append(dataUsageTime)
12517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                .append("}").toString();
12653313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
12753313d7e8153982f842910118371e1dc061248cdJeff Sharkey
128003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey    @Override
129003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey    public int hashCode() {
130003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey        return Objects.hash(cycleRule, title, summary, dataLimitBytes, dataLimitBehavior,
131003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey                dataUsageBytes, dataUsageTime);
132003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey    }
133003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey
134003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey    @Override
135003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey    public boolean equals(Object obj) {
136003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey        if (obj instanceof SubscriptionPlan) {
137003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey            final SubscriptionPlan other = (SubscriptionPlan) obj;
138003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey            return Objects.equals(cycleRule, other.cycleRule)
139003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey                    && Objects.equals(title, other.title)
140003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey                    && Objects.equals(summary, other.summary)
141003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey                    && dataLimitBytes == other.dataLimitBytes
142003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey                    && dataLimitBehavior == other.dataLimitBehavior
143003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey                    && dataUsageBytes == other.dataUsageBytes
144003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey                    && dataUsageTime == other.dataUsageTime;
145003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey        }
146003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey        return false;
147003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey    }
148003d3e61e6f6ed47e1d6301af302ce69557ba5faJeff Sharkey
14953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public static final Parcelable.Creator<SubscriptionPlan> CREATOR = new Parcelable.Creator<SubscriptionPlan>() {
15053313d7e8153982f842910118371e1dc061248cdJeff Sharkey        @Override
15153313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public SubscriptionPlan createFromParcel(Parcel source) {
15253313d7e8153982f842910118371e1dc061248cdJeff Sharkey            return new SubscriptionPlan(source);
15353313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
15453313d7e8153982f842910118371e1dc061248cdJeff Sharkey
15553313d7e8153982f842910118371e1dc061248cdJeff Sharkey        @Override
15653313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public SubscriptionPlan[] newArray(int size) {
15753313d7e8153982f842910118371e1dc061248cdJeff Sharkey            return new SubscriptionPlan[size];
15853313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
15953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    };
16053313d7e8153982f842910118371e1dc061248cdJeff Sharkey
16117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** {@hide} */
16217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    public @NonNull RecurrenceRule getCycleRule() {
16317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        return cycleRule;
16453313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
16553313d7e8153982f842910118371e1dc061248cdJeff Sharkey
16617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** Return the short title of this plan. */
16753313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public @Nullable CharSequence getTitle() {
16853313d7e8153982f842910118371e1dc061248cdJeff Sharkey        return title;
16953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
17053313d7e8153982f842910118371e1dc061248cdJeff Sharkey
17117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /** Return the short summary of this plan. */
17253313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public @Nullable CharSequence getSummary() {
17353313d7e8153982f842910118371e1dc061248cdJeff Sharkey        return summary;
17453313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
17553313d7e8153982f842910118371e1dc061248cdJeff Sharkey
17617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /**
17717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * Return the usage threshold at which data access changes according to
17817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * {@link #getDataLimitBehavior()}.
17917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     */
18053313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public @BytesLong long getDataLimitBytes() {
18153313d7e8153982f842910118371e1dc061248cdJeff Sharkey        return dataLimitBytes;
18253313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
18353313d7e8153982f842910118371e1dc061248cdJeff Sharkey
18417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /**
18517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * Return the behavior of data access when usage reaches
18617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * {@link #getDataLimitBytes()}.
18717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     */
18853313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public @LimitBehavior int getDataLimitBehavior() {
18953313d7e8153982f842910118371e1dc061248cdJeff Sharkey        return dataLimitBehavior;
19053313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
19153313d7e8153982f842910118371e1dc061248cdJeff Sharkey
19217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /**
19317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * Return a snapshot of currently known mobile data usage at
19417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * {@link #getDataUsageTime()}.
19517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     */
19653313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public @BytesLong long getDataUsageBytes() {
19753313d7e8153982f842910118371e1dc061248cdJeff Sharkey        return dataUsageBytes;
19853313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
19953313d7e8153982f842910118371e1dc061248cdJeff Sharkey
20017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /**
20117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * Return the time at which {@link #getDataUsageBytes()} was valid.
20217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     */
20353313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public @CurrentTimeMillisLong long getDataUsageTime() {
20453313d7e8153982f842910118371e1dc061248cdJeff Sharkey        return dataUsageTime;
20553313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
20653313d7e8153982f842910118371e1dc061248cdJeff Sharkey
20753313d7e8153982f842910118371e1dc061248cdJeff Sharkey    /**
20817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * Return an iterator that will return all valid data usage cycles based on
20917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * any recurrence rules. The iterator starts from the currently active cycle
21017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * and walks backwards through time.
21153313d7e8153982f842910118371e1dc061248cdJeff Sharkey     */
2120fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey    public Iterator<Range<ZonedDateTime>> cycleIterator() {
21317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        return cycleRule.cycleIterator();
21453313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
21553313d7e8153982f842910118371e1dc061248cdJeff Sharkey
21617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey    /**
21717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     * Builder for a {@link SubscriptionPlan}.
21817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey     */
21953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    public static class Builder {
22053313d7e8153982f842910118371e1dc061248cdJeff Sharkey        private final SubscriptionPlan plan;
22153313d7e8153982f842910118371e1dc061248cdJeff Sharkey
22217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        /** {@hide} */
22317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        public Builder(ZonedDateTime start, ZonedDateTime end, Period period) {
22417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            plan = new SubscriptionPlan(new RecurrenceRule(start, end, period));
22553313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
22653313d7e8153982f842910118371e1dc061248cdJeff Sharkey
22717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        /**
22817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         * Start defining a {@link SubscriptionPlan} that covers a very specific
22917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         * window of time, and never automatically recurs.
2300fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         *
2310fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * @param start The exact time at which the plan starts.
2320fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * @param end The exact time at which the plan ends.
23317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         */
23453313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public static Builder createNonrecurring(ZonedDateTime start, ZonedDateTime end) {
23553313d7e8153982f842910118371e1dc061248cdJeff Sharkey            if (!end.isAfter(start)) {
23653313d7e8153982f842910118371e1dc061248cdJeff Sharkey                throw new IllegalArgumentException(
23753313d7e8153982f842910118371e1dc061248cdJeff Sharkey                        "End " + end + " isn't after start " + start);
23853313d7e8153982f842910118371e1dc061248cdJeff Sharkey            }
23917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            return new Builder(start, end, null);
24053313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
24153313d7e8153982f842910118371e1dc061248cdJeff Sharkey
24217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        /**
2430fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * Start defining a {@link SubscriptionPlan} that starts at a specific
2440fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * time, and automatically recurs after each specific period of time,
2450fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * repeating indefinitely.
2460fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * <p>
2470fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * When the given period is set to exactly one month, the plan will
2480fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * always recur on the day of the month defined by
2490fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * {@link ZonedDateTime#getDayOfMonth()}. When a particular month ends
2500fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * before this day, the plan will recur on the last possible instant of
2510fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * that month.
2520fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         *
2530fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * @param start The exact time at which the plan starts.
2540fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey         * @param period The period after which the plan automatically recurs.
25517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         */
2560fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        public static Builder createRecurring(ZonedDateTime start, Period period) {
2570a5570d49df7d438b618616e439192f3c216cfe8Jeff Sharkey            if (period.isZero() || period.isNegative()) {
2580a5570d49df7d438b618616e439192f3c216cfe8Jeff Sharkey                throw new IllegalArgumentException("Period " + period + " must be positive");
2590a5570d49df7d438b618616e439192f3c216cfe8Jeff Sharkey            }
2600fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey            return new Builder(start, null, period);
2610fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        }
2620fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey
2630fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        /** {@hide} */
2640fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        @SystemApi
2650fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        @Deprecated
26653313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public static Builder createRecurringMonthly(ZonedDateTime start) {
26717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            return new Builder(start, null, Period.ofMonths(1));
26853313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
26953313d7e8153982f842910118371e1dc061248cdJeff Sharkey
2700fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        /** {@hide} */
2710fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        @SystemApi
2720fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        @Deprecated
27353313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public static Builder createRecurringWeekly(ZonedDateTime start) {
27417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            return new Builder(start, null, Period.ofDays(7));
27553313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
27653313d7e8153982f842910118371e1dc061248cdJeff Sharkey
2770fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        /** {@hide} */
2780fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        @SystemApi
2790fc6d03b628c8cbe80e3c2c14aaf8c6944b32d1eJeff Sharkey        @Deprecated
28053313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public static Builder createRecurringDaily(ZonedDateTime start) {
28117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            return new Builder(start, null, Period.ofDays(1));
28253313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
28353313d7e8153982f842910118371e1dc061248cdJeff Sharkey
28453313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public SubscriptionPlan build() {
28553313d7e8153982f842910118371e1dc061248cdJeff Sharkey            return plan;
28653313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
28753313d7e8153982f842910118371e1dc061248cdJeff Sharkey
28817bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        /** Set the short title of this plan. */
28953313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public Builder setTitle(@Nullable CharSequence title) {
29053313d7e8153982f842910118371e1dc061248cdJeff Sharkey            plan.title = title;
29153313d7e8153982f842910118371e1dc061248cdJeff Sharkey            return this;
29253313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
29353313d7e8153982f842910118371e1dc061248cdJeff Sharkey
29417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        /** Set the short summary of this plan. */
29553313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public Builder setSummary(@Nullable CharSequence summary) {
29653313d7e8153982f842910118371e1dc061248cdJeff Sharkey            plan.summary = summary;
29753313d7e8153982f842910118371e1dc061248cdJeff Sharkey            return this;
29853313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
29953313d7e8153982f842910118371e1dc061248cdJeff Sharkey
30017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        /**
30117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         * Set the usage threshold at which data access changes.
30217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         *
30317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         * @param dataLimitBytes the usage threshold at which data access
30417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         *            changes
30517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         * @param dataLimitBehavior the behavior of data access when usage
30617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         *            reaches the threshold
30717bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         */
30853313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public Builder setDataLimit(@BytesLong long dataLimitBytes,
30953313d7e8153982f842910118371e1dc061248cdJeff Sharkey                @LimitBehavior int dataLimitBehavior) {
31017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            if (dataLimitBytes < 0) {
31117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                throw new IllegalArgumentException("Limit bytes must be positive");
31217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            }
31317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            if (dataLimitBehavior < 0) {
31417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                throw new IllegalArgumentException("Limit behavior must be defined");
31553313d7e8153982f842910118371e1dc061248cdJeff Sharkey            }
31653313d7e8153982f842910118371e1dc061248cdJeff Sharkey            plan.dataLimitBytes = dataLimitBytes;
31753313d7e8153982f842910118371e1dc061248cdJeff Sharkey            plan.dataLimitBehavior = dataLimitBehavior;
31853313d7e8153982f842910118371e1dc061248cdJeff Sharkey            return this;
31953313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
32053313d7e8153982f842910118371e1dc061248cdJeff Sharkey
32117bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey        /**
32217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         * Set a snapshot of currently known mobile data usage.
32317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         *
32417bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         * @param dataUsageBytes the currently known mobile data usage
32517bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         * @param dataUsageTime the time at which this snapshot was valid
32617bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey         */
32753313d7e8153982f842910118371e1dc061248cdJeff Sharkey        public Builder setDataUsage(@BytesLong long dataUsageBytes,
32853313d7e8153982f842910118371e1dc061248cdJeff Sharkey                @CurrentTimeMillisLong long dataUsageTime) {
32917bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            if (dataUsageBytes < 0) {
33017bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                throw new IllegalArgumentException("Usage bytes must be positive");
33153313d7e8153982f842910118371e1dc061248cdJeff Sharkey            }
33217bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey            if (dataUsageTime < 0) {
33317bebd2fd7d3af0bc648172da6ae36f8b55ad7afJeff Sharkey                throw new IllegalArgumentException("Usage time must be positive");
33453313d7e8153982f842910118371e1dc061248cdJeff Sharkey            }
33553313d7e8153982f842910118371e1dc061248cdJeff Sharkey            plan.dataUsageBytes = dataUsageBytes;
33653313d7e8153982f842910118371e1dc061248cdJeff Sharkey            plan.dataUsageTime = dataUsageTime;
33753313d7e8153982f842910118371e1dc061248cdJeff Sharkey            return this;
33853313d7e8153982f842910118371e1dc061248cdJeff Sharkey        }
33953313d7e8153982f842910118371e1dc061248cdJeff Sharkey    }
34053313d7e8153982f842910118371e1dc061248cdJeff Sharkey}
341