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

