/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app.admin;

import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.TEXT;

import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.util.Pair;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
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;

/**
 * Determines when over-the-air system updates are installed on a device. Only a device policy
 * controller (DPC) running in device owner mode can set an update policy for the device—by calling
 * the {@code DevicePolicyManager} method
 * {@link DevicePolicyManager#setSystemUpdatePolicy setSystemUpdatePolicy()}. An update
 * policy affects the pending system update (if there is one) and any future updates for the device.
 *
 * <p>If a policy is set on a device, the system doesn't notify the user about updates.</p>
 * <h3>Example</h3>
 *
 * <p>The example below shows how a DPC might set a maintenance window for system updates:</p>
 * <pre><code>
 * private final MAINTENANCE_WINDOW_START = 1380; // 11pm
 * private final MAINTENANCE_WINDOW_END = 120; // 2am
 *
 * // ...
 *
 * // Create the system update policy
 * SystemUpdatePolicy policy = SystemUpdatePolicy.createWindowedInstallPolicy(
 *     MAINTENANCE_WINDOW_START, MAINTENANCE_WINDOW_END);
 *
 * // Get a DevicePolicyManager instance to set the policy on the device
 * DevicePolicyManager dpm =
 *     (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
 * ComponentName adminComponent = getComponentName(context);
 * dpm.setSystemUpdatePolicy(adminComponent, policy);
 * </code></pre>
 *
 * <h3>Developer guide</h3>
 * To learn more, read <a href="{@docRoot}work/dpc/system-updates">Manage system updates</a>.
 *
 * @see DevicePolicyManager#setSystemUpdatePolicy
 * @see DevicePolicyManager#getSystemUpdatePolicy
 */
public final class SystemUpdatePolicy implements Parcelable {
    private static final String TAG = "SystemUpdatePolicy";

    /** @hide */
    @IntDef(prefix = { "TYPE_" }, value = {
            TYPE_INSTALL_AUTOMATIC,
            TYPE_INSTALL_WINDOWED,
            TYPE_POSTPONE
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface SystemUpdatePolicyType {}

    /**
     * Unknown policy type, used only internally.
     */
    private static final int TYPE_UNKNOWN = -1;

    /**
     * Installs system updates (without user interaction) as soon as they become available. Setting
     * this policy type immediately installs any pending updates that might be postponed or waiting
     * for a maintenance window.
     */
    public static final int TYPE_INSTALL_AUTOMATIC = 1;

    /**
     * Installs system updates (without user interaction) during a daily maintenance window. Set the
     * start and end of the daily maintenance window, as minutes of the day, when creating a new
     * {@code TYPE_INSTALL_WINDOWED} policy. See
     * {@link #createWindowedInstallPolicy createWindowedInstallPolicy()}.
     *
     * <p>No connectivity, not enough disk space, or a low battery are typical reasons Android might
     * not install a system update in the daily maintenance window. After 30 days trying to install
     * an update in the maintenance window (regardless of policy changes in this period), the system
     * prompts the device user to install the update.
     */
    public static final int TYPE_INSTALL_WINDOWED = 2;

    /**
     * Postpones the installation of system updates for 30 days. After the 30-day period has ended,
     * the system prompts the device user to install the update.
     *
     * <p>The system limits each update to one 30-day postponement. The period begins when the
     * system first postpones the update and setting new {@code TYPE_POSTPONE} policies won’t extend
     * the period. If, after 30 days the update isn’t installed (through policy changes), the system
     * prompts the user to install the update.
     *
     * <p><strong>Note</strong>: Device manufacturers or carriers might choose to exempt important
     * security updates from a postponement policy. Exempted updates notify the device user when
     * they become available.
     */
    public static final int TYPE_POSTPONE = 3;

    /**
     * Incoming system updates (including security updates) should be blocked. This flag is not
     * exposed to third-party apps (and any attempt to set it will raise exceptions). This is used
     * to represent the current installation option type to the privileged system update clients,
     * for example to indicate OTA freeze is currently in place or when system is outside a daily
     * maintenance window.
     *
     * @see InstallationOption
     * @hide
     */
    @SystemApi
    public static final int TYPE_PAUSE = 4;

    private static final String KEY_POLICY_TYPE = "policy_type";
    private static final String KEY_INSTALL_WINDOW_START = "install_window_start";
    private static final String KEY_INSTALL_WINDOW_END = "install_window_end";
    private static final String KEY_FREEZE_TAG = "freeze";
    private static final String KEY_FREEZE_START = "start";
    private static final String KEY_FREEZE_END = "end";

    /**
     * The upper boundary of the daily maintenance window: 24 * 60 minutes.
     */
    private static final int WINDOW_BOUNDARY = 24 * 60;

    /**
     * The maximum length of a single freeze period: 90  days.
     */
    static final int FREEZE_PERIOD_MAX_LENGTH = 90;

    /**
     * The minimum allowed time between two adjacent freeze period (from the end of the first
     * freeze period to the start of the second freeze period, both exclusive): 60 days.
     */
    static final int FREEZE_PERIOD_MIN_SEPARATION = 60;


    /**
     * An exception class that represents various validation errors thrown from
     * {@link SystemUpdatePolicy#setFreezePeriods} and
     * {@link DevicePolicyManager#setSystemUpdatePolicy}
     */
    public static final class ValidationFailedException extends IllegalArgumentException
            implements Parcelable {

        /** @hide */
        @IntDef(prefix = { "ERROR_" }, value = {
                ERROR_NONE,
                ERROR_DUPLICATE_OR_OVERLAP,
                ERROR_NEW_FREEZE_PERIOD_TOO_LONG,
                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 {}

        /** @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 = 2;

        /**
         * There exists at least one freeze period whose length exceeds 90 days.
         */
        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 = 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 = 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 = 6;

        @ValidationFailureType
        private final int mErrorCode;

        private ValidationFailedException(int errorCode, String message) {
            super(message);
            mErrorCode = errorCode;
        }

        /**
         * Returns the type of validation error associated with this exception.
         */
        public @ValidationFailureType int getErrorCode() {
            return mErrorCode;
        }

        /** @hide */
        public static ValidationFailedException duplicateOrOverlapPeriods() {
            return new ValidationFailedException(ERROR_DUPLICATE_OR_OVERLAP,
                    "Found duplicate or overlapping periods");
        }

        /** @hide */
        public static ValidationFailedException freezePeriodTooLong(String message) {
            return new ValidationFailedException(ERROR_NEW_FREEZE_PERIOD_TOO_LONG, message);
        }

        /** @hide */
        public static ValidationFailedException freezePeriodTooClose(String message) {
            return new ValidationFailedException(ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE, message);
        }

        /** @hide */
        public static ValidationFailedException combinedPeriodTooLong(String message) {
            return new ValidationFailedException(ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG, message);
        }

        /** @hide */
        public static ValidationFailedException combinedPeriodTooClose(String message) {
            return new ValidationFailedException(ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE, message);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mErrorCode);
            dest.writeString(getMessage());
        }

        public static final @android.annotation.NonNull Parcelable.Creator<ValidationFailedException> CREATOR =
                new Parcelable.Creator<ValidationFailedException>() {
            @Override
            public ValidationFailedException createFromParcel(Parcel source) {
                return new ValidationFailedException(source.readInt(), source.readString());
            }

            @Override
            public ValidationFailedException[] newArray(int size) {
                return new ValidationFailedException[size];
            }

        };
    }

    @SystemUpdatePolicyType
    private int mPolicyType;

    private int mMaintenanceWindowStart;
    private int mMaintenanceWindowEnd;

    private final ArrayList<FreezePeriod> mFreezePeriods;

    private SystemUpdatePolicy() {
        mPolicyType = TYPE_UNKNOWN;
        mFreezePeriods = new ArrayList<>();
    }

    /**
     * Create a policy object and set it to install update automatically as soon as one is
     * available.
     *
     * @see #TYPE_INSTALL_AUTOMATIC
     */
    public static SystemUpdatePolicy createAutomaticInstallPolicy() {
        SystemUpdatePolicy policy = new SystemUpdatePolicy();
        policy.mPolicyType = TYPE_INSTALL_AUTOMATIC;
        return policy;
    }

    /**
     * Create a policy object and set it to: new system update will only be installed automatically
     * when the system clock is inside a daily maintenance window. If the start and end times are
     * the same, the window is considered to include the <i>whole 24 hours</i>. That is, updates can
     * install at any time. If start time is later than end time, the window is considered spanning
     * midnight (i.e. the end time denotes a time on the next day). The maintenance window will last
     * for 30 days for any given update, after which the window will no longer be effective and
     * the pending update will be made available for manual installation as if no system update
     * policy were set on the device. See {@link #TYPE_INSTALL_WINDOWED} for the details of this
     * policy's behavior.
     *
     * @param startTime the start of the maintenance window, measured as the number of minutes from
     *            midnight in the device's local time. Must be in the range of [0, 1440).
     * @param endTime the end of the maintenance window, measured as the number of minutes from
     *            midnight in the device's local time. Must be in the range of [0, 1440).
     * @throws IllegalArgumentException If the {@code startTime} or {@code endTime} isn't in the
     *            accepted range.
     * @return The configured policy.
     * @see #TYPE_INSTALL_WINDOWED
     */
    public static SystemUpdatePolicy createWindowedInstallPolicy(int startTime, int endTime) {
        if (startTime < 0 || startTime >= WINDOW_BOUNDARY
                || endTime < 0 || endTime >= WINDOW_BOUNDARY) {
            throw new IllegalArgumentException("startTime and endTime must be inside [0, 1440)");
        }
        SystemUpdatePolicy policy = new SystemUpdatePolicy();
        policy.mPolicyType = TYPE_INSTALL_WINDOWED;
        policy.mMaintenanceWindowStart = startTime;
        policy.mMaintenanceWindowEnd = endTime;
        return policy;
    }

    /**
     * Create a policy object and set it to block installation for a maximum period of 30 days.
     * To learn more about this policy's behavior, see {@link #TYPE_POSTPONE}.
     *
     * <p><b>Note: </b> security updates (e.g. monthly security patches) will <i>not</i> be affected
     * by this policy.
     *
     * @see #TYPE_POSTPONE
     */
    public static SystemUpdatePolicy createPostponeInstallPolicy() {
        SystemUpdatePolicy policy = new SystemUpdatePolicy();
        policy.mPolicyType = TYPE_POSTPONE;
        return policy;
    }

    /**
     * Returns the type of system update policy, or -1 if no policy has been set.
     *
     @return The policy type or -1 if the type isn't set.
     */
    @SystemUpdatePolicyType
    public int getPolicyType() {
        return mPolicyType;
    }

    /**
     * Get the start of the maintenance window.
     *
     * @return the start of the maintenance window measured as the number of minutes from midnight,
     * or -1 if the policy does not have a maintenance window.
     */
    public int getInstallWindowStart() {
        if (mPolicyType == TYPE_INSTALL_WINDOWED) {
            return mMaintenanceWindowStart;
        } else {
            return -1;
        }
    }

    /**
     * Get the end of the maintenance window.
     *
     * @return the end of the maintenance window measured as the number of minutes from midnight,
     * or -1 if the policy does not have a maintenance window.
     */
    public int getInstallWindowEnd() {
        if (mPolicyType == TYPE_INSTALL_WINDOWED) {
            return mMaintenanceWindowEnd;
        } else {
            return -1;
        }
    }

    /**
     * Return if this object represents a valid policy with:
     * 1. Correct type
     * 2. Valid maintenance window if applicable
     * 3. Valid freeze periods
     * @hide
     */
    public boolean isValid() {
        try {
            validateType();
            validateFreezePeriods();
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    /**
     * Validate the type and maintenance window (if applicable) of this policy object,
     * throws {@link IllegalArgumentException} if it's invalid.
     * @hide
     */
    public void validateType() {
        if (mPolicyType == TYPE_INSTALL_AUTOMATIC || mPolicyType == TYPE_POSTPONE) {
            return;
        } else if (mPolicyType == TYPE_INSTALL_WINDOWED) {
            if (!(mMaintenanceWindowStart >= 0 && mMaintenanceWindowStart < WINDOW_BOUNDARY
                    && mMaintenanceWindowEnd >= 0 && mMaintenanceWindowEnd < WINDOW_BOUNDARY)) {
                throw new IllegalArgumentException("Invalid maintenance window");
            }
        } else {
            throw new IllegalArgumentException("Invalid system update policy type.");
        }
    }

    /**
     * Configure a list of freeze periods on top of the current policy. When the device's clock is
     * within any of the freeze periods, all incoming system updates including security patches will
     * be blocked and cannot be installed. When the device is outside the freeze periods, the normal
     * policy behavior will apply.
     * <p>
     * Each individual freeze period is allowed to be at most 90 days long, and adjacent freeze
     * periods need to be at least 60 days apart. Also, the list of freeze periods should not
     * contain duplicates or overlap with each other. If any of these conditions is not met, a
     * {@link ValidationFailedException} will be thrown.
     * <p>
     * Handling of leap year: we ignore leap years in freeze period calculations, in particular,
     * <ul>
     * <li>When a freeze period is defined, February 29th is disregarded so even though a freeze
     * period can be specified to start or end on February 29th, it will be treated as if the period
     * started or ended on February 28th.</li>
     * <li>When applying freeze period behavior to the device, a system clock of February 29th is
     * treated as if it were February 28th</li>
     * <li>When calculating the number of days of a freeze period or separation between two freeze
     * periods, February 29th is also ignored and not counted as one day.</li>
     * </ul>
     *
     * @param freezePeriods the list of freeze periods
     * @throws ValidationFailedException if the supplied freeze periods do not meet the
     *         requirement set above
     * @return this instance
     */
    public SystemUpdatePolicy setFreezePeriods(List<FreezePeriod> freezePeriods) {
        FreezePeriod.validatePeriods(freezePeriods);
        mFreezePeriods.clear();
        mFreezePeriods.addAll(freezePeriods);
        return this;
    }

    /**
     * Returns the list of freeze periods previously set on this system update policy object.
     *
     * @return the list of freeze periods, or an empty list if none was set.
     */
    public List<FreezePeriod> getFreezePeriods() {
        return Collections.unmodifiableList(mFreezePeriods);
    }

    /**
     * Returns the real calendar dates of the current freeze period, or null if the device
     * is not in a freeze period at the moment.
     * @hide
     */
    public Pair<LocalDate, LocalDate> getCurrentFreezePeriod(LocalDate now) {
        for (FreezePeriod interval : mFreezePeriods) {
            if (interval.contains(now)) {
                return interval.toCurrentOrFutureRealDates(now);
            }
        }
        return null;
    }

    /**
     * Returns time (in milliseconds) until the start of the next freeze period, assuming now
     * is not within a freeze period.
     */
    private long timeUntilNextFreezePeriod(long now) {
        List<FreezePeriod> sortedPeriods = FreezePeriod.canonicalizePeriods(mFreezePeriods);
        LocalDate nowDate = millisToDate(now);
        LocalDate nextFreezeStart = null;
        for (FreezePeriod interval : sortedPeriods) {
            if (interval.after(nowDate)) {
                nextFreezeStart = interval.toCurrentOrFutureRealDates(nowDate).first;
                break;
            } else if (interval.contains(nowDate)) {
                throw new IllegalArgumentException("Given date is inside a freeze period");
            }
        }
        if (nextFreezeStart == null) {
            // If no interval is after now, then it must be the one that starts at the beginning
            // of next year
            nextFreezeStart = sortedPeriods.get(0).toCurrentOrFutureRealDates(nowDate).first;
        }
        return dateToMillis(nextFreezeStart) - now;
    }

    /** @hide */
    public void validateFreezePeriods() {
        FreezePeriod.validatePeriods(mFreezePeriods);
    }

    /** @hide */
    public void validateAgainstPreviousFreezePeriod(LocalDate prevPeriodStart,
            LocalDate prevPeriodEnd, LocalDate now) {
        FreezePeriod.validateAgainstPreviousFreezePeriod(mFreezePeriods, prevPeriodStart,
                prevPeriodEnd, now);
    }

    /**
     * An installation option represents how system update clients should act on incoming system
     * 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> {@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
     * time, in milliseconds.
     *
     * This is an internal API for system update clients.
     * @hide
     */
    @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(@InstallationOptionType int type, long effectiveTime) {
            this.mType = type;
            this.mEffectiveTime = effectiveTime;
        }

        /**
         * 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;
        }

        /** @hide */
        protected void limitEffectiveTime(long otherTime) {
            mEffectiveTime = Long.min(mEffectiveTime, otherTime);
        }
    }

    /**
     * Returns the installation option at the specified time, under the current
     * {@code SystemUpdatePolicy} object. This is a convenience method for system update clients
     * so they can instantiate this policy at any given time and find out what to do with incoming
     * system updates, without the need of examining the overall policy structure.
     *
     * Normally the system update clients will query the current installation option by calling this
     * method with the current timestamp, and act on the returned option until its effective time
     * lapses. It can then query the latest option using a new timestamp. It should also listen
     * for {@code DevicePolicyManager#ACTION_SYSTEM_UPDATE_POLICY_CHANGED} broadcast, in case the
     * whole policy is updated.
     *
     * @param when At what time the intallation option is being queried, specified in number of
           milliseonds since the epoch.
     * @see InstallationOption
     * @hide
     */
    @SystemApi
    public InstallationOption getInstallationOptionAt(long when) {
        LocalDate whenDate = millisToDate(when);
        Pair<LocalDate, LocalDate> current = getCurrentFreezePeriod(whenDate);
        if (current != null) {
            return new InstallationOption(TYPE_PAUSE,
                    dateToMillis(roundUpLeapDay(current.second).plusDays(1)) - when);
        }
        // We are not within a freeze period, query the underlying policy.
        // But also consider the start of the next freeze period, which might
        // reduce the effective time of the current installation option
        InstallationOption option = getInstallationOptionRegardlessFreezeAt(when);
        if (mFreezePeriods.size() > 0) {
            option.limitEffectiveTime(timeUntilNextFreezePeriod(when));
        }
        return option;
    }

    private InstallationOption getInstallationOptionRegardlessFreezeAt(long when) {
        if (mPolicyType == TYPE_INSTALL_AUTOMATIC || mPolicyType == TYPE_POSTPONE) {
            return new InstallationOption(mPolicyType, Long.MAX_VALUE);
        } else if (mPolicyType == TYPE_INSTALL_WINDOWED) {
            Calendar query = Calendar.getInstance();
            query.setTimeInMillis(when);
            // Calculate the number of milliseconds since midnight of the time specified by when
            long whenMillis = TimeUnit.HOURS.toMillis(query.get(Calendar.HOUR_OF_DAY))
                    + TimeUnit.MINUTES.toMillis(query.get(Calendar.MINUTE))
                    + TimeUnit.SECONDS.toMillis(query.get(Calendar.SECOND))
                    + query.get(Calendar.MILLISECOND);
            long windowStartMillis = TimeUnit.MINUTES.toMillis(mMaintenanceWindowStart);
            long windowEndMillis = TimeUnit.MINUTES.toMillis(mMaintenanceWindowEnd);
            final long dayInMillis = TimeUnit.DAYS.toMillis(1);

            if ((windowStartMillis <= whenMillis && whenMillis <= windowEndMillis)
                    || ((windowStartMillis > windowEndMillis)
                    && (windowStartMillis <= whenMillis || whenMillis <= windowEndMillis))) {
                return new InstallationOption(TYPE_INSTALL_AUTOMATIC,
                        (windowEndMillis - whenMillis + dayInMillis) % dayInMillis);
            } else {
                return new InstallationOption(TYPE_PAUSE,
                        (windowStartMillis - whenMillis + dayInMillis) % dayInMillis);
            }
        } else {
            throw new RuntimeException("Unknown policy type");
        }
    }

    private static LocalDate roundUpLeapDay(LocalDate date) {
        if (date.isLeapYear() && date.getMonthValue() == 2 && date.getDayOfMonth() == 28) {
            return date.plusDays(1);
        } else {
            return date;
        }
    }

    /** Convert a timestamp since epoch to a LocalDate using default timezone, truncating
     * the hour/min/seconds part.
     */
    private static LocalDate millisToDate(long when) {
        return Instant.ofEpochMilli(when).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * Returns the timestamp since epoch of a LocalDate, assuming the time is 00:00:00.
     */
    private static long dateToMillis(LocalDate when) {
        return LocalDateTime.of(when, LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant()
                .toEpochMilli();
    }

    @Override
    public String toString() {
        return String.format("SystemUpdatePolicy (type: %d, windowStart: %d, windowEnd: %d, "
                + "freezes: [%s])",
                mPolicyType, mMaintenanceWindowStart, mMaintenanceWindowEnd,
                mFreezePeriods.stream().map(n -> n.toString()).collect(Collectors.joining(",")));
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mPolicyType);
        dest.writeInt(mMaintenanceWindowStart);
        dest.writeInt(mMaintenanceWindowEnd);
        int freezeCount = mFreezePeriods.size();
        dest.writeInt(freezeCount);
        for (int i = 0; i < freezeCount; i++) {
            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());
        }
    }

    public static final @android.annotation.NonNull Parcelable.Creator<SystemUpdatePolicy> CREATOR =
            new Parcelable.Creator<SystemUpdatePolicy>() {

                @Override
                public SystemUpdatePolicy createFromParcel(Parcel source) {
                    SystemUpdatePolicy policy = new SystemUpdatePolicy();
                    policy.mPolicyType = source.readInt();
                    policy.mMaintenanceWindowStart = source.readInt();
                    policy.mMaintenanceWindowEnd = source.readInt();
                    int freezeCount = source.readInt();
                    policy.mFreezePeriods.ensureCapacity(freezeCount);
                    for (int i = 0; i < freezeCount; i++) {
                        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;
                }

                @Override
                public SystemUpdatePolicy[] newArray(int size) {
                    return new SystemUpdatePolicy[size];
                }
    };

    /**
     * Restore a previously saved SystemUpdatePolicy from XML. No need to validate
     * the reconstructed policy since the XML is supposed to be created by the
     * system server from a validated policy object previously.
     * @hide
     */
    public static SystemUpdatePolicy restoreFromXml(XmlPullParser parser) {
        try {
            SystemUpdatePolicy policy = new SystemUpdatePolicy();
            String value = parser.getAttributeValue(null, KEY_POLICY_TYPE);
            if (value != null) {
                policy.mPolicyType = Integer.parseInt(value);

                value = parser.getAttributeValue(null, KEY_INSTALL_WINDOW_START);
                if (value != null) {
                    policy.mMaintenanceWindowStart = Integer.parseInt(value);
                }
                value = parser.getAttributeValue(null, KEY_INSTALL_WINDOW_END);
                if (value != null) {
                    policy.mMaintenanceWindowEnd = Integer.parseInt(value);
                }

                int outerDepth = parser.getDepth();
                int type;
                while ((type = parser.next()) != END_DOCUMENT
                        && (type != END_TAG || parser.getDepth() > outerDepth)) {
                    if (type == END_TAG || type == TEXT) {
                        continue;
                    }
                    if (!parser.getName().equals(KEY_FREEZE_TAG)) {
                        continue;
                    }
                    policy.mFreezePeriods.add(new FreezePeriod(
                            MonthDay.parse(parser.getAttributeValue(null, KEY_FREEZE_START)),
                            MonthDay.parse(parser.getAttributeValue(null, KEY_FREEZE_END))));
                }
                return policy;
            }
        } catch (NumberFormatException | XmlPullParserException | IOException e) {
            // Fail through
            Log.w(TAG, "Load xml failed", e);
        }
        return null;
    }

    /**
     * @hide
     */
    public void saveToXml(XmlSerializer out) throws IOException {
        out.attribute(null, KEY_POLICY_TYPE, Integer.toString(mPolicyType));
        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++) {
            FreezePeriod interval = mFreezePeriods.get(i);
            out.startTag(null, KEY_FREEZE_TAG);
            out.attribute(null, KEY_FREEZE_START, interval.getStart().toString());
            out.attribute(null, KEY_FREEZE_END, interval.getEnd().toString());
            out.endTag(null, KEY_FREEZE_TAG);
        }
    }
}

