1 /* 2 * Copyright 2016, 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 com.android.managedprovisioning.model; 18 19 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION; 20 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER; 21 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM; 22 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM; 23 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE; 24 import static com.android.internal.util.Preconditions.checkNotNull; 25 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.os.PersistableBundle; 29 import androidx.annotation.Nullable; 30 import android.text.TextUtils; 31 import com.android.internal.annotations.Immutable; 32 import com.android.managedprovisioning.common.PersistableBundlable; 33 import com.android.managedprovisioning.common.StoreUtils; 34 import java.io.IOException; 35 import java.util.Arrays; 36 import java.util.Objects; 37 import org.xmlpull.v1.XmlPullParser; 38 import org.xmlpull.v1.XmlPullParserException; 39 import org.xmlpull.v1.XmlSerializer; 40 41 /** 42 * Stores the device admin package download information. 43 */ 44 @Immutable 45 public final class PackageDownloadInfo extends PersistableBundlable { 46 public static final byte[] DEFAULT_PACKAGE_CHECKSUM = new byte[0]; 47 public static final byte[] DEFAULT_SIGNATURE_CHECKSUM = new byte[0]; 48 // Always download packages if no minimum version given. 49 public static final int DEFAULT_MINIMUM_VERSION = Integer.MAX_VALUE; 50 51 public static final Parcelable.Creator<PackageDownloadInfo> CREATOR 52 = new Parcelable.Creator<PackageDownloadInfo>() { 53 @Override 54 public PackageDownloadInfo createFromParcel(Parcel in) { 55 return new PackageDownloadInfo(in); 56 } 57 58 @Override 59 public PackageDownloadInfo[] newArray(int size) { 60 return new PackageDownloadInfo[size]; 61 } 62 }; 63 64 /** 65 * Url where the package (.apk) can be downloaded from. {@code null} if there is no download 66 * location specified. 67 */ 68 public final String location; 69 /** Cookie header for http request. */ 70 @Nullable 71 public final String cookieHeader; 72 /** 73 * One of the following two checksums should be non empty. SHA-256 hash of the 74 * .apk file, or empty array if not used. 75 */ 76 public final byte[] packageChecksum; 77 /** SHA-256 hash of the signature in the .apk file, or empty array if not used. */ 78 public final byte[] signatureChecksum; 79 /** Minimum supported version code of the downloaded package. */ 80 public final int minVersion; 81 PackageDownloadInfo(Builder builder)82 private PackageDownloadInfo(Builder builder) { 83 location = builder.mLocation; 84 cookieHeader = builder.mCookieHeader; 85 packageChecksum = checkNotNull(builder.mPackageChecksum, "package checksum can't be null"); 86 signatureChecksum = checkNotNull(builder.mSignatureChecksum, 87 "signature checksum can't be null"); 88 minVersion = builder.mMinVersion; 89 90 validateFields(); 91 } 92 PackageDownloadInfo(Parcel in)93 private PackageDownloadInfo(Parcel in) { 94 this(createBuilderFromPersistableBundle( 95 PersistableBundlable.getPersistableBundleFromParcel(in))); 96 } 97 validateFields()98 private void validateFields() { 99 if (TextUtils.isEmpty(location)) { 100 throw new IllegalArgumentException("Download location must not be empty."); 101 } 102 if (packageChecksum.length == 0 && signatureChecksum.length == 0) { 103 throw new IllegalArgumentException("Package checksum or signature checksum must be " 104 + "provided."); 105 } 106 } 107 fromPersistableBundle(PersistableBundle bundle)108 /* package */ static PackageDownloadInfo fromPersistableBundle(PersistableBundle bundle) { 109 return createBuilderFromPersistableBundle(bundle).build(); 110 } 111 createBuilderFromPersistableBundle(PersistableBundle bundle)112 private static Builder createBuilderFromPersistableBundle(PersistableBundle bundle) { 113 Builder builder = new Builder(); 114 builder.setMinVersion(bundle.getInt(EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE)); 115 builder.setLocation(bundle.getString( 116 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION)); 117 builder.setCookieHeader(bundle.getString( 118 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER)); 119 builder.setPackageChecksum(StoreUtils.stringToByteArray(bundle.getString( 120 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM))); 121 builder.setSignatureChecksum(StoreUtils.stringToByteArray(bundle.getString( 122 EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM))); 123 return builder; 124 } 125 126 @Override toPersistableBundle()127 public PersistableBundle toPersistableBundle() { 128 final PersistableBundle bundle = new PersistableBundle(); 129 bundle.putInt(EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE, 130 minVersion); 131 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION, location); 132 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER, 133 cookieHeader); 134 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM, 135 StoreUtils.byteArrayToString(packageChecksum)); 136 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM, 137 StoreUtils.byteArrayToString(signatureChecksum)); 138 return bundle; 139 } 140 141 public final static class Builder { 142 private String mLocation; 143 private String mCookieHeader; 144 private byte[] mPackageChecksum = DEFAULT_PACKAGE_CHECKSUM; 145 private byte[] mSignatureChecksum = DEFAULT_SIGNATURE_CHECKSUM; 146 private int mMinVersion = DEFAULT_MINIMUM_VERSION; 147 setLocation(String location)148 public Builder setLocation(String location) { 149 mLocation = location; 150 return this; 151 } 152 setCookieHeader(String cookieHeader)153 public Builder setCookieHeader(String cookieHeader) { 154 mCookieHeader = cookieHeader; 155 return this; 156 } 157 setPackageChecksum(byte[] packageChecksum)158 public Builder setPackageChecksum(byte[] packageChecksum) { 159 mPackageChecksum = packageChecksum; 160 return this; 161 } 162 setSignatureChecksum(byte[] signatureChecksum)163 public Builder setSignatureChecksum(byte[] signatureChecksum) { 164 mSignatureChecksum = signatureChecksum; 165 return this; 166 } 167 setMinVersion(int minVersion)168 public Builder setMinVersion(int minVersion) { 169 mMinVersion = minVersion; 170 return this; 171 } 172 build()173 public PackageDownloadInfo build() { 174 return new PackageDownloadInfo(this); 175 } 176 builder()177 public static Builder builder() { 178 return new Builder(); 179 } 180 } 181 } 182