Merge "Tweak SystemUpdatePolicy APIs" into pi-dev
This commit is contained in:
@@ -6749,6 +6749,12 @@ package android.app.admin {
|
||||
field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
|
||||
}
|
||||
|
||||
public class FreezePeriod {
|
||||
ctor public FreezePeriod(java.time.MonthDay, java.time.MonthDay);
|
||||
method public java.time.MonthDay getEnd();
|
||||
method public java.time.MonthDay getStart();
|
||||
}
|
||||
|
||||
public abstract class NetworkEvent implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public long getId();
|
||||
@@ -6819,16 +6825,16 @@ package android.app.admin {
|
||||
field public static final int SECURITY_PATCH_STATE_UNKNOWN = 0; // 0x0
|
||||
}
|
||||
|
||||
public class SystemUpdatePolicy implements android.os.Parcelable {
|
||||
public final class SystemUpdatePolicy implements android.os.Parcelable {
|
||||
method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
|
||||
method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
|
||||
method public static android.app.admin.SystemUpdatePolicy createWindowedInstallPolicy(int, int);
|
||||
method public int describeContents();
|
||||
method public java.util.List<android.util.Pair<java.lang.Integer, java.lang.Integer>> getFreezePeriods();
|
||||
method public java.util.List<android.app.admin.FreezePeriod> getFreezePeriods();
|
||||
method public int getInstallWindowEnd();
|
||||
method public int getInstallWindowStart();
|
||||
method public int getPolicyType();
|
||||
method public android.app.admin.SystemUpdatePolicy setFreezePeriods(java.util.List<android.util.Pair<java.lang.Integer, java.lang.Integer>>);
|
||||
method public android.app.admin.SystemUpdatePolicy setFreezePeriods(java.util.List<android.app.admin.FreezePeriod>);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.admin.SystemUpdatePolicy> CREATOR;
|
||||
field public static final int TYPE_INSTALL_AUTOMATIC = 1; // 0x1
|
||||
@@ -6841,11 +6847,12 @@ package android.app.admin {
|
||||
method public int getErrorCode();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.admin.SystemUpdatePolicy.ValidationFailedException> CREATOR;
|
||||
field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 5; // 0x5
|
||||
field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 4; // 0x4
|
||||
field public static final int ERROR_DUPLICATE_OR_OVERLAP = 1; // 0x1
|
||||
field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 3; // 0x3
|
||||
field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 2; // 0x2
|
||||
field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 6; // 0x6
|
||||
field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 5; // 0x5
|
||||
field public static final int ERROR_DUPLICATE_OR_OVERLAP = 2; // 0x2
|
||||
field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 4; // 0x4
|
||||
field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 3; // 0x3
|
||||
field public static final int ERROR_UNKNOWN = 1; // 0x1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@ package android.app.admin {
|
||||
field public static final int STATE_USER_UNMANAGED = 0; // 0x0
|
||||
}
|
||||
|
||||
public class SystemUpdatePolicy implements android.os.Parcelable {
|
||||
public final class SystemUpdatePolicy implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.app.admin.SystemUpdatePolicy.InstallationOption getInstallationOptionAt(long);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
|
||||
@@ -20,49 +20,88 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An interval representing one freeze period which repeats annually. We use the number of days
|
||||
* since the start of (non-leap) year to define the start and end dates of an interval, both
|
||||
* inclusive. If the end date is smaller than the start date, the interval is considered wrapped
|
||||
* around the year-end. As far as an interval is concerned, February 29th should be treated as
|
||||
* if it were February 28th: so an interval starting or ending on February 28th are not
|
||||
* distinguishable from an interval on February 29th. When calulating interval length or
|
||||
* distance between two dates, February 29th is also disregarded.
|
||||
* A class that represents one freeze period which repeats <em>annually</em>. A freeze period has
|
||||
* two {@link java.time#MonthDay} values that define the start and end dates of the period, both
|
||||
* inclusive. If the end date is earlier than the start date, the period is considered wrapped
|
||||
* around the year-end. As far as freeze period is concerned, leap year is disregarded and February
|
||||
* 29th should be treated as if it were February 28th: so a freeze starting or ending on February
|
||||
* 28th is identical to a freeze starting or ending on February 29th. When calulating the length of
|
||||
* a freeze or the distance bewteen two freee periods, February 29th is also ignored.
|
||||
*
|
||||
* @see SystemUpdatePolicy#setFreezePeriods
|
||||
* @hide
|
||||
*/
|
||||
public class FreezeInterval {
|
||||
private static final String TAG = "FreezeInterval";
|
||||
public class FreezePeriod {
|
||||
private static final String TAG = "FreezePeriod";
|
||||
|
||||
private static final int DUMMY_YEAR = 2001;
|
||||
static final int DAYS_IN_YEAR = 365; // 365 since DUMMY_YEAR is not a leap year
|
||||
|
||||
final int mStartDay; // [1,365]
|
||||
final int mEndDay; // [1,365]
|
||||
private final MonthDay mStart;
|
||||
private final MonthDay mEnd;
|
||||
|
||||
FreezeInterval(int startDay, int endDay) {
|
||||
if (startDay < 1 || startDay > 365 || endDay < 1 || endDay > 365) {
|
||||
throw new RuntimeException("Bad dates for Interval: " + startDay + "," + endDay);
|
||||
}
|
||||
mStartDay = startDay;
|
||||
mEndDay = endDay;
|
||||
/*
|
||||
* Start and end dates represented by number of days since the beginning of the year.
|
||||
* They are internal representations of mStart and mEnd with normalized Leap year days
|
||||
* (Feb 29 == Feb 28 == 59th day of year). All internal calclations are based on
|
||||
* these two values so that leap year days are disregarded.
|
||||
*/
|
||||
private final int mStartDay; // [1, 365]
|
||||
private final int mEndDay; // [1, 365]
|
||||
|
||||
/**
|
||||
* Creates a freeze period by its start and end dates. If the end date is earlier than the start
|
||||
* date, the freeze period is considered wrapping year-end.
|
||||
*/
|
||||
public FreezePeriod(MonthDay start, MonthDay end) {
|
||||
mStart = start;
|
||||
mStartDay = mStart.atYear(DUMMY_YEAR).getDayOfYear();
|
||||
mEnd = end;
|
||||
mEndDay = mEnd.atYear(DUMMY_YEAR).getDayOfYear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the start date (inclusive) of this freeze period.
|
||||
*/
|
||||
public MonthDay getStart() {
|
||||
return mStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end date (inclusive) of this freeze period.
|
||||
*/
|
||||
public MonthDay getEnd() {
|
||||
return mEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
private FreezePeriod(int startDay, int endDay) {
|
||||
mStartDay = startDay;
|
||||
mStart = dayOfYearToMonthDay(startDay);
|
||||
mEndDay = endDay;
|
||||
mEnd = dayOfYearToMonthDay(endDay);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
int getLength() {
|
||||
return getEffectiveEndDay() - mStartDay + 1;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
boolean isWrapped() {
|
||||
return mEndDay < mStartDay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective end day, taking wrapping around year-end into consideration
|
||||
* @hide
|
||||
*/
|
||||
int getEffectiveEndDay() {
|
||||
if (!isWrapped()) {
|
||||
@@ -72,6 +111,7 @@ public class FreezeInterval {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
boolean contains(LocalDate localDate) {
|
||||
final int daysOfYear = dayOfYearDisregardLeapYear(localDate);
|
||||
if (!isWrapped()) {
|
||||
@@ -84,6 +124,7 @@ public class FreezeInterval {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
boolean after(LocalDate localDate) {
|
||||
return mStartDay > dayOfYearDisregardLeapYear(localDate);
|
||||
}
|
||||
@@ -95,6 +136,7 @@ public class FreezeInterval {
|
||||
* include now, the returned dates represents the next future interval.
|
||||
* The result will always have the same month and dayOfMonth value as the non-instantiated
|
||||
* interval itself.
|
||||
* @hide
|
||||
*/
|
||||
Pair<LocalDate, LocalDate> toCurrentOrFutureRealDates(LocalDate now) {
|
||||
final int nowDays = dayOfYearDisregardLeapYear(now);
|
||||
@@ -138,14 +180,24 @@ public class FreezeInterval {
|
||||
+ LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).format(formatter);
|
||||
}
|
||||
|
||||
// Treat the supplied date as in a non-leap year and return its day of year.
|
||||
static int dayOfYearDisregardLeapYear(LocalDate date) {
|
||||
/** @hide */
|
||||
private static MonthDay dayOfYearToMonthDay(int dayOfYear) {
|
||||
LocalDate date = LocalDate.ofYearDay(DUMMY_YEAR, dayOfYear);
|
||||
return MonthDay.of(date.getMonth(), date.getDayOfMonth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Treat the supplied date as in a non-leap year and return its day of year.
|
||||
* @hide
|
||||
*/
|
||||
private static int dayOfYearDisregardLeapYear(LocalDate date) {
|
||||
return date.withYear(DUMMY_YEAR).getDayOfYear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of days between first (inclusive) and second (exclusive),
|
||||
* treating all years in between as non-leap.
|
||||
* @hide
|
||||
*/
|
||||
public static int distanceWithoutLeapYear(LocalDate first, LocalDate second) {
|
||||
return dayOfYearDisregardLeapYear(first) - dayOfYearDisregardLeapYear(second)
|
||||
@@ -165,16 +217,16 @@ public class FreezeInterval {
|
||||
* 3. At most one wrapped Interval remains, and it will be at the end of the list
|
||||
* @hide
|
||||
*/
|
||||
protected static List<FreezeInterval> canonicalizeIntervals(List<FreezeInterval> intervals) {
|
||||
static List<FreezePeriod> canonicalizePeriods(List<FreezePeriod> intervals) {
|
||||
boolean[] taken = new boolean[DAYS_IN_YEAR];
|
||||
// First convert the intervals into flat array
|
||||
for (FreezeInterval interval : intervals) {
|
||||
for (FreezePeriod interval : intervals) {
|
||||
for (int i = interval.mStartDay; i <= interval.getEffectiveEndDay(); i++) {
|
||||
taken[(i - 1) % DAYS_IN_YEAR] = true;
|
||||
}
|
||||
}
|
||||
// Then reconstruct intervals from the array
|
||||
List<FreezeInterval> result = new ArrayList<>();
|
||||
List<FreezePeriod> result = new ArrayList<>();
|
||||
int i = 0;
|
||||
while (i < DAYS_IN_YEAR) {
|
||||
if (!taken[i]) {
|
||||
@@ -183,14 +235,14 @@ public class FreezeInterval {
|
||||
}
|
||||
final int intervalStart = i + 1;
|
||||
while (i < DAYS_IN_YEAR && taken[i]) i++;
|
||||
result.add(new FreezeInterval(intervalStart, i));
|
||||
result.add(new FreezePeriod(intervalStart, i));
|
||||
}
|
||||
// Check if the last entry can be merged to the first entry to become one single
|
||||
// wrapped interval
|
||||
final int lastIndex = result.size() - 1;
|
||||
if (lastIndex > 0 && result.get(lastIndex).mEndDay == DAYS_IN_YEAR
|
||||
&& result.get(0).mStartDay == 1) {
|
||||
FreezeInterval wrappedInterval = new FreezeInterval(result.get(lastIndex).mStartDay,
|
||||
FreezePeriod wrappedInterval = new FreezePeriod(result.get(lastIndex).mStartDay,
|
||||
result.get(0).mEndDay);
|
||||
result.set(lastIndex, wrappedInterval);
|
||||
result.remove(0);
|
||||
@@ -207,18 +259,18 @@ public class FreezeInterval {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected static void validatePeriods(List<FreezeInterval> periods) {
|
||||
List<FreezeInterval> allPeriods = FreezeInterval.canonicalizeIntervals(periods);
|
||||
static void validatePeriods(List<FreezePeriod> periods) {
|
||||
List<FreezePeriod> allPeriods = FreezePeriod.canonicalizePeriods(periods);
|
||||
if (allPeriods.size() != periods.size()) {
|
||||
throw SystemUpdatePolicy.ValidationFailedException.duplicateOrOverlapPeriods();
|
||||
}
|
||||
for (int i = 0; i < allPeriods.size(); i++) {
|
||||
FreezeInterval current = allPeriods.get(i);
|
||||
FreezePeriod current = allPeriods.get(i);
|
||||
if (current.getLength() > SystemUpdatePolicy.FREEZE_PERIOD_MAX_LENGTH) {
|
||||
throw SystemUpdatePolicy.ValidationFailedException.freezePeriodTooLong("Freeze "
|
||||
+ "period " + current + " is too long: " + current.getLength() + " days");
|
||||
}
|
||||
FreezeInterval previous = i > 0 ? allPeriods.get(i - 1)
|
||||
FreezePeriod previous = i > 0 ? allPeriods.get(i - 1)
|
||||
: allPeriods.get(allPeriods.size() - 1);
|
||||
if (previous != current) {
|
||||
final int separation;
|
||||
@@ -247,7 +299,7 @@ public class FreezeInterval {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected static void validateAgainstPreviousFreezePeriod(List<FreezeInterval> periods,
|
||||
static void validateAgainstPreviousFreezePeriod(List<FreezePeriod> periods,
|
||||
LocalDate prevPeriodStart, LocalDate prevPeriodEnd, LocalDate now) {
|
||||
if (periods.size() == 0 || prevPeriodStart == null || prevPeriodEnd == null) {
|
||||
return;
|
||||
@@ -258,14 +310,14 @@ public class FreezeInterval {
|
||||
// Clock was adjusted backwards. We can continue execution though, the separation
|
||||
// and length validation below still works under this condition.
|
||||
}
|
||||
List<FreezeInterval> allPeriods = FreezeInterval.canonicalizeIntervals(periods);
|
||||
List<FreezePeriod> allPeriods = FreezePeriod.canonicalizePeriods(periods);
|
||||
// Given current time now, find the freeze period that's either current, or the one
|
||||
// that's immediately afterwards. For the later case, it might be after the year-end,
|
||||
// but this can only happen if there is only one freeze period.
|
||||
FreezeInterval curOrNextFreezePeriod = allPeriods.get(0);
|
||||
for (FreezeInterval interval : allPeriods) {
|
||||
FreezePeriod curOrNextFreezePeriod = allPeriods.get(0);
|
||||
for (FreezePeriod interval : allPeriods) {
|
||||
if (interval.contains(now)
|
||||
|| interval.mStartDay > FreezeInterval.dayOfYearDisregardLeapYear(now)) {
|
||||
|| interval.mStartDay > FreezePeriod.dayOfYearDisregardLeapYear(now)) {
|
||||
curOrNextFreezePeriod = interval;
|
||||
break;
|
||||
}
|
||||
@@ -282,7 +334,7 @@ public class FreezeInterval {
|
||||
// Now validate [prevPeriodStart, prevPeriodEnd] against curOrNextFreezeDates
|
||||
final String periodsDescription = "Prev: " + prevPeriodStart + "," + prevPeriodEnd
|
||||
+ "; cur: " + curOrNextFreezeDates.first + "," + curOrNextFreezeDates.second;
|
||||
long separation = FreezeInterval.distanceWithoutLeapYear(curOrNextFreezeDates.first,
|
||||
long separation = FreezePeriod.distanceWithoutLeapYear(curOrNextFreezeDates.first,
|
||||
prevPeriodEnd) - 1;
|
||||
if (separation > 0) {
|
||||
// Two intervals do not overlap, check separation
|
||||
@@ -292,7 +344,7 @@ public class FreezeInterval {
|
||||
}
|
||||
} else {
|
||||
// Two intervals overlap, check combined length
|
||||
long length = FreezeInterval.distanceWithoutLeapYear(curOrNextFreezeDates.second,
|
||||
long length = FreezePeriod.distanceWithoutLeapYear(curOrNextFreezeDates.second,
|
||||
prevPeriodStart) + 1;
|
||||
if (length > SystemUpdatePolicy.FREEZE_PERIOD_MAX_LENGTH) {
|
||||
throw ValidationFailedException.combinedPeriodTooLong("Combined freeze period "
|
||||
@@ -38,9 +38,11 @@ import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.MonthDay;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -51,7 +53,7 @@ import java.util.stream.Collectors;
|
||||
* @see DevicePolicyManager#setSystemUpdatePolicy
|
||||
* @see DevicePolicyManager#getSystemUpdatePolicy
|
||||
*/
|
||||
public class SystemUpdatePolicy implements Parcelable {
|
||||
public final class SystemUpdatePolicy implements Parcelable {
|
||||
private static final String TAG = "SystemUpdatePolicy";
|
||||
|
||||
/** @hide */
|
||||
@@ -163,6 +165,7 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE,
|
||||
ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG,
|
||||
ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE,
|
||||
ERROR_UNKNOWN,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface ValidationFailureType {}
|
||||
@@ -170,34 +173,39 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
/** @hide */
|
||||
public static final int ERROR_NONE = 0;
|
||||
|
||||
/**
|
||||
* Validation failed with unknown error.
|
||||
*/
|
||||
public static final int ERROR_UNKNOWN = 1;
|
||||
|
||||
/**
|
||||
* The freeze periods contains duplicates, periods that overlap with each
|
||||
* other or periods whose start and end joins.
|
||||
*/
|
||||
public static final int ERROR_DUPLICATE_OR_OVERLAP = 1;
|
||||
public static final int ERROR_DUPLICATE_OR_OVERLAP = 2;
|
||||
|
||||
/**
|
||||
* There exists at least one freeze period whose length exceeds 90 days.
|
||||
*/
|
||||
public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 2;
|
||||
public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 3;
|
||||
|
||||
/**
|
||||
* There exists some freeze period which starts within 60 days of the preceding period's
|
||||
* end time.
|
||||
*/
|
||||
public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 3;
|
||||
public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 4;
|
||||
|
||||
/**
|
||||
* The device has been in a freeze period and when combining with the new freeze period
|
||||
* to be set, it will result in the total freeze period being longer than 90 days.
|
||||
*/
|
||||
public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 4;
|
||||
public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 5;
|
||||
|
||||
/**
|
||||
* The device has been in a freeze period and some new freeze period to be set is less
|
||||
* than 60 days from the end of the last freeze period the device went through.
|
||||
*/
|
||||
public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 5;
|
||||
public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 6;
|
||||
|
||||
@ValidationFailureType
|
||||
private final int mErrorCode;
|
||||
@@ -272,7 +280,7 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
private int mMaintenanceWindowStart;
|
||||
private int mMaintenanceWindowEnd;
|
||||
|
||||
private final ArrayList<FreezeInterval> mFreezePeriods;
|
||||
private final ArrayList<FreezePeriod> mFreezePeriods;
|
||||
|
||||
private SystemUpdatePolicy() {
|
||||
mPolicyType = TYPE_UNKNOWN;
|
||||
@@ -444,12 +452,10 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
* requirement set above
|
||||
* @return this instance
|
||||
*/
|
||||
public SystemUpdatePolicy setFreezePeriods(List<Pair<Integer, Integer>> freezePeriods) {
|
||||
List<FreezeInterval> newPeriods = freezePeriods.stream().map(
|
||||
p -> new FreezeInterval(p.first, p.second)).collect(Collectors.toList());
|
||||
FreezeInterval.validatePeriods(newPeriods);
|
||||
public SystemUpdatePolicy setFreezePeriods(List<FreezePeriod> freezePeriods) {
|
||||
FreezePeriod.validatePeriods(freezePeriods);
|
||||
mFreezePeriods.clear();
|
||||
mFreezePeriods.addAll(newPeriods);
|
||||
mFreezePeriods.addAll(freezePeriods);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -458,12 +464,8 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
*
|
||||
* @return the list of freeze periods, or an empty list if none was set.
|
||||
*/
|
||||
public List<Pair<Integer, Integer>> getFreezePeriods() {
|
||||
List<Pair<Integer, Integer>> result = new ArrayList<>(mFreezePeriods.size());
|
||||
for (FreezeInterval interval : mFreezePeriods) {
|
||||
result.add(new Pair<>(interval.mStartDay, interval.mEndDay));
|
||||
}
|
||||
return result;
|
||||
public List<FreezePeriod> getFreezePeriods() {
|
||||
return Collections.unmodifiableList(mFreezePeriods);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -472,7 +474,7 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
* @hide
|
||||
*/
|
||||
public Pair<LocalDate, LocalDate> getCurrentFreezePeriod(LocalDate now) {
|
||||
for (FreezeInterval interval : mFreezePeriods) {
|
||||
for (FreezePeriod interval : mFreezePeriods) {
|
||||
if (interval.contains(now)) {
|
||||
return interval.toCurrentOrFutureRealDates(now);
|
||||
}
|
||||
@@ -485,10 +487,10 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
* is not within a freeze period.
|
||||
*/
|
||||
private long timeUntilNextFreezePeriod(long now) {
|
||||
List<FreezeInterval> sortedPeriods = FreezeInterval.canonicalizeIntervals(mFreezePeriods);
|
||||
List<FreezePeriod> sortedPeriods = FreezePeriod.canonicalizePeriods(mFreezePeriods);
|
||||
LocalDate nowDate = millisToDate(now);
|
||||
LocalDate nextFreezeStart = null;
|
||||
for (FreezeInterval interval : sortedPeriods) {
|
||||
for (FreezePeriod interval : sortedPeriods) {
|
||||
if (interval.after(nowDate)) {
|
||||
nextFreezeStart = interval.toCurrentOrFutureRealDates(nowDate).first;
|
||||
break;
|
||||
@@ -506,13 +508,13 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
|
||||
/** @hide */
|
||||
public void validateFreezePeriods() {
|
||||
FreezeInterval.validatePeriods(mFreezePeriods);
|
||||
FreezePeriod.validatePeriods(mFreezePeriods);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void validateAgainstPreviousFreezePeriod(LocalDate prevPeriodStart,
|
||||
LocalDate prevPeriodEnd, LocalDate now) {
|
||||
FreezeInterval.validateAgainstPreviousFreezePeriod(mFreezePeriods, prevPeriodStart,
|
||||
FreezePeriod.validateAgainstPreviousFreezePeriod(mFreezePeriods, prevPeriodStart,
|
||||
prevPeriodEnd, now);
|
||||
}
|
||||
|
||||
@@ -521,10 +523,10 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
* updates and how long this action is valid for, given the current system update policy. Its
|
||||
* action could be one of the following
|
||||
* <ul>
|
||||
* <li> {@code TYPE_INSTALL_AUTOMATIC} system updates should be installed immedately and without
|
||||
* user intervention as soon as they become available.
|
||||
* <li> {@code TYPE_POSTPONE} system updates should be postponed for a maximum of 30 days
|
||||
* <li> {@code TYPE_PAUSE} system updates should be postponed indefinitely until further notice
|
||||
* <li> {@link #TYPE_INSTALL_AUTOMATIC} system updates should be installed immedately and
|
||||
* without user intervention as soon as they become available.
|
||||
* <li> {@link #TYPE_POSTPONE} system updates should be postponed for a maximum of 30 days
|
||||
* <li> {@link #TYPE_PAUSE} system updates should be postponed indefinitely until further notice
|
||||
* </ul>
|
||||
*
|
||||
* The effective time measures how long this installation option is valid for from the queried
|
||||
@@ -535,18 +537,38 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
*/
|
||||
@SystemApi
|
||||
public static class InstallationOption {
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "TYPE_" }, value = {
|
||||
TYPE_INSTALL_AUTOMATIC,
|
||||
TYPE_PAUSE,
|
||||
TYPE_POSTPONE
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface InstallationOptionType {}
|
||||
|
||||
@InstallationOptionType
|
||||
private final int mType;
|
||||
private long mEffectiveTime;
|
||||
|
||||
InstallationOption(int type, long effectiveTime) {
|
||||
InstallationOption(@InstallationOptionType int type, long effectiveTime) {
|
||||
this.mType = type;
|
||||
this.mEffectiveTime = effectiveTime;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
/**
|
||||
* Returns the type of the current installation option, could be one of
|
||||
* {@link #TYPE_INSTALL_AUTOMATIC}, {@link #TYPE_POSTPONE} and {@link #TYPE_PAUSE}.
|
||||
* @return type of installation option.
|
||||
*/
|
||||
public @InstallationOptionType int getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how long the current installation option in effective for, starting from the time
|
||||
* of query.
|
||||
* @return the effective time in milliseconds.
|
||||
*/
|
||||
public long getEffectiveTime() {
|
||||
return mEffectiveTime;
|
||||
}
|
||||
@@ -667,9 +689,11 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
int freezeCount = mFreezePeriods.size();
|
||||
dest.writeInt(freezeCount);
|
||||
for (int i = 0; i < freezeCount; i++) {
|
||||
FreezeInterval interval = mFreezePeriods.get(i);
|
||||
dest.writeInt(interval.mStartDay);
|
||||
dest.writeInt(interval.mEndDay);
|
||||
FreezePeriod interval = mFreezePeriods.get(i);
|
||||
dest.writeInt(interval.getStart().getMonthValue());
|
||||
dest.writeInt(interval.getStart().getDayOfMonth());
|
||||
dest.writeInt(interval.getEnd().getMonthValue());
|
||||
dest.writeInt(interval.getEnd().getDayOfMonth());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,8 +710,9 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
int freezeCount = source.readInt();
|
||||
policy.mFreezePeriods.ensureCapacity(freezeCount);
|
||||
for (int i = 0; i < freezeCount; i++) {
|
||||
policy.mFreezePeriods.add(
|
||||
new FreezeInterval(source.readInt(), source.readInt()));
|
||||
MonthDay start = MonthDay.of(source.readInt(), source.readInt());
|
||||
MonthDay end = MonthDay.of(source.readInt(), source.readInt());
|
||||
policy.mFreezePeriods.add(new FreezePeriod(start, end));
|
||||
}
|
||||
return policy;
|
||||
}
|
||||
@@ -730,9 +755,9 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
if (!parser.getName().equals(KEY_FREEZE_TAG)) {
|
||||
continue;
|
||||
}
|
||||
policy.mFreezePeriods.add(new FreezeInterval(
|
||||
Integer.parseInt(parser.getAttributeValue(null, KEY_FREEZE_START)),
|
||||
Integer.parseInt(parser.getAttributeValue(null, KEY_FREEZE_END))));
|
||||
policy.mFreezePeriods.add(new FreezePeriod(
|
||||
MonthDay.parse(parser.getAttributeValue(null, KEY_FREEZE_START)),
|
||||
MonthDay.parse(parser.getAttributeValue(null, KEY_FREEZE_END))));
|
||||
}
|
||||
return policy;
|
||||
}
|
||||
@@ -751,10 +776,10 @@ public class SystemUpdatePolicy implements Parcelable {
|
||||
out.attribute(null, KEY_INSTALL_WINDOW_START, Integer.toString(mMaintenanceWindowStart));
|
||||
out.attribute(null, KEY_INSTALL_WINDOW_END, Integer.toString(mMaintenanceWindowEnd));
|
||||
for (int i = 0; i < mFreezePeriods.size(); i++) {
|
||||
FreezeInterval interval = mFreezePeriods.get(i);
|
||||
FreezePeriod interval = mFreezePeriods.get(i);
|
||||
out.startTag(null, KEY_FREEZE_TAG);
|
||||
out.attribute(null, KEY_FREEZE_START, Integer.toString(interval.mStartDay));
|
||||
out.attribute(null, KEY_FREEZE_END, Integer.toString(interval.mEndDay));
|
||||
out.attribute(null, KEY_FREEZE_START, interval.getStart().toString());
|
||||
out.attribute(null, KEY_FREEZE_END, interval.getEnd().toString());
|
||||
out.endTag(null, KEY_FREEZE_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import android.app.admin.FreezeInterval;
|
||||
import android.app.admin.FreezePeriod;
|
||||
import android.app.admin.SystemUpdatePolicy;
|
||||
import android.os.Parcel;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
@@ -42,15 +42,15 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.MonthDay;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link android.app.admin.SystemUpdatePolicy}.
|
||||
* Throughout this test, we use "MM-DD" format to denote dates without year.
|
||||
@@ -224,36 +224,36 @@ public final class SystemUpdatePolicyTest {
|
||||
|
||||
@Test
|
||||
public void testDistanceWithoutLeapYear() {
|
||||
assertEquals(364, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(364, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2016, 12, 31), LocalDate.of(2016, 1, 1)));
|
||||
assertEquals(365, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(365, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2017, 1, 1), LocalDate.of(2016, 1, 1)));
|
||||
assertEquals(365, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(365, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2017, 2, 28), LocalDate.of(2016, 2, 29)));
|
||||
assertEquals(-365, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(-365, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2016, 1, 1), LocalDate.of(2017, 1, 1)));
|
||||
assertEquals(1, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(1, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 29)));
|
||||
assertEquals(1, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(1, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 28)));
|
||||
assertEquals(0, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(0, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2016, 2, 29), LocalDate.of(2016, 2, 28)));
|
||||
assertEquals(0, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(0, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2016, 2, 28), LocalDate.of(2016, 2, 28)));
|
||||
|
||||
assertEquals(59, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(59, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2016, 3, 1), LocalDate.of(2016, 1, 1)));
|
||||
assertEquals(59, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(59, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2017, 3, 1), LocalDate.of(2017, 1, 1)));
|
||||
|
||||
assertEquals(365 * 40, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(365 * 40, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2040, 1, 1), LocalDate.of(2000, 1, 1)));
|
||||
|
||||
assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2019, 3, 1), LocalDate.of(2017, 3, 1)));
|
||||
assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2018, 3, 1), LocalDate.of(2016, 3, 1)));
|
||||
assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
|
||||
assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
|
||||
LocalDate.of(2017, 3, 1), LocalDate.of(2015, 3, 1)));
|
||||
|
||||
}
|
||||
@@ -386,10 +386,10 @@ public final class SystemUpdatePolicyTest {
|
||||
|
||||
// Two freeze periods
|
||||
p = SystemUpdatePolicy.createAutomaticInstallPolicy();
|
||||
setFreezePeriods(p, "05-01", "06-01", "11-01", "01-29");
|
||||
// automatic policy for July, August, September and October
|
||||
setFreezePeriods(p, "05-01", "06-01", "10-15", "01-10");
|
||||
// automatic policy for July, August, September and October until 15th
|
||||
assertInstallationOption(
|
||||
SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(92),
|
||||
SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(31 + 30 + 14),
|
||||
millis_2018_08_01, p);
|
||||
}
|
||||
|
||||
@@ -435,18 +435,18 @@ public final class SystemUpdatePolicyTest {
|
||||
String... dates) throws Exception {
|
||||
SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy();
|
||||
setFreezePeriods(p, dates);
|
||||
p.validateAgainstPreviousFreezePeriod(parseDate(prevStart), parseDate(prevEnd),
|
||||
parseDate(now));
|
||||
p.validateAgainstPreviousFreezePeriod(parseLocalDate(prevStart),
|
||||
parseLocalDate(prevEnd), parseLocalDate(now));
|
||||
}
|
||||
|
||||
// "MM-DD" format for date
|
||||
private void setFreezePeriods(SystemUpdatePolicy policy, String... dates) throws Exception {
|
||||
List<Pair<Integer, Integer>> periods = new ArrayList<>();
|
||||
LocalDate lastDate = null;
|
||||
List<FreezePeriod> periods = new ArrayList<>();
|
||||
MonthDay lastDate = null;
|
||||
for (String date : dates) {
|
||||
LocalDate currentDate = parseDate(date);
|
||||
MonthDay currentDate = parseMonthDay(date);
|
||||
if (lastDate != null) {
|
||||
periods.add(new Pair<>(lastDate.getDayOfYear(), currentDate.getDayOfYear()));
|
||||
periods.add(new FreezePeriod(lastDate, currentDate));
|
||||
lastDate = null;
|
||||
} else {
|
||||
lastDate = currentDate;
|
||||
@@ -457,7 +457,7 @@ public final class SystemUpdatePolicyTest {
|
||||
}
|
||||
|
||||
private void testSerialization(SystemUpdatePolicy policy,
|
||||
List<Pair<Integer, Integer>> expectedPeriods) throws Exception {
|
||||
List<FreezePeriod> expectedPeriods) throws Exception {
|
||||
// Test parcel / unparcel
|
||||
Parcel parcel = Parcel.obtain();
|
||||
policy.writeToParcel(parcel, 0);
|
||||
@@ -485,36 +485,27 @@ public final class SystemUpdatePolicyTest {
|
||||
}
|
||||
|
||||
private void checkFreezePeriods(SystemUpdatePolicy policy,
|
||||
List<Pair<Integer, Integer>> expectedPeriods) {
|
||||
List<FreezePeriod> expectedPeriods) {
|
||||
int i = 0;
|
||||
for (Pair<Integer, Integer> period : policy.getFreezePeriods()) {
|
||||
assertEquals(expectedPeriods.get(i).first, period.first);
|
||||
assertEquals(expectedPeriods.get(i).second, period.second);
|
||||
for (FreezePeriod period : policy.getFreezePeriods()) {
|
||||
assertEquals(expectedPeriods.get(i).getStart(), period.getStart());
|
||||
assertEquals(expectedPeriods.get(i).getEnd(), period.getEnd());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private LocalDate parseDate(String date) {
|
||||
// Use leap year when parsing date string to handle "02-29", but force round down
|
||||
// to Feb 28th by overriding the year to non-leap year.
|
||||
final int year;
|
||||
boolean monthDateOnly = false;
|
||||
if (date.length() == 5) {
|
||||
year = 2000;
|
||||
monthDateOnly = true;
|
||||
} else {
|
||||
year = Integer.parseInt(date.substring(0, 4));
|
||||
date = date.substring(5);
|
||||
}
|
||||
LocalDate result = LocalDate.of(year, Integer.parseInt(date.substring(0, 2)),
|
||||
// MonthDay is of format MM-dd
|
||||
private MonthDay parseMonthDay(String date) {
|
||||
return MonthDay.of(Integer.parseInt(date.substring(0, 2)),
|
||||
Integer.parseInt(date.substring(3, 5)));
|
||||
if (monthDateOnly) {
|
||||
return result.withYear(2001);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// LocalDat is of format YYYY-MM-dd
|
||||
private LocalDate parseLocalDate(String date) {
|
||||
return parseMonthDay(date.substring(5)).atYear(Integer.parseInt(date.substring(0, 4)));
|
||||
}
|
||||
|
||||
|
||||
private long toMillis(int year, int month, int day) {
|
||||
return LocalDateTime.of(year, month, day, 0, 0, 0).atZone(ZoneId.systemDefault())
|
||||
.toInstant().toEpochMilli();
|
||||
|
||||
Reference in New Issue
Block a user