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 com.android.internal.util.Preconditions.checkArgument; 20 import static com.android.internal.util.Preconditions.checkNotNull; 21 22 23 import android.accounts.Account; 24 import android.content.Context; 25 import android.content.ComponentName; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.os.PersistableBundle; 29 import android.support.annotation.Nullable; 30 import android.text.TextUtils; 31 32 import java.util.Arrays; 33 import java.util.Locale; 34 import java.util.Objects; 35 import java.util.Set; 36 37 import com.android.internal.annotations.Immutable; 38 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException; 39 import com.android.managedprovisioning.common.Utils; 40 41 /** 42 * Provisioning parameters for Device Owner and Profile Owner provisioning. 43 */ 44 public final class ProvisioningParams implements Parcelable { 45 public static final long DEFAULT_LOCAL_TIME = -1; 46 public static final Integer DEFAULT_MAIN_COLOR = null; 47 public static final boolean DEFAULT_STARTED_BY_TRUSTED_SOURCE = false; 48 public static final boolean DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED = false; 49 public static final boolean DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION = false; 50 public static final boolean DEFAULT_SKIP_USER_SETUP = true; 51 // Intent extra used internally for passing data between activities and service. 52 public static final String EXTRA_PROVISIONING_PARAMS = "provisioningParams"; 53 54 public static final Parcelable.Creator<ProvisioningParams> CREATOR 55 = new Parcelable.Creator<ProvisioningParams>() { 56 @Override 57 public ProvisioningParams createFromParcel(Parcel in) { 58 return new ProvisioningParams(in); 59 } 60 61 @Override 62 public ProvisioningParams[] newArray(int size) { 63 return new ProvisioningParams[size]; 64 } 65 }; 66 67 @Nullable 68 public final String timeZone; 69 70 public final long localTime; 71 72 @Nullable 73 public final Locale locale; 74 75 /** WiFi configuration. */ 76 @Nullable 77 public final WifiInfo wifiInfo; 78 79 /** 80 * Package name of the device admin package. 81 * 82 * <p>At least one one of deviceAdminPackageName and deviceAdminComponentName should be 83 * non-null. 84 */ 85 @Deprecated 86 public final String deviceAdminPackageName; 87 88 /** 89 * {@link ComponentName} of the device admin package. 90 * 91 * <p>At least one one of deviceAdminPackageName and deviceAdminComponentName should be 92 * non-null. 93 */ 94 public final ComponentName deviceAdminComponentName; 95 96 /** {@link Account} that should be migrated to the managed profile. */ 97 @Nullable 98 public final Account accountToMigrate; 99 100 /** Provisioning action comes along with the provisioning data. */ 101 public final String provisioningAction; 102 103 /** 104 * The main color theme used in managed profile only. 105 * 106 * <p>{@code null} means the default value. 107 */ 108 @Nullable 109 public final Integer mainColor; 110 111 /** The download information of device admin package. */ 112 @Nullable 113 public final PackageDownloadInfo deviceAdminDownloadInfo; 114 115 /** 116 * Custom key-value pairs from enterprise mobility management which are passed to device admin 117 * package after provisioning. 118 * 119 * <p>Note that {@link ProvisioningParams} is not immutable because this field is mutable. 120 */ 121 @Nullable 122 public final PersistableBundle adminExtrasBundle; 123 124 /** 125 * True iff provisioning flow was started by a trusted app. This includes Nfc bump and QR code. 126 */ 127 public final boolean startedByTrustedSource; 128 129 /** True if all system apps should be enabled after provisioning. */ 130 public final boolean leaveAllSystemAppsEnabled; 131 132 /** True if device encryption should be skipped. */ 133 public final boolean skipEncryption; 134 135 /** True if user setup can be skipped. */ 136 public final boolean skipUserSetup; 137 138 // TODO (stevenckng): This shouldn't belong here. Remove this logic from ProvisioningParams. 139 private ComponentName inferedDeviceAdminComponentName; 140 141 private final Utils mUtils = new Utils(); 142 143 public String inferDeviceAdminPackageName() { 144 if (deviceAdminComponentName != null) { 145 return deviceAdminComponentName.getPackageName(); 146 } 147 return deviceAdminPackageName; 148 } 149 150 // This should not be called if the app has not been installed yet. 151 public ComponentName inferDeviceAdminComponentName(Context c) 152 throws IllegalProvisioningArgumentException { 153 if (inferedDeviceAdminComponentName == null) { 154 inferedDeviceAdminComponentName = mUtils.findDeviceAdmin( 155 deviceAdminPackageName, deviceAdminComponentName, c); 156 } 157 return inferedDeviceAdminComponentName; 158 } 159 160 private ProvisioningParams(Builder builder) { 161 timeZone = builder.mTimeZone; 162 localTime = builder.mLocalTime; 163 locale = builder.mLocale; 164 165 wifiInfo = builder.mWifiInfo; 166 167 deviceAdminComponentName = builder.mDeviceAdminComponentName; 168 deviceAdminPackageName = builder.mDeviceAdminPackageName; 169 170 deviceAdminDownloadInfo = builder.mDeviceAdminDownloadInfo; 171 172 adminExtrasBundle = builder.mAdminExtrasBundle; 173 174 startedByTrustedSource = builder.mStartedByTrustedSource; 175 leaveAllSystemAppsEnabled = builder.mLeaveAllSystemAppsEnabled; 176 skipEncryption = builder.mSkipEncryption; 177 accountToMigrate = builder.mAccountToMigrate; 178 provisioningAction = checkNotNull(builder.mProvisioningAction); 179 mainColor = builder.mMainColor; 180 skipUserSetup = builder.mSkipUserSetup; 181 182 validateFields(); 183 } 184 185 private ProvisioningParams(Parcel in) { 186 timeZone = in.readString(); 187 localTime = in.readLong(); 188 locale = (Locale) in.readSerializable(); 189 190 wifiInfo = (WifiInfo) in.readParcelable(WifiInfo.class.getClassLoader()); 191 192 deviceAdminPackageName = in.readString(); 193 deviceAdminComponentName = (ComponentName) 194 in.readParcelable(null /* use default classloader */); 195 196 deviceAdminDownloadInfo = 197 (PackageDownloadInfo) in.readParcelable(PackageDownloadInfo.class.getClassLoader()); 198 199 adminExtrasBundle = in.readParcelable(null /* use default classloader */); 200 201 startedByTrustedSource = in.readInt() == 1; 202 leaveAllSystemAppsEnabled = in.readInt() == 1; 203 skipEncryption = in.readInt() == 1; 204 accountToMigrate = (Account) in.readParcelable(null /* use default classloader */); 205 provisioningAction = checkNotNull(in.readString()); 206 if (in.readInt() != 0) { 207 mainColor = in.readInt(); 208 } else { 209 mainColor = null; 210 } 211 skipUserSetup = in.readInt() == 1; 212 213 validateFields(); 214 } 215 216 private void validateFields() { 217 checkArgument(deviceAdminPackageName != null || deviceAdminComponentName != null); 218 } 219 220 @Override 221 public int describeContents() { 222 return 0; 223 } 224 225 @Override 226 public void writeToParcel(Parcel out, int flags) { 227 out.writeString(timeZone); 228 out.writeLong(localTime); 229 out.writeSerializable(locale); 230 231 out.writeParcelable(wifiInfo, 0 /* default */ ); 232 233 out.writeString(deviceAdminPackageName); 234 out.writeParcelable(deviceAdminComponentName, 0 /* default */); 235 236 out.writeParcelable(deviceAdminDownloadInfo, 0 /* default */); 237 238 out.writeParcelable(adminExtrasBundle, 0 /* default */); 239 240 out.writeInt(startedByTrustedSource ? 1 : 0); 241 out.writeInt(leaveAllSystemAppsEnabled ? 1 : 0); 242 out.writeInt(skipEncryption ? 1 : 0); 243 out.writeParcelable(accountToMigrate, 0 /* default */); 244 out.writeString(provisioningAction); 245 if (mainColor != null) { 246 out.writeInt(1); 247 out.writeInt(mainColor); 248 } else { 249 out.writeInt(0); 250 } 251 out.writeInt(skipUserSetup ? 1 : 0); 252 } 253 254 @Override 255 public boolean equals(Object o) { 256 if (this == o) { 257 return true; 258 } 259 if (o == null || getClass() != o.getClass()) { 260 return false; 261 } 262 ProvisioningParams that = (ProvisioningParams) o; 263 return localTime == that.localTime 264 && startedByTrustedSource == that.startedByTrustedSource 265 && leaveAllSystemAppsEnabled == that.leaveAllSystemAppsEnabled 266 && skipEncryption == that.skipEncryption 267 && skipUserSetup == that.skipUserSetup 268 && Objects.equals(timeZone, that.timeZone) 269 && Objects.equals(locale, that.locale) 270 && Objects.equals(wifiInfo, that.wifiInfo) 271 && Objects.equals(deviceAdminPackageName, that.deviceAdminPackageName) 272 && Objects.equals(deviceAdminComponentName, that.deviceAdminComponentName) 273 && Objects.equals(accountToMigrate, that.accountToMigrate) 274 && Objects.equals(provisioningAction, that.provisioningAction) 275 && Objects.equals(mainColor, that.mainColor) 276 && Objects.equals(deviceAdminDownloadInfo, that.deviceAdminDownloadInfo) 277 && isPersistableBundleEquals(adminExtrasBundle, that.adminExtrasBundle) 278 && Objects.equals( 279 inferedDeviceAdminComponentName, that.inferedDeviceAdminComponentName); 280 } 281 282 /** 283 * Compares two {@link PersistableBundle} objects are equals. 284 */ 285 private static boolean isPersistableBundleEquals( 286 PersistableBundle obj1, PersistableBundle obj2) { 287 if (obj1 == obj2) { 288 return true; 289 } 290 if (obj1 == null || obj2 == null || obj1.size() != obj2.size()) { 291 return false; 292 } 293 Set<String> keys = obj1.keySet(); 294 for (String key : keys) { 295 Object val1 = obj1.get(key); 296 Object val2 = obj2.get(key); 297 if (!isPersistableBundleSupportedValueEquals(val1, val2)) { 298 return false; 299 } 300 } 301 return true; 302 } 303 304 /** 305 * Compares two values which type is supported by {@link PersistableBundle}. 306 * 307 * <p>If the type isn't supported. The equality is done by {@link Object#equals(Object)}. 308 */ 309 private static boolean isPersistableBundleSupportedValueEquals(Object val1, Object val2) { 310 if (val1 == val2) { 311 return true; 312 } else if (val1 == null || val2 == null || !val1.getClass().equals(val2.getClass())) { 313 return false; 314 } else if (val1 instanceof PersistableBundle && val2 instanceof PersistableBundle) { 315 return isPersistableBundleEquals((PersistableBundle) val1, (PersistableBundle) val2); 316 } else if (val1 instanceof int[]) { 317 return Arrays.equals((int[]) val1, (int[]) val2); 318 } else if (val1 instanceof long[]) { 319 return Arrays.equals((long[]) val1, (long[]) val2); 320 } else if (val1 instanceof double[]) { 321 return Arrays.equals((double[]) val1, (double[]) val2); 322 } else if (val1 instanceof boolean[]) { 323 return Arrays.equals((boolean[]) val1, (boolean[]) val2); 324 } else if (val1 instanceof String[]) { 325 return Arrays.equals((String[]) val1, (String[]) val2); 326 } else { 327 return Objects.equals(val1, val2); 328 } 329 } 330 331 public final static class Builder { 332 private String mTimeZone; 333 private long mLocalTime = DEFAULT_LOCAL_TIME; 334 private Locale mLocale; 335 private WifiInfo mWifiInfo; 336 private String mDeviceAdminPackageName; 337 private ComponentName mDeviceAdminComponentName; 338 private Account mAccountToMigrate; 339 private String mProvisioningAction; 340 private Integer mMainColor = DEFAULT_MAIN_COLOR; 341 private PackageDownloadInfo mDeviceAdminDownloadInfo; 342 private PersistableBundle mAdminExtrasBundle; 343 private boolean mStartedByTrustedSource = DEFAULT_STARTED_BY_TRUSTED_SOURCE; 344 private boolean mLeaveAllSystemAppsEnabled = DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED; 345 private boolean mSkipEncryption = DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION; 346 private boolean mSkipUserSetup = DEFAULT_SKIP_USER_SETUP; 347 348 public Builder setTimeZone(String timeZone) { 349 mTimeZone = timeZone; 350 return this; 351 } 352 353 public Builder setLocalTime(long localTime) { 354 mLocalTime = localTime; 355 return this; 356 } 357 358 public Builder setLocale(Locale locale) { 359 mLocale = locale; 360 return this; 361 } 362 363 public Builder setWifiInfo(WifiInfo wifiInfo) { 364 mWifiInfo = wifiInfo; 365 return this; 366 } 367 368 @Deprecated 369 public Builder setDeviceAdminPackageName(String deviceAdminPackageName) { 370 mDeviceAdminPackageName = deviceAdminPackageName; 371 return this; 372 } 373 374 public Builder setDeviceAdminComponentName(ComponentName deviceAdminComponentName) { 375 mDeviceAdminComponentName = deviceAdminComponentName; 376 return this; 377 } 378 379 public Builder setAccountToMigrate(Account accountToMigrate) { 380 mAccountToMigrate = accountToMigrate; 381 return this; 382 } 383 384 public Builder setProvisioningAction(String provisioningAction) { 385 mProvisioningAction = provisioningAction; 386 return this; 387 } 388 389 public Builder setMainColor(Integer mainColor) { 390 mMainColor = mainColor; 391 return this; 392 } 393 394 public Builder setDeviceAdminDownloadInfo(PackageDownloadInfo deviceAdminDownloadInfo) { 395 mDeviceAdminDownloadInfo = deviceAdminDownloadInfo; 396 return this; 397 } 398 399 public Builder setAdminExtrasBundle(PersistableBundle adminExtrasBundle) { 400 mAdminExtrasBundle = adminExtrasBundle; 401 return this; 402 } 403 404 public Builder setStartedByTrustedSource(boolean startedByTrustedSource) { 405 mStartedByTrustedSource = startedByTrustedSource; 406 return this; 407 } 408 409 public Builder setLeaveAllSystemAppsEnabled(boolean leaveAllSystemAppsEnabled) { 410 mLeaveAllSystemAppsEnabled = leaveAllSystemAppsEnabled; 411 return this; 412 } 413 414 public Builder setSkipEncryption(boolean skipEncryption) { 415 mSkipEncryption = skipEncryption; 416 return this; 417 } 418 419 public Builder setSkipUserSetup(boolean skipUserSetup) { 420 mSkipUserSetup = skipUserSetup; 421 return this; 422 } 423 424 public ProvisioningParams build() { 425 return new ProvisioningParams(this); 426 } 427 428 public static Builder builder() { 429 return new Builder(); 430 } 431 } 432 } 433