Home | History | Annotate | Download | only in admin
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.app.admin;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.Nullable;
     21 import android.os.Build;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 
     25 import org.xmlpull.v1.XmlPullParser;
     26 import org.xmlpull.v1.XmlSerializer;
     27 
     28 import java.io.IOException;
     29 import java.lang.annotation.Retention;
     30 import java.lang.annotation.RetentionPolicy;
     31 import java.util.Objects;
     32 
     33 /**
     34  * A class containing information about a pending system update.
     35  */
     36 public final class SystemUpdateInfo implements Parcelable {
     37 
     38     /**
     39      * Represents it is unknown whether the system update is a security patch.
     40      */
     41     public static final int SECURITY_PATCH_STATE_UNKNOWN = 0;
     42 
     43     /**
     44      * Represents the system update is not a security patch.
     45      */
     46     public static final int SECURITY_PATCH_STATE_FALSE = 1;
     47 
     48     /**
     49      * Represents the system update is a security patch.
     50      */
     51     public static final int SECURITY_PATCH_STATE_TRUE = 2;
     52 
     53     /** @hide */
     54     @Retention(RetentionPolicy.SOURCE)
     55     @IntDef({SECURITY_PATCH_STATE_FALSE, SECURITY_PATCH_STATE_TRUE, SECURITY_PATCH_STATE_UNKNOWN})
     56     public @interface SecurityPatchState {}
     57 
     58     private static final String ATTR_RECEIVED_TIME = "received-time";
     59     private static final String ATTR_SECURITY_PATCH_STATE = "security-patch-state";
     60     // Tag used to store original build fingerprint to detect when the update is applied.
     61     private static final String ATTR_ORIGINAL_BUILD = "original-build";
     62 
     63     private final long mReceivedTime;
     64     @SecurityPatchState
     65     private final int mSecurityPatchState;
     66 
     67     private SystemUpdateInfo(long receivedTime, @SecurityPatchState int securityPatchState) {
     68         this.mReceivedTime = receivedTime;
     69         this.mSecurityPatchState = securityPatchState;
     70     }
     71 
     72     private SystemUpdateInfo(Parcel in) {
     73         mReceivedTime = in.readLong();
     74         mSecurityPatchState = in.readInt();
     75     }
     76 
     77     /** @hide */
     78     @Nullable
     79     public static SystemUpdateInfo of(long receivedTime) {
     80         return receivedTime == -1
     81                 ? null : new SystemUpdateInfo(receivedTime, SECURITY_PATCH_STATE_UNKNOWN);
     82     }
     83 
     84     /** @hide */
     85     @Nullable
     86     public static SystemUpdateInfo of(long receivedTime, boolean isSecurityPatch) {
     87         return receivedTime == -1 ? null : new SystemUpdateInfo(receivedTime,
     88                 isSecurityPatch ? SECURITY_PATCH_STATE_TRUE : SECURITY_PATCH_STATE_FALSE);
     89     }
     90 
     91     /**
     92      * Gets time when the update was first available in milliseconds since midnight, January 1,
     93      * 1970 UTC.
     94      * @return Time in milliseconds as given by {@link System#currentTimeMillis()}
     95      */
     96     public long getReceivedTime() {
     97         return mReceivedTime;
     98     }
     99 
    100     /**
    101      * Gets whether the update is a security patch.
    102      * @return {@link #SECURITY_PATCH_STATE_FALSE}, {@link #SECURITY_PATCH_STATE_TRUE}, or
    103      *         {@link #SECURITY_PATCH_STATE_UNKNOWN}.
    104      */
    105     @SecurityPatchState
    106     public int getSecurityPatchState() {
    107         return mSecurityPatchState;
    108     }
    109 
    110     public static final Creator<SystemUpdateInfo> CREATOR =
    111             new Creator<SystemUpdateInfo>() {
    112                 @Override
    113                 public SystemUpdateInfo createFromParcel(Parcel in) {
    114                     return new SystemUpdateInfo(in);
    115                 }
    116 
    117                 @Override
    118                 public SystemUpdateInfo[] newArray(int size) {
    119                     return new SystemUpdateInfo[size];
    120                 }
    121             };
    122 
    123     /** @hide */
    124     public void writeToXml(XmlSerializer out, String tag) throws IOException {
    125         out.startTag(null, tag);
    126         out.attribute(null, ATTR_RECEIVED_TIME, String.valueOf(mReceivedTime));
    127         out.attribute(null, ATTR_SECURITY_PATCH_STATE, String.valueOf(mSecurityPatchState));
    128         out.attribute(null, ATTR_ORIGINAL_BUILD , Build.FINGERPRINT);
    129         out.endTag(null, tag);
    130     }
    131 
    132     /** @hide */
    133     @Nullable
    134     public static SystemUpdateInfo readFromXml(XmlPullParser parser) {
    135         // If an OTA has been applied (build fingerprint has changed), discard stale info.
    136         final String buildFingerprint = parser.getAttributeValue(null, ATTR_ORIGINAL_BUILD );
    137         if (!Build.FINGERPRINT.equals(buildFingerprint)) {
    138             return null;
    139         }
    140         final long receivedTime =
    141                 Long.parseLong(parser.getAttributeValue(null, ATTR_RECEIVED_TIME));
    142         final int securityPatchState =
    143                 Integer.parseInt(parser.getAttributeValue(null, ATTR_SECURITY_PATCH_STATE));
    144         return new SystemUpdateInfo(receivedTime, securityPatchState);
    145     }
    146 
    147     @Override
    148     public int describeContents() {
    149         return 0;
    150     }
    151 
    152     @Override
    153     public void writeToParcel(Parcel dest, int flags) {
    154         dest.writeLong(getReceivedTime());
    155         dest.writeInt(getSecurityPatchState());
    156     }
    157 
    158     @Override
    159     public String toString() {
    160         return String.format("SystemUpdateInfo (receivedTime = %d, securityPatchState = %s)",
    161                 mReceivedTime, securityPatchStateToString(mSecurityPatchState));
    162     }
    163 
    164     private static String securityPatchStateToString(@SecurityPatchState int state) {
    165         switch (state) {
    166             case SECURITY_PATCH_STATE_FALSE:
    167                 return "false";
    168             case SECURITY_PATCH_STATE_TRUE:
    169                 return "true";
    170             case SECURITY_PATCH_STATE_UNKNOWN:
    171                 return "unknown";
    172             default:
    173                 throw new IllegalArgumentException("Unrecognized security patch state: " + state);
    174         }
    175     }
    176 
    177     @Override
    178     public boolean equals(Object o) {
    179         if (this == o) return true;
    180         if (o == null || getClass() != o.getClass()) return false;
    181         SystemUpdateInfo that = (SystemUpdateInfo) o;
    182         return mReceivedTime == that.mReceivedTime
    183                 && mSecurityPatchState == that.mSecurityPatchState;
    184     }
    185 
    186     @Override
    187     public int hashCode() {
    188         return Objects.hash(mReceivedTime, mSecurityPatchState);
    189     }
    190 }
    191