diff options
13 files changed, 111 insertions, 68 deletions
diff --git a/api/current.txt b/api/current.txt index 5b5bd24168b0..5931b314fa09 100644 --- a/api/current.txt +++ b/api/current.txt @@ -42407,7 +42407,7 @@ package android.telephony { } public final class SubscriptionPlan implements android.os.Parcelable { - method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator(); + method public java.util.Iterator<android.util.Range<java.time.ZonedDateTime>> cycleIterator(); method public int describeContents(); method public int getDataLimitBehavior(); method public long getDataLimitBytes(); @@ -42429,9 +42429,7 @@ package android.telephony { public static class SubscriptionPlan.Builder { method public android.telephony.SubscriptionPlan build(); method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime); - method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime); - method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime); - method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime); + method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period); method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int); method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long); method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence); diff --git a/api/system-current.txt b/api/system-current.txt index 76a71cd7c44e..0bcb1c24ff34 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5191,7 +5191,7 @@ package android.telephony { } public final class SubscriptionPlan implements android.os.Parcelable { - method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator(); + method public java.util.Iterator<android.util.Range<java.time.ZonedDateTime>> cycleIterator(); method public int describeContents(); method public int getDataLimitBehavior(); method public long getDataLimitBytes(); @@ -5213,9 +5213,10 @@ package android.telephony { public static class SubscriptionPlan.Builder { method public android.telephony.SubscriptionPlan build(); method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime); - method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime); - method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime); - method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime); + method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period); + method public static deprecated android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime); + method public static deprecated android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime); + method public static deprecated android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime); method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int); method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long); method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence); diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java index 1a28732e874e..e84c85ee8edb 100644 --- a/core/java/android/net/NetworkPolicy.java +++ b/core/java/android/net/NetworkPolicy.java @@ -19,7 +19,7 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; import android.util.BackupUtils; -import android.util.Pair; +import android.util.Range; import android.util.RecurrenceRule; import com.android.internal.util.Preconditions; @@ -136,7 +136,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { return 0; } - public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() { + public Iterator<Range<ZonedDateTime>> cycleIterator() { return cycleRule.cycleIterator(); } diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index bf6b7e09f529..6546c391799b 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -31,6 +31,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.DebugUtils; import android.util.Pair; +import android.util.Range; import com.google.android.collect.Sets; @@ -258,8 +259,21 @@ public class NetworkPolicyManager { } /** {@hide} */ + @Deprecated public static Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator(NetworkPolicy policy) { - return policy.cycleIterator(); + final Iterator<Range<ZonedDateTime>> it = policy.cycleIterator(); + return new Iterator<Pair<ZonedDateTime, ZonedDateTime>>() { + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public Pair<ZonedDateTime, ZonedDateTime> next() { + final Range<ZonedDateTime> r = it.next(); + return Pair.create(r.getLower(), r.getUpper()); + } + }; } /** diff --git a/core/java/android/util/RecurrenceRule.java b/core/java/android/util/RecurrenceRule.java index 9f115eba442c..975ad488bf54 100644 --- a/core/java/android/util/RecurrenceRule.java +++ b/core/java/android/util/RecurrenceRule.java @@ -158,7 +158,7 @@ public class RecurrenceRule implements Parcelable { && period.getDays() == 0; } - public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() { + public Iterator<Range<ZonedDateTime>> cycleIterator() { if (period != null) { return new RecurringIterator(); } else { @@ -166,7 +166,7 @@ public class RecurrenceRule implements Parcelable { } } - private class NonrecurringIterator implements Iterator<Pair<ZonedDateTime, ZonedDateTime>> { + private class NonrecurringIterator implements Iterator<Range<ZonedDateTime>> { boolean hasNext; public NonrecurringIterator() { @@ -179,13 +179,13 @@ public class RecurrenceRule implements Parcelable { } @Override - public Pair<ZonedDateTime, ZonedDateTime> next() { + public Range<ZonedDateTime> next() { hasNext = false; - return new Pair<>(start, end); + return new Range<>(start, end); } } - private class RecurringIterator implements Iterator<Pair<ZonedDateTime, ZonedDateTime>> { + private class RecurringIterator implements Iterator<Range<ZonedDateTime>> { int i; ZonedDateTime cycleStart; ZonedDateTime cycleEnd; @@ -231,12 +231,12 @@ public class RecurrenceRule implements Parcelable { } @Override - public Pair<ZonedDateTime, ZonedDateTime> next() { + public Range<ZonedDateTime> next() { if (LOGD) Log.d(TAG, "Cycle " + i + " from " + cycleStart + " to " + cycleEnd); - Pair<ZonedDateTime, ZonedDateTime> p = new Pair<>(cycleStart, cycleEnd); + Range<ZonedDateTime> r = new Range<>(cycleStart, cycleEnd); i--; updateCycle(); - return p; + return r; } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index da15506ecac8..c5ab2e6887b1 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -487,6 +487,7 @@ <protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" /> <protected-broadcast android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" /> <protected-broadcast android:name="android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION" /> + <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_PLANS_CHANGED" /> <protected-broadcast android:name="com.android.bluetooth.btservice.action.ALARM_WAKEUP" /> <protected-broadcast android:name="com.android.server.action.NETWORK_STATS_POLL" /> diff --git a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java index 42b6048b533a..39d492d65415 100644 --- a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java +++ b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java @@ -57,13 +57,13 @@ public class RecurrenceRuleTest extends TestCase { assertTrue(r.isMonthly()); - final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator(); + final Iterator<Range<ZonedDateTime>> it = r.cycleIterator(); assertTrue(it.hasNext()); - assertEquals(Pair.create( + assertEquals(new Range<>( ZonedDateTime.parse("2015-11-14T00:00:00.00Z"), ZonedDateTime.parse("2015-12-14T00:00:00.00Z")), it.next()); assertTrue(it.hasNext()); - assertEquals(Pair.create( + assertEquals(new Range<>( ZonedDateTime.parse("2015-10-14T00:00:00.00Z"), ZonedDateTime.parse("2015-11-14T00:00:00.00Z")), it.next()); } @@ -77,13 +77,13 @@ public class RecurrenceRuleTest extends TestCase { assertFalse(r.isMonthly()); - final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator(); + final Iterator<Range<ZonedDateTime>> it = r.cycleIterator(); assertTrue(it.hasNext()); - assertEquals(Pair.create( + assertEquals(new Range<>( ZonedDateTime.parse("2010-11-17T00:11:00.00Z"), ZonedDateTime.parse("2010-11-20T00:11:00.00Z")), it.next()); assertTrue(it.hasNext()); - assertEquals(Pair.create( + assertEquals(new Range<>( ZonedDateTime.parse("2010-11-14T00:11:00.00Z"), ZonedDateTime.parse("2010-11-17T00:11:00.00Z")), it.next()); assertFalse(it.hasNext()); @@ -98,9 +98,9 @@ public class RecurrenceRuleTest extends TestCase { assertFalse(r.isMonthly()); - final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator(); + final Iterator<Range<ZonedDateTime>> it = r.cycleIterator(); assertTrue(it.hasNext()); - assertEquals(Pair.create( + assertEquals(new Range<>( ZonedDateTime.parse("2010-11-14T00:11:00.000Z"), ZonedDateTime.parse("2010-11-20T00:11:00.000Z")), it.next()); assertFalse(it.hasNext()); @@ -112,7 +112,7 @@ public class RecurrenceRuleTest extends TestCase { assertFalse(r.isMonthly()); - final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator(); + final Iterator<Range<ZonedDateTime>> it = r.cycleIterator(); assertFalse(it.hasNext()); } @@ -122,22 +122,22 @@ public class RecurrenceRuleTest extends TestCase { ZonedDateTime.parse("2030-01-31T00:00:00.000Z"), Period.ofMonths(1)); - final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator(); + final Iterator<Range<ZonedDateTime>> it = r.cycleIterator(); ZonedDateTime lastStart = null; int months = 0; while (it.hasNext()) { - final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next(); + final Range<ZonedDateTime> cycle = it.next(); // Make sure cycle has reasonable length - final long length = cycle.second.toEpochSecond() - cycle.first.toEpochSecond(); + final long length = cycle.getUpper().toEpochSecond() - cycle.getLower().toEpochSecond(); assertTrue(cycle + " must be more than 4 weeks", length >= 2419200); assertTrue(cycle + " must be less than 5 weeks", length <= 3024000); // Make sure we have no gaps if (lastStart != null) { - assertEquals(lastStart, cycle.second); + assertEquals(lastStart, cycle.getUpper()); } - lastStart = cycle.first; + lastStart = cycle.getLower(); months++; } diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java index 3868ea6a1056..906a6a3dd1cc 100644 --- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java +++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java @@ -57,6 +57,7 @@ import android.provider.Settings; import android.telephony.TelephonyManager; import android.util.DebugUtils; import android.util.Pair; +import android.util.Range; import android.util.Slog; import com.android.internal.R; @@ -266,9 +267,9 @@ public class MultipathPolicyTracker { } private long getRemainingDailyBudget(long limitBytes, - Pair<ZonedDateTime, ZonedDateTime> cycle) { - final long start = cycle.first.toInstant().toEpochMilli(); - final long end = cycle.second.toInstant().toEpochMilli(); + Range<ZonedDateTime> cycle) { + final long start = cycle.getLower().toInstant().toEpochMilli(); + final long end = cycle.getUpper().toInstant().toEpochMilli(); final long totalBytes = getNetworkTotalBytes(start, end); final long remainingBytes = totalBytes == -1 ? 0 : Math.max(0, limitBytes - totalBytes); // 1 + ((end - now - 1) / millisInDay with integers is equivalent to: @@ -389,7 +390,7 @@ public class MultipathPolicyTracker { private static boolean hasActiveCycle(NetworkPolicy policy) { return policy.hasCycle() && policy.lastLimitSnooze < - policy.cycleIterator().next().first.toInstant().toEpochMilli(); + policy.cycleIterator().next().getLower().toInstant().toEpochMilli(); } // Only ever updated on the handler thread. Accessed from other binder threads to retrieve diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 1782ae5293d0..98f69d130f3b 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -195,6 +195,7 @@ import android.util.AtomicFile; import android.util.DataUnit; import android.util.Log; import android.util.Pair; +import android.util.Range; import android.util.RecurrenceRule; import android.util.Slog; import android.util.SparseArray; @@ -1777,11 +1778,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { quotaBytes = quotaUnlimited; } else { // Limited data; let's only use 10% of remaining budget - final Pair<ZonedDateTime, ZonedDateTime> cycle = plan.cycleIterator().next(); - final long start = cycle.first.toInstant().toEpochMilli(); - final long end = cycle.second.toInstant().toEpochMilli(); + final Range<ZonedDateTime> cycle = plan.cycleIterator().next(); + final long start = cycle.getLower().toInstant().toEpochMilli(); + final long end = cycle.getUpper().toInstant().toEpochMilli(); final Instant now = mClock.instant(); - final long startOfDay = ZonedDateTime.ofInstant(now, cycle.first.getZone()) + final long startOfDay = ZonedDateTime.ofInstant(now, cycle.getLower().getZone()) .truncatedTo(ChronoUnit.DAYS) .toInstant().toEpochMilli(); final long totalBytes = getTotalBytes( diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 2ef754e2ba6a..ab525237db5c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -47,7 +47,7 @@ import android.util.ArrayMap; import android.util.AtomicFile; import android.util.IntArray; import android.util.MathUtils; -import android.util.Pair; +import android.util.Range; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -266,11 +266,11 @@ public class NetworkStatsCollection implements FileRotator.Reader { long collectEnd = end; if (augmentEnd != SubscriptionPlan.TIME_UNKNOWN) { - final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = augmentPlan.cycleIterator(); + final Iterator<Range<ZonedDateTime>> it = augmentPlan.cycleIterator(); while (it.hasNext()) { - final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next(); - final long cycleStart = cycle.first.toInstant().toEpochMilli(); - final long cycleEnd = cycle.second.toInstant().toEpochMilli(); + final Range<ZonedDateTime> cycle = it.next(); + final long cycleStart = cycle.getLower().toInstant().toEpochMilli(); + final long cycleEnd = cycle.getUpper().toInstant().toEpochMilli(); if (cycleStart <= augmentEnd && augmentEnd < cycleEnd) { augmentStart = cycleStart; collectStart = Long.min(collectStart, augmentStart); diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java index d908b8e29146..dc478213c80c 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -121,7 +121,7 @@ import android.text.TextUtils; import android.text.format.Time; import android.util.DataUnit; import android.util.Log; -import android.util.Pair; +import android.util.Range; import android.util.RecurrenceRule; import com.android.internal.telephony.PhoneConstants; @@ -821,11 +821,11 @@ public class NetworkPolicyManagerServiceTest { private static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) { RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTime), ZoneId.systemDefault()); - final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = policy.cycleIterator(); + final Iterator<Range<ZonedDateTime>> it = policy.cycleIterator(); while (it.hasNext()) { - final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next(); - if (cycle.first.toInstant().toEpochMilli() < currentTime) { - return cycle.first.toInstant().toEpochMilli(); + final Range<ZonedDateTime> cycle = it.next(); + if (cycle.getLower().toInstant().toEpochMilli() < currentTime) { + return cycle.getLower().toInstant().toEpochMilli(); } } throw new IllegalStateException( @@ -835,7 +835,7 @@ public class NetworkPolicyManagerServiceTest { private static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) { RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTime), ZoneId.systemDefault()); - return policy.cycleIterator().next().second.toInstant().toEpochMilli(); + return policy.cycleIterator().next().getUpper().toInstant().toEpochMilli(); } @Test diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 754fe687344a..a9389bea2452 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -477,6 +477,9 @@ public class SubscriptionManager { * <p> * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription * the user is interested in. + * <p> + * Receivers should protect themselves by checking that the sender holds the + * {@code android.permission.MANAGE_SUBSCRIPTION_PLANS} permission. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @SystemApi @@ -1719,6 +1722,8 @@ public class SubscriptionManager { * </ul> * * @param subId the subscriber this relationship applies to + * @throws SecurityException if the caller doesn't meet the requirements + * outlined above. */ @SystemApi public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) { @@ -1744,10 +1749,13 @@ public class SubscriptionManager { * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. * </ul> * - * @param subId the subscriber this relationship applies to + * @param subId the subscriber this relationship applies to. An empty list + * may be sent to clear any existing plans. * @param plans the list of plans. The first plan is always the primary and * most important plan. Any additional plans are secondary and * may not be displayed or used by decision making logic. + * @throws SecurityException if the caller doesn't meet the requirements + * outlined above. */ @SystemApi public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) { @@ -1788,6 +1796,8 @@ public class SubscriptionManager { * be automatically cleared, or {@code 0} to leave in the * requested state until explicitly cleared, or the next reboot, * whichever happens first. + * @throws SecurityException if the caller doesn't meet the requirements + * outlined above. */ @SystemApi public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, @@ -1822,6 +1832,8 @@ public class SubscriptionManager { * be automatically cleared, or {@code 0} to leave in the * requested state until explicitly cleared, or the next reboot, * whichever happens first. + * @throws SecurityException if the caller doesn't meet the requirements + * outlined above. */ @SystemApi public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested, diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java index 4ffb70ba04a8..ef2a364f5a34 100644 --- a/telephony/java/android/telephony/SubscriptionPlan.java +++ b/telephony/java/android/telephony/SubscriptionPlan.java @@ -24,7 +24,7 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.util.Pair; +import android.util.Range; import android.util.RecurrenceRule; import com.android.internal.util.Preconditions; @@ -209,7 +209,7 @@ public final class SubscriptionPlan implements Parcelable { * any recurrence rules. The iterator starts from the currently active cycle * and walks backwards through time. */ - public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() { + public Iterator<Range<ZonedDateTime>> cycleIterator() { return cycleRule.cycleIterator(); } @@ -227,6 +227,9 @@ public final class SubscriptionPlan implements Parcelable { /** * Start defining a {@link SubscriptionPlan} that covers a very specific * window of time, and never automatically recurs. + * + * @param start The exact time at which the plan starts. + * @param end The exact time at which the plan ends. */ public static Builder createNonrecurring(ZonedDateTime start, ZonedDateTime end) { if (!end.isAfter(start)) { @@ -237,28 +240,40 @@ public final class SubscriptionPlan implements Parcelable { } /** - * Start defining a {@link SubscriptionPlan} that will recur - * automatically every month. It will always recur on the same day of a - * particular month. When a particular month ends before the defined - * recurrence day, the plan will recur on the last instant of that - * month. + * Start defining a {@link SubscriptionPlan} that starts at a specific + * time, and automatically recurs after each specific period of time, + * repeating indefinitely. + * <p> + * When the given period is set to exactly one month, the plan will + * always recur on the day of the month defined by + * {@link ZonedDateTime#getDayOfMonth()}. When a particular month ends + * before this day, the plan will recur on the last possible instant of + * that month. + * + * @param start The exact time at which the plan starts. + * @param period The period after which the plan automatically recurs. */ + public static Builder createRecurring(ZonedDateTime start, Period period) { + return new Builder(start, null, period); + } + + /** {@hide} */ + @SystemApi + @Deprecated public static Builder createRecurringMonthly(ZonedDateTime start) { return new Builder(start, null, Period.ofMonths(1)); } - /** - * Start defining a {@link SubscriptionPlan} that will recur - * automatically every week. - */ + /** {@hide} */ + @SystemApi + @Deprecated public static Builder createRecurringWeekly(ZonedDateTime start) { return new Builder(start, null, Period.ofDays(7)); } - /** - * Start defining a {@link SubscriptionPlan} that will recur - * automatically every day. - */ + /** {@hide} */ + @SystemApi + @Deprecated public static Builder createRecurringDaily(ZonedDateTime start) { return new Builder(start, null, Period.ofDays(1)); } |