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_ACCOUNT_TO_MIGRATE; 20 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 21 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME; 22 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME; 23 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DISCLAIMERS; 24 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION; 25 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED; 26 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE; 27 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME; 28 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ORGANIZATION_NAME; 29 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS; 30 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION; 31 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SUPPORT_URL; 32 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE; 33 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_USE_MOBILE_DATA; 34 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_CLOUD_ENROLLMENT; 35 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_MANAGED_ACCOUNT; 36 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_QR_CODE; 37 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_UNSPECIFIED; 38 39 import static com.android.internal.util.Preconditions.checkArgument; 40 import static com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences.DEFAULT_PROVISIONING_ID; 41 import static com.android.managedprovisioning.common.StoreUtils.accountToPersistableBundle; 42 import static com.android.managedprovisioning.common.StoreUtils.getObjectAttrFromPersistableBundle; 43 import static com.android.managedprovisioning.common.StoreUtils.getStringAttrFromPersistableBundle; 44 import static com.android.managedprovisioning.common.StoreUtils.putPersistableBundlableIfNotNull; 45 46 import static java.util.Objects.requireNonNull; 47 48 import android.accounts.Account; 49 import android.annotation.IntDef; 50 import android.app.admin.DevicePolicyManager; 51 import android.content.ComponentName; 52 import android.content.Context; 53 import android.os.Parcel; 54 import android.os.Parcelable; 55 import android.os.PersistableBundle; 56 import android.util.AtomicFile; 57 import android.util.Xml; 58 59 import androidx.annotation.Nullable; 60 61 import com.android.internal.util.FastXmlSerializer; 62 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException; 63 import com.android.managedprovisioning.common.PersistableBundlable; 64 import com.android.managedprovisioning.common.ProvisionLogger; 65 import com.android.managedprovisioning.common.StoreUtils; 66 import com.android.managedprovisioning.common.Utils; 67 68 import org.xmlpull.v1.XmlPullParser; 69 import org.xmlpull.v1.XmlPullParserException; 70 import org.xmlpull.v1.XmlSerializer; 71 72 import java.io.File; 73 import java.io.FileInputStream; 74 import java.io.FileOutputStream; 75 import java.io.IOException; 76 import java.lang.annotation.Retention; 77 import java.lang.annotation.RetentionPolicy; 78 import java.nio.charset.StandardCharsets; 79 import java.util.ArrayList; 80 import java.util.Arrays; 81 import java.util.Locale; 82 import java.util.stream.Collectors; 83 84 /** 85 * Provisioning parameters for Device Owner and Profile Owner provisioning. 86 */ 87 public final class ProvisioningParams extends PersistableBundlable { 88 public static final long DEFAULT_LOCAL_TIME = -1; 89 public static final boolean DEFAULT_STARTED_BY_TRUSTED_SOURCE = false; 90 public static final boolean DEFAULT_IS_NFC = false; 91 public static final boolean DEFAULT_IS_QR_PROVISIONING = false; 92 public static final boolean DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED = false; 93 public static final boolean DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION = false; 94 public static final boolean DEFAULT_EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS = false; 95 public static final boolean DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED = false; 96 public static final boolean DEFAULT_EXTRA_PROVISIONING_USE_MOBILE_DATA = false; 97 public static final boolean DEFAULT_EXTRA_PROVISIONING_IS_ORGANIZATION_OWNED = false; 98 public static final ArrayList<Integer> DEFAULT_EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES = 99 new ArrayList<>(); 100 public static final int DEFAULT_EXTRA_PROVISIONING_SUPPORTED_MODES = 0; 101 public static final boolean DEFAULT_EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER = false; 102 public static final boolean DEFAULT_EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE = false; 103 public static final boolean DEFAULT_EXTRA_PROVISIONING_PERMISSION_GRANT_OPT_OUT = false; 104 public static final boolean DEFAULT_EXTRA_PROVISIONING_KEEP_SCREEN_ON = false; 105 public static final boolean DEFAULT_EXTRA_ALLOW_OFFLINE = false; 106 public static final boolean DEFAULT_EXTRA_PROVISIONING_SHOULD_LAUNCH_RESULT_INTENT = false; 107 108 109 // Intent extra used internally for passing data between activities and service. 110 public static final String EXTRA_PROVISIONING_PARAMS = "provisioningParams"; 111 112 public static final int FLOW_TYPE_UNSPECIFIED = 0; 113 public static final int FLOW_TYPE_LEGACY = 1; 114 public static final int FLOW_TYPE_ADMIN_INTEGRATED = 2; 115 116 @IntDef(prefix = { "PROVISIONING_TRIGGER_" }, value = { 117 PROVISIONING_TRIGGER_UNSPECIFIED, 118 PROVISIONING_TRIGGER_CLOUD_ENROLLMENT, 119 PROVISIONING_TRIGGER_QR_CODE, 120 PROVISIONING_TRIGGER_MANAGED_ACCOUNT 121 }) 122 @Retention(RetentionPolicy.SOURCE) 123 public @interface ProvisioningTrigger {} 124 125 @IntDef(prefix = { "FLOW_TYPE_" }, value = { 126 FLOW_TYPE_UNSPECIFIED, 127 FLOW_TYPE_LEGACY, 128 FLOW_TYPE_ADMIN_INTEGRATED 129 }) 130 @Retention(RetentionPolicy.SOURCE) 131 public @interface FlowType {} 132 133 private static final String TAG_PROVISIONING_ID = "provisioning-id"; 134 private static final String TAG_PROVISIONING_PARAMS = "provisioning-params"; 135 private static final String TAG_WIFI_INFO = "wifi-info"; 136 private static final String TAG_PACKAGE_DOWNLOAD_INFO = "download-info"; 137 private static final String TAG_STARTED_BY_TRUSTED_SOURCE = "started-by-trusted-source"; 138 private static final String TAG_IS_NFC = "started-is-nfc"; 139 private static final String TAG_IS_QR_PROVISIONING = "is-qr-provisioning"; 140 private static final String TAG_PROVISIONING_ACTION = "provisioning-action"; 141 private static final String TAG_IS_ORGANIZATION_OWNED_PROVISIONING = 142 "is-organization-owned-provisioning"; 143 private static final String TAG_ALLOWED_PROVISIONING_MODES = 144 "allowed-provisioning-modes"; 145 private static final String TAG_INITIATOR_REQUESTED_PROVISIONING_MODES = 146 "initiator-requested-provisioning-modes"; 147 private static final String TAG_FLOW_TYPE = "flow-type"; 148 private static final String TAG_ALLOW_PROVISIONING_AFTER_USER_SETUP_COMPLETE = 149 "allow-provisioning-after-user-setup-complete"; 150 private static final String TAG_PROVISIONING_TRIGGER = "provisioning-trigger"; 151 private static final String TAG_SKIP_OWNERSHIP_DISCLAIMER = "skip-ownership-disclaimer"; 152 private static final String TAG_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE = 153 "provisioning-return-before-policy-compliance"; 154 private static final String TAG_DEVICE_OWNER_PERMISSION_GRANT_OPT_OUT = 155 "device-owner-opt-out-of-permission-grants"; 156 private static final String TAG_KEEP_SCREEN_ON = "keep-screen-on"; 157 private static final String TAG_ALLOW_OFFLINE = "allow-offline"; 158 private static final String TAG_ROLE_HOLDER_PACKAGE_DOWNLOAD_INFO = 159 "role-holder-download-info"; 160 private static final String TAG_PROVISIONING_SHOULD_LAUNCH_RESULT_INTENT = 161 "provisioning-should-launch-result-intent"; 162 163 public static final Parcelable.Creator<ProvisioningParams> CREATOR 164 = new Parcelable.Creator<ProvisioningParams>() { 165 @Override 166 public ProvisioningParams createFromParcel(Parcel in) { 167 return new ProvisioningParams(in); 168 } 169 170 @Override 171 public ProvisioningParams[] newArray(int size) { 172 return new ProvisioningParams[size]; 173 } 174 }; 175 176 public final long provisioningId; 177 178 @Nullable 179 public final String timeZone; 180 181 public final long localTime; 182 183 @Nullable 184 public final Locale locale; 185 186 /** WiFi configuration. */ 187 @Nullable 188 public final WifiInfo wifiInfo; 189 190 public final boolean useMobileData; 191 192 /** 193 * Package name of the device admin package. 194 * 195 * <p>At least one one of deviceAdminPackageName and deviceAdminComponentName should be 196 * non-null. 197 * <p> 198 * In most cases, it is preferable to access the admin package name using 199 * {@link #inferDeviceAdminPackageName}. 200 */ 201 @Deprecated 202 @Nullable 203 public final String deviceAdminPackageName; 204 205 /** 206 * {@link ComponentName} of the device admin package. 207 * 208 * <p>At least one one of deviceAdminPackageName and deviceAdminComponentName should be 209 * non-null. 210 * <p> 211 * In most cases, it is preferable to access the admin component name using 212 * {@link #inferDeviceAdminComponentName(Utils, Context, int)} . 213 */ 214 @Nullable 215 public final ComponentName deviceAdminComponentName; 216 217 public final String organizationName; 218 public final String supportUrl; 219 220 /** {@link Account} that should be migrated to the managed profile. */ 221 @Nullable 222 public final Account accountToMigrate; 223 224 /** True if the account will not be removed from the calling user after it is migrated. */ 225 public final boolean keepAccountMigrated; 226 227 /** Provisioning action comes along with the provisioning data. */ 228 public final String provisioningAction; 229 230 /** The download information of device admin package. */ 231 @Nullable 232 public final PackageDownloadInfo deviceAdminDownloadInfo; 233 234 /** List of disclaimers */ 235 @Nullable 236 public final DisclaimersParam disclaimersParam; 237 238 /** 239 * Custom key-value pairs from enterprise mobility management which are passed to device admin 240 * package after provisioning. 241 * 242 * <p>Note that {@link ProvisioningParams} is not immutable because this field is mutable. 243 */ 244 @Nullable 245 public final PersistableBundle adminExtrasBundle; 246 247 /** 248 * True iff provisioning flow was started by a trusted app. This includes Nfc bump and QR code. 249 */ 250 public final boolean startedByTrustedSource; 251 252 public final boolean isNfc; 253 254 public final boolean isQrProvisioning; 255 256 /** True if all system apps should be enabled after provisioning. */ 257 public final boolean leaveAllSystemAppsEnabled; 258 259 /** True if device encryption should be skipped. */ 260 public final boolean skipEncryption; 261 262 public final boolean skipEducationScreens; 263 264 /** 265 * True if the provisioning is done on a device owned by the organization. 266 * 267 * <p>For the admin-integrated flow, this field is only set after the admin app 268 * picks a provisioning mode. 269 */ 270 public final boolean isOrganizationOwnedProvisioning; 271 272 /** 273 * {@link ArrayList} of {@link Integer} containing a subset of {{@link 274 * DevicePolicyManager#PROVISIONING_MODE_MANAGED_PROFILE}, {@link 275 * DevicePolicyManager#PROVISIONING_MODE_FULLY_MANAGED_DEVICE}, {@link 276 * DevicePolicyManager#PROVISIONING_MODE_MANAGED_PROFILE_ON_PERSONAL_DEVICE}}. 277 **/ 278 public final ArrayList<Integer> allowedProvisioningModes; 279 280 /** 281 * Integer specifying what provisioning modes have been specified by the provisioning 282 * initiator. 283 * 284 * <p>Can be a combination of {@link 285 * DevicePolicyManager#FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED}, {@link 286 * DevicePolicyManager#FLAG_SUPPORTED_MODES_PERSONALLY_OWNED}, {@link 287 * DevicePolicyManager#FLAG_SUPPORTED_MODES_DEVICE_OWNER} or if not relevant to the 288 * admin-integrated flow, {@link ProvisioningParams#DEFAULT_EXTRA_PROVISIONING_SUPPORTED_MODES}. 289 * 290 */ 291 public final int initiatorRequestedProvisioningModes; 292 293 /** True if provisioning after user setup complete should be allowed. */ 294 public final boolean allowProvisioningAfterUserSetupComplete; 295 296 /** 297 * The type of flow to be performed. 298 * <p>Must be one of {@link #FLOW_TYPE_UNSPECIFIED}, {@link #FLOW_TYPE_LEGACY} or {@link 299 * #FLOW_TYPE_ADMIN_INTEGRATED}. 300 **/ 301 public final @FlowType int flowType; 302 303 /** 304 * The way provisioning was started. 305 * <p>Can be one of {@link DevicePolicyManager#PROVISIONING_TRIGGER_CLOUD_ENROLLMENT}, {@link 306 * DevicePolicyManager#PROVISIONING_TRIGGER_QR_CODE}, {@link 307 * DevicePolicyManager#PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER} or {@link 308 * DevicePolicyManager#PROVISIONING_TRIGGER_UNSPECIFIED}. 309 */ 310 public final @ProvisioningTrigger int provisioningTrigger; 311 312 /** 313 * Whether to skip the ownership disclaimer. 314 */ 315 public final boolean skipOwnershipDisclaimer; 316 317 /** 318 * True if the provisioning flow should return before starting the admin app's {@link 319 * DevicePolicyManager#ACTION_ADMIN_POLICY_COMPLIANCE} handler. Default value is {@code true}. 320 */ 321 public final boolean returnBeforePolicyCompliance; 322 323 /** 324 * True if the device owner has opted out of controlling permission grants for 325 * sensors-related permissions. See {@link DevicePolicyManager#setPermissionGrantState} 326 */ 327 public final boolean deviceOwnerPermissionGrantOptOut; 328 329 /** 330 * {@code true} if the screen should be on throughout the provisioning flow 331 */ 332 public final boolean keepScreenOn; 333 334 /** 335 * {@code true} if offline provisioning is allowed 336 * 337 * <p>In T this can also be used to force platform side provisioning. 338 * 339 * @see DevicePolicyManager#EXTRA_PROVISIONING_ALLOW_OFFLINE 340 */ 341 public final boolean allowOffline; 342 343 /** 344 * {@code true} if provisioning should launch the result intent returned by the 345 * device manager role holder. 346 * 347 * {@code false} by default. 348 * 349 * @see DevicePolicyManager#EXTRA_PROVISIONING_SHOULD_LAUNCH_RESULT_INTENT 350 */ 351 public final boolean provisioningShouldLaunchResultIntent; 352 353 /** The download information of the role holder package. */ 354 @Nullable 355 public final PackageDownloadInfo roleHolderDownloadInfo; 356 inferStaticDeviceAdminPackageName(ComponentName deviceAdminComponentName, String deviceAdminPackageName)357 public static String inferStaticDeviceAdminPackageName(ComponentName deviceAdminComponentName, 358 String deviceAdminPackageName) { 359 if (deviceAdminComponentName != null) { 360 return deviceAdminComponentName.getPackageName(); 361 } 362 return deviceAdminPackageName; 363 } 364 inferDeviceAdminPackageName()365 public String inferDeviceAdminPackageName() { 366 return inferStaticDeviceAdminPackageName(deviceAdminComponentName, deviceAdminPackageName); 367 } 368 369 /** 370 * Due to legacy reason, DPC is allowed to provide either package name or the component name. 371 * If component name is not {@code null}, we will return it right away. Otherwise, we will 372 * infer the component name. 373 * <p> 374 * In most cases, it is preferable to access the admin component name using this method. 375 * But if the purpose is to verify the device admin component name, you should use 376 * {@link Utils#findDeviceAdmin(String, ComponentName, Context, int)} instead. 377 */ inferDeviceAdminComponentName(Utils utils, Context context, int userId)378 public ComponentName inferDeviceAdminComponentName(Utils utils, Context context, int userId) 379 throws IllegalProvisioningArgumentException { 380 if (deviceAdminComponentName != null) { 381 return deviceAdminComponentName; 382 } 383 return utils.findDeviceAdmin( 384 deviceAdminPackageName, deviceAdminComponentName, context, userId); 385 } 386 ProvisioningParams(Builder builder)387 private ProvisioningParams(Builder builder) { 388 provisioningId = builder.mProvisioningId; 389 timeZone = builder.mTimeZone; 390 localTime = builder.mLocalTime; 391 locale = builder.mLocale; 392 393 wifiInfo = builder.mWifiInfo; 394 useMobileData = builder.mUseMobileData; 395 396 deviceAdminComponentName = builder.mDeviceAdminComponentName; 397 deviceAdminPackageName = builder.mDeviceAdminPackageName; 398 organizationName = builder.mOrganizationName; 399 supportUrl = builder.mSupportUrl; 400 401 deviceAdminDownloadInfo = builder.mDeviceAdminDownloadInfo; 402 disclaimersParam = builder.mDisclaimersParam; 403 404 adminExtrasBundle = builder.mAdminExtrasBundle; 405 406 startedByTrustedSource = builder.mStartedByTrustedSource; 407 isNfc = builder.mIsNfc; 408 isQrProvisioning = builder.mIsQrProvisioning; 409 leaveAllSystemAppsEnabled = builder.mLeaveAllSystemAppsEnabled; 410 skipEncryption = builder.mSkipEncryption; 411 accountToMigrate = builder.mAccountToMigrate; 412 provisioningAction = builder.mProvisioningAction; 413 skipEducationScreens = builder.mSkipEducationScreens; 414 keepAccountMigrated = builder.mKeepAccountMigrated; 415 416 isOrganizationOwnedProvisioning = builder.mIsOrganizationOwnedProvisioning; 417 allowedProvisioningModes = builder.mAllowedProvisioningModes; 418 initiatorRequestedProvisioningModes = builder.mInitiatorRequestedProvisioningModes; 419 flowType = builder.mFlowType; 420 allowProvisioningAfterUserSetupComplete = builder.mAllowProvisioningAfterUserSetupComplete; 421 provisioningTrigger = builder.mProvisioningTrigger; 422 skipOwnershipDisclaimer = builder.mSkipOwnershipDisclaimer; 423 returnBeforePolicyCompliance = builder.mReturnBeforePolicyCompliance; 424 deviceOwnerPermissionGrantOptOut = builder.mDeviceOwnerPermissionGrantOptOut; 425 keepScreenOn = builder.mKeepScreenOn; 426 allowOffline = builder.mAllowOffline; 427 roleHolderDownloadInfo = builder.mRoleHolderDownloadInfo; 428 provisioningShouldLaunchResultIntent = builder.mProvisioningShouldLaunchResultIntent; 429 430 if (!builder.mSkipValidation) { 431 requireNonNull(provisioningAction); 432 validateFields(); 433 } 434 } 435 ProvisioningParams(Parcel in)436 private ProvisioningParams(Parcel in) { 437 this(createBuilderFromPersistableBundle( 438 PersistableBundlable.getPersistableBundleFromParcel(in))); 439 } 440 validateFields()441 private void validateFields() { 442 checkArgument(deviceAdminPackageName != null || deviceAdminComponentName != null); 443 } 444 445 @Override toPersistableBundle()446 public PersistableBundle toPersistableBundle() { 447 final PersistableBundle bundle = new PersistableBundle(); 448 449 bundle.putLong(TAG_PROVISIONING_ID, provisioningId); 450 bundle.putString(EXTRA_PROVISIONING_TIME_ZONE, timeZone); 451 bundle.putLong(EXTRA_PROVISIONING_LOCAL_TIME, localTime); 452 bundle.putString(EXTRA_PROVISIONING_LOCALE, StoreUtils.localeToString(locale)); 453 putPersistableBundlableIfNotNull(bundle, TAG_WIFI_INFO, wifiInfo); 454 bundle.putBoolean(EXTRA_PROVISIONING_USE_MOBILE_DATA, useMobileData); 455 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, deviceAdminPackageName); 456 bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, 457 StoreUtils.componentNameToString(deviceAdminComponentName)); 458 bundle.putString(EXTRA_PROVISIONING_ORGANIZATION_NAME, organizationName); 459 bundle.putString(EXTRA_PROVISIONING_SUPPORT_URL, supportUrl); 460 bundle.putPersistableBundle(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, accountToMigrate == null 461 ? null : accountToPersistableBundle(accountToMigrate)); 462 bundle.putString(TAG_PROVISIONING_ACTION, provisioningAction); 463 putPersistableBundlableIfNotNull(bundle, TAG_PACKAGE_DOWNLOAD_INFO, 464 deviceAdminDownloadInfo); 465 putPersistableBundlableIfNotNull(bundle, EXTRA_PROVISIONING_DISCLAIMERS, 466 disclaimersParam); 467 bundle.putPersistableBundle(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, adminExtrasBundle); 468 bundle.putBoolean(TAG_STARTED_BY_TRUSTED_SOURCE, startedByTrustedSource); 469 bundle.putBoolean(TAG_IS_NFC, isNfc); 470 bundle.putBoolean(TAG_IS_QR_PROVISIONING, isQrProvisioning); 471 bundle.putBoolean(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED, 472 leaveAllSystemAppsEnabled); 473 bundle.putBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION, skipEncryption); 474 bundle.putBoolean(EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS, skipEducationScreens); 475 bundle.putBoolean(EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION, keepAccountMigrated); 476 bundle.putBoolean(TAG_IS_ORGANIZATION_OWNED_PROVISIONING, isOrganizationOwnedProvisioning); 477 bundle.putIntArray(TAG_ALLOWED_PROVISIONING_MODES, 478 integerArrayListToIntArray(allowedProvisioningModes)); 479 bundle.putInt(TAG_INITIATOR_REQUESTED_PROVISIONING_MODES, 480 initiatorRequestedProvisioningModes); 481 bundle.putInt(TAG_FLOW_TYPE, flowType); 482 bundle.putBoolean(TAG_ALLOW_PROVISIONING_AFTER_USER_SETUP_COMPLETE, 483 allowProvisioningAfterUserSetupComplete); 484 bundle.putInt(TAG_PROVISIONING_TRIGGER, provisioningTrigger); 485 bundle.putBoolean(TAG_SKIP_OWNERSHIP_DISCLAIMER, skipOwnershipDisclaimer); 486 bundle.putBoolean(TAG_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE, 487 returnBeforePolicyCompliance); 488 bundle.putBoolean(TAG_DEVICE_OWNER_PERMISSION_GRANT_OPT_OUT, 489 deviceOwnerPermissionGrantOptOut); 490 bundle.putBoolean(TAG_KEEP_SCREEN_ON, keepScreenOn); 491 bundle.putBoolean(TAG_ALLOW_OFFLINE, allowOffline); 492 putPersistableBundlableIfNotNull(bundle, TAG_ROLE_HOLDER_PACKAGE_DOWNLOAD_INFO, 493 roleHolderDownloadInfo); 494 bundle.putBoolean(TAG_PROVISIONING_SHOULD_LAUNCH_RESULT_INTENT, 495 provisioningShouldLaunchResultIntent); 496 return bundle; 497 } 498 fromPersistableBundle(PersistableBundle bundle)499 /* package */ static ProvisioningParams fromPersistableBundle(PersistableBundle bundle) { 500 return createBuilderFromPersistableBundle(bundle).build(); 501 } 502 createBuilderFromPersistableBundle(PersistableBundle bundle)503 private static Builder createBuilderFromPersistableBundle(PersistableBundle bundle) { 504 Builder builder = new Builder(/* skipValidation= */ false); 505 builder.setProvisioningId(bundle.getLong(TAG_PROVISIONING_ID, DEFAULT_PROVISIONING_ID)); 506 builder.setTimeZone(bundle.getString(EXTRA_PROVISIONING_TIME_ZONE)); 507 builder.setLocalTime(bundle.getLong(EXTRA_PROVISIONING_LOCAL_TIME)); 508 builder.setLocale(getStringAttrFromPersistableBundle(bundle, 509 EXTRA_PROVISIONING_LOCALE, StoreUtils::stringToLocale)); 510 builder.setUseMobileData(bundle.getBoolean(EXTRA_PROVISIONING_USE_MOBILE_DATA)); 511 builder.setWifiInfo(getObjectAttrFromPersistableBundle(bundle, 512 TAG_WIFI_INFO, WifiInfo::fromPersistableBundle)); 513 builder.setDeviceAdminPackageName(bundle.getString( 514 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME)); 515 builder.setDeviceAdminComponentName(getStringAttrFromPersistableBundle(bundle, 516 EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, StoreUtils::stringToComponentName)); 517 builder.setOrganizationName(bundle.getString(EXTRA_PROVISIONING_ORGANIZATION_NAME)); 518 builder.setSupportUrl(bundle.getString(EXTRA_PROVISIONING_SUPPORT_URL)); 519 builder.setAccountToMigrate(getObjectAttrFromPersistableBundle(bundle, 520 EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, StoreUtils::persistableBundleToAccount)); 521 builder.setProvisioningAction(bundle.getString(TAG_PROVISIONING_ACTION)); 522 builder.setDeviceAdminDownloadInfo(getObjectAttrFromPersistableBundle(bundle, 523 TAG_PACKAGE_DOWNLOAD_INFO, PackageDownloadInfo::fromPersistableBundle)); 524 builder.setDisclaimersParam(getObjectAttrFromPersistableBundle(bundle, 525 EXTRA_PROVISIONING_DISCLAIMERS, DisclaimersParam::fromPersistableBundle)); 526 builder.setAdminExtrasBundle(bundle.getPersistableBundle( 527 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE)); 528 builder.setStartedByTrustedSource(bundle.getBoolean(TAG_STARTED_BY_TRUSTED_SOURCE)); 529 builder.setIsNfc(bundle.getBoolean(TAG_IS_NFC)); 530 builder.setIsQrProvisioning(bundle.getBoolean(TAG_IS_QR_PROVISIONING)); 531 builder.setSkipEncryption(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION)); 532 builder.setLeaveAllSystemAppsEnabled(bundle.getBoolean( 533 EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED)); 534 builder.setSkipEducationScreens(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS)); 535 builder.setKeepAccountMigrated(bundle.getBoolean( 536 EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION)); 537 builder.setIsOrganizationOwnedProvisioning(bundle.getBoolean( 538 TAG_IS_ORGANIZATION_OWNED_PROVISIONING)); 539 builder.setAllowedProvisioningModes( 540 intArrayToIntegerArrayList(bundle.getIntArray(TAG_ALLOWED_PROVISIONING_MODES))); 541 builder.setInitiatorRequestedProvisioningModes(bundle.getInt( 542 TAG_INITIATOR_REQUESTED_PROVISIONING_MODES)); 543 builder.setFlowType(bundle.getInt(TAG_FLOW_TYPE)); 544 builder.setAllowProvisioningAfterUserSetupComplete(bundle.getBoolean( 545 TAG_ALLOW_PROVISIONING_AFTER_USER_SETUP_COMPLETE)); 546 builder.setProvisioningTrigger(bundle.getInt(TAG_PROVISIONING_TRIGGER)); 547 builder.setSkipOwnershipDisclaimer(bundle.getBoolean(TAG_SKIP_OWNERSHIP_DISCLAIMER)); 548 builder.setReturnBeforePolicyCompliance(bundle.getBoolean( 549 TAG_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE)); 550 builder.setDeviceOwnerPermissionGrantOptOut( 551 bundle.getBoolean(TAG_DEVICE_OWNER_PERMISSION_GRANT_OPT_OUT)); 552 builder.setKeepScreenOn(bundle.getBoolean(TAG_KEEP_SCREEN_ON)); 553 builder.setAllowOffline(bundle.getBoolean(TAG_ALLOW_OFFLINE)); 554 builder.setRoleHolderDownloadInfo(getObjectAttrFromPersistableBundle( 555 bundle, 556 TAG_ROLE_HOLDER_PACKAGE_DOWNLOAD_INFO, 557 PackageDownloadInfo::fromPersistableBundle)); 558 builder.setProvisioningShouldLaunchResultIntent( 559 bundle.getBoolean(TAG_PROVISIONING_SHOULD_LAUNCH_RESULT_INTENT)); 560 return builder; 561 } 562 intArrayToIntegerArrayList(int[] intArray)563 private static ArrayList<Integer> intArrayToIntegerArrayList(int[] intArray) { 564 return Arrays.stream(intArray).boxed().collect(Collectors.toCollection(ArrayList::new)); 565 } 566 integerArrayListToIntArray(ArrayList<Integer> arrayList)567 private static int[] integerArrayListToIntArray(ArrayList<Integer> arrayList) { 568 return arrayList.stream().mapToInt(Integer::valueOf).toArray(); 569 } 570 toBuilder()571 public Builder toBuilder() { 572 return createBuilderFromPersistableBundle(toPersistableBundle()); 573 } 574 575 @Override toString()576 public String toString() { 577 return "ProvisioningParams values: " + toPersistableBundle().toString(); 578 } 579 580 /** 581 * Saves the ProvisioningParams to the specified file. 582 */ save(File file)583 public void save(File file) { 584 ProvisionLogger.logd("Saving ProvisioningParams to " + file); 585 AtomicFile atomicFile = null; 586 FileOutputStream stream = null; 587 try { 588 atomicFile = new AtomicFile(file); 589 stream = atomicFile.startWrite(); 590 XmlSerializer serializer = new FastXmlSerializer(); 591 serializer.setOutput(stream, StandardCharsets.UTF_8.name()); 592 serializer.startDocument(null, true); 593 serializer.startTag(null, TAG_PROVISIONING_PARAMS); 594 toPersistableBundle().saveToXml(serializer); 595 serializer.endTag(null, TAG_PROVISIONING_PARAMS); 596 serializer.endDocument(); 597 atomicFile.finishWrite(stream); 598 } catch (IOException | XmlPullParserException e) { 599 ProvisionLogger.loge("Caught exception while trying to save Provisioning Params to " 600 + " file " + file, e); 601 file.delete(); 602 if (atomicFile != null) { 603 atomicFile.failWrite(stream); 604 } 605 } 606 } 607 cleanUp()608 public void cleanUp() { 609 if (disclaimersParam != null) { 610 disclaimersParam.cleanUp(); 611 } 612 } 613 614 /** 615 * Loads the ProvisioningParams From the specified file. 616 */ load(File file)617 public static ProvisioningParams load(File file) { 618 if (!file.exists()) { 619 return null; 620 } 621 ProvisionLogger.logd("Loading ProvisioningParams from " + file); 622 try (FileInputStream stream = new FileInputStream(file)) { 623 XmlPullParser parser = Xml.newPullParser(); 624 parser.setInput(stream, null); 625 return load(parser); 626 } catch (IOException | XmlPullParserException e) { 627 ProvisionLogger.loge("Caught exception while trying to load the provisioning params" 628 + " from file " + file, e); 629 return null; 630 } 631 } 632 load(XmlPullParser parser)633 private static ProvisioningParams load(XmlPullParser parser) throws XmlPullParserException, 634 IOException { 635 int type; 636 int outerDepth = parser.getDepth(); 637 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 638 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 639 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 640 continue; 641 } 642 String tag = parser.getName(); 643 switch (tag) { 644 case TAG_PROVISIONING_PARAMS: 645 return createBuilderFromPersistableBundle( 646 PersistableBundle.restoreFromXml(parser)).build(); 647 } 648 } 649 return new Builder(/* skipValidation= */ false).build(); 650 } 651 652 public final static class Builder { 653 private final boolean mSkipValidation; 654 private long mProvisioningId; 655 private String mTimeZone; 656 private long mLocalTime = DEFAULT_LOCAL_TIME; 657 private Locale mLocale; 658 private WifiInfo mWifiInfo; 659 private String mDeviceAdminPackageName; 660 private ComponentName mDeviceAdminComponentName; 661 private String mOrganizationName; 662 private String mSupportUrl; 663 private Account mAccountToMigrate; 664 private String mProvisioningAction; 665 private PackageDownloadInfo mDeviceAdminDownloadInfo; 666 private DisclaimersParam mDisclaimersParam; 667 private PersistableBundle mAdminExtrasBundle; 668 private boolean mStartedByTrustedSource = DEFAULT_STARTED_BY_TRUSTED_SOURCE; 669 private boolean mIsNfc = DEFAULT_IS_NFC; 670 private boolean mIsQrProvisioning = DEFAULT_IS_QR_PROVISIONING; 671 private boolean mLeaveAllSystemAppsEnabled = DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED; 672 private boolean mSkipEncryption = DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION; 673 private boolean mSkipEducationScreens = DEFAULT_EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS; 674 private boolean mKeepAccountMigrated = DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED; 675 private boolean mUseMobileData = DEFAULT_EXTRA_PROVISIONING_USE_MOBILE_DATA; 676 private boolean mIsOrganizationOwnedProvisioning = 677 DEFAULT_EXTRA_PROVISIONING_IS_ORGANIZATION_OWNED; 678 private ArrayList<Integer> mAllowedProvisioningModes = 679 DEFAULT_EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES; 680 private int mInitiatorRequestedProvisioningModes = 681 DEFAULT_EXTRA_PROVISIONING_SUPPORTED_MODES; 682 private @FlowType int mFlowType = FLOW_TYPE_UNSPECIFIED; 683 private boolean mAllowProvisioningAfterUserSetupComplete = false; 684 private @ProvisioningTrigger int mProvisioningTrigger = PROVISIONING_TRIGGER_UNSPECIFIED; 685 private boolean mSkipOwnershipDisclaimer = 686 DEFAULT_EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER; 687 private boolean mReturnBeforePolicyCompliance = 688 DEFAULT_EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE; 689 private boolean mDeviceOwnerPermissionGrantOptOut = 690 DEFAULT_EXTRA_PROVISIONING_PERMISSION_GRANT_OPT_OUT; 691 private boolean mKeepScreenOn = DEFAULT_EXTRA_PROVISIONING_KEEP_SCREEN_ON; 692 private boolean mAllowOffline = DEFAULT_EXTRA_ALLOW_OFFLINE; 693 public PackageDownloadInfo mRoleHolderDownloadInfo; 694 private boolean mProvisioningShouldLaunchResultIntent = 695 DEFAULT_EXTRA_PROVISIONING_SHOULD_LAUNCH_RESULT_INTENT; 696 Builder()697 public Builder() { 698 this(/* skipValidation= */ false); 699 } 700 Builder(boolean skipValidation)701 public Builder(boolean skipValidation) { 702 mSkipValidation = skipValidation; 703 } 704 setProvisioningId(long provisioningId)705 public Builder setProvisioningId(long provisioningId) { 706 mProvisioningId = provisioningId; 707 return this; 708 } 709 setTimeZone(String timeZone)710 public Builder setTimeZone(String timeZone) { 711 mTimeZone = timeZone; 712 return this; 713 } 714 setLocalTime(long localTime)715 public Builder setLocalTime(long localTime) { 716 mLocalTime = localTime; 717 return this; 718 } 719 setLocale(Locale locale)720 public Builder setLocale(Locale locale) { 721 mLocale = locale; 722 return this; 723 } 724 setWifiInfo(WifiInfo wifiInfo)725 public Builder setWifiInfo(WifiInfo wifiInfo) { 726 mWifiInfo = wifiInfo; 727 return this; 728 } 729 730 @Deprecated setDeviceAdminPackageName(String deviceAdminPackageName)731 public Builder setDeviceAdminPackageName(String deviceAdminPackageName) { 732 mDeviceAdminPackageName = deviceAdminPackageName; 733 return this; 734 } 735 setDeviceAdminComponentName(ComponentName deviceAdminComponentName)736 public Builder setDeviceAdminComponentName(ComponentName deviceAdminComponentName) { 737 mDeviceAdminComponentName = deviceAdminComponentName; 738 return this; 739 } 740 setOrganizationName(String organizationName)741 public Builder setOrganizationName(String organizationName) { 742 mOrganizationName = organizationName; 743 return this; 744 } 745 setSupportUrl(String supportUrl)746 public Builder setSupportUrl(String supportUrl) { 747 mSupportUrl = supportUrl; 748 return this; 749 } 750 setAccountToMigrate(Account accountToMigrate)751 public Builder setAccountToMigrate(Account accountToMigrate) { 752 mAccountToMigrate = accountToMigrate; 753 return this; 754 } 755 setProvisioningAction(String provisioningAction)756 public Builder setProvisioningAction(String provisioningAction) { 757 mProvisioningAction = provisioningAction; 758 return this; 759 } 760 setDeviceAdminDownloadInfo(PackageDownloadInfo deviceAdminDownloadInfo)761 public Builder setDeviceAdminDownloadInfo(PackageDownloadInfo deviceAdminDownloadInfo) { 762 mDeviceAdminDownloadInfo = deviceAdminDownloadInfo; 763 return this; 764 } 765 setDisclaimersParam(DisclaimersParam disclaimersParam)766 public Builder setDisclaimersParam(DisclaimersParam disclaimersParam) { 767 mDisclaimersParam = disclaimersParam; 768 return this; 769 } 770 setAdminExtrasBundle(PersistableBundle adminExtrasBundle)771 public Builder setAdminExtrasBundle(PersistableBundle adminExtrasBundle) { 772 mAdminExtrasBundle = adminExtrasBundle; 773 return this; 774 } 775 setStartedByTrustedSource(boolean startedByTrustedSource)776 public Builder setStartedByTrustedSource(boolean startedByTrustedSource) { 777 mStartedByTrustedSource = startedByTrustedSource; 778 return this; 779 } 780 setIsNfc(boolean isNfc)781 public Builder setIsNfc(boolean isNfc) { 782 mIsNfc = isNfc; 783 return this; 784 } 785 setIsQrProvisioning(boolean qrProvisioning)786 public Builder setIsQrProvisioning(boolean qrProvisioning) { 787 mIsQrProvisioning = qrProvisioning; 788 return this; 789 } 790 setLeaveAllSystemAppsEnabled(boolean leaveAllSystemAppsEnabled)791 public Builder setLeaveAllSystemAppsEnabled(boolean leaveAllSystemAppsEnabled) { 792 mLeaveAllSystemAppsEnabled = leaveAllSystemAppsEnabled; 793 return this; 794 } 795 setSkipEncryption(boolean skipEncryption)796 public Builder setSkipEncryption(boolean skipEncryption) { 797 mSkipEncryption = skipEncryption; 798 return this; 799 } 800 setSkipEducationScreens(boolean skipEducationScreens)801 public Builder setSkipEducationScreens(boolean skipEducationScreens) { 802 mSkipEducationScreens = skipEducationScreens; 803 return this; 804 } 805 setKeepAccountMigrated(boolean keepAccountMigrated)806 public Builder setKeepAccountMigrated(boolean keepAccountMigrated) { 807 mKeepAccountMigrated = keepAccountMigrated; 808 return this; 809 } 810 setUseMobileData(boolean useMobileData)811 public Builder setUseMobileData(boolean useMobileData) { 812 mUseMobileData = useMobileData; 813 return this; 814 } 815 setIsOrganizationOwnedProvisioning(boolean isOrganizationOwnedProvisioning)816 public Builder setIsOrganizationOwnedProvisioning(boolean isOrganizationOwnedProvisioning) { 817 mIsOrganizationOwnedProvisioning = isOrganizationOwnedProvisioning; 818 return this; 819 } 820 setFlowType(@lowType int flowType)821 public Builder setFlowType(@FlowType int flowType) { 822 mFlowType = flowType; 823 return this; 824 } 825 setAllowProvisioningAfterUserSetupComplete( boolean allowProvisioningAfterUserSetupComplete)826 public Builder setAllowProvisioningAfterUserSetupComplete( 827 boolean allowProvisioningAfterUserSetupComplete) { 828 mAllowProvisioningAfterUserSetupComplete = allowProvisioningAfterUserSetupComplete; 829 return this; 830 } 831 setProvisioningTrigger(@rovisioningTrigger int provisioningTrigger)832 public Builder setProvisioningTrigger(@ProvisioningTrigger int provisioningTrigger) { 833 mProvisioningTrigger = provisioningTrigger; 834 return this; 835 } 836 setAllowedProvisioningModes(ArrayList<Integer> provisioningModes)837 public Builder setAllowedProvisioningModes(ArrayList<Integer> provisioningModes) { 838 mAllowedProvisioningModes = new ArrayList<>(provisioningModes); 839 return this; 840 } 841 setInitiatorRequestedProvisioningModes( int initiatorRequestedProvisioningModes)842 public Builder setInitiatorRequestedProvisioningModes( 843 int initiatorRequestedProvisioningModes) { 844 mInitiatorRequestedProvisioningModes = initiatorRequestedProvisioningModes; 845 return this; 846 } 847 848 /** 849 * See {@link ProvisioningParams#skipOwnershipDisclaimer}. 850 */ setSkipOwnershipDisclaimer(boolean skipOwnershipDisclaimer)851 public Builder setSkipOwnershipDisclaimer(boolean skipOwnershipDisclaimer) { 852 mSkipOwnershipDisclaimer = skipOwnershipDisclaimer; 853 return this; 854 } 855 856 /** 857 * Setter for {@link #returnBeforePolicyCompliance}. 858 */ setReturnBeforePolicyCompliance(boolean returnBeforePolicyCompliance)859 public Builder setReturnBeforePolicyCompliance(boolean returnBeforePolicyCompliance) { 860 mReturnBeforePolicyCompliance = returnBeforePolicyCompliance; 861 return this; 862 } 863 864 /** 865 * Setter for whether the admin has opted out of controlling permission grants. 866 */ setDeviceOwnerPermissionGrantOptOut(boolean optout)867 public Builder setDeviceOwnerPermissionGrantOptOut(boolean optout) { 868 mDeviceOwnerPermissionGrantOptOut = optout; 869 return this; 870 } 871 872 /** 873 * Setter for whether the screen should be on throughout the provisioning flow. 874 */ setKeepScreenOn(boolean keepScreenOn)875 public Builder setKeepScreenOn(boolean keepScreenOn) { 876 mKeepScreenOn = keepScreenOn; 877 return this; 878 } 879 880 /** 881 * Setter for whether offline provisioning is allowed. 882 * 883 * @see DevicePolicyManager#EXTRA_PROVISIONING_ALLOW_OFFLINE 884 */ setAllowOffline(boolean allowOffline)885 public Builder setAllowOffline(boolean allowOffline) { 886 mAllowOffline = allowOffline; 887 return this; 888 } 889 890 /** 891 * Setter for the role holder download info. 892 */ setRoleHolderDownloadInfo(PackageDownloadInfo roleHolderDownloadInfo)893 public Builder setRoleHolderDownloadInfo(PackageDownloadInfo roleHolderDownloadInfo) { 894 mRoleHolderDownloadInfo = roleHolderDownloadInfo; 895 return this; 896 } 897 898 /** 899 * Setter for whether provisioning should launch the result intent returned by the 900 * device manager role holder. 901 * 902 * @see DevicePolicyManager#EXTRA_PROVISIONING_SHOULD_LAUNCH_RESULT_INTENT 903 */ setProvisioningShouldLaunchResultIntent( boolean provisioningShouldLaunchResultIntent)904 public Builder setProvisioningShouldLaunchResultIntent( 905 boolean provisioningShouldLaunchResultIntent) { 906 mProvisioningShouldLaunchResultIntent = provisioningShouldLaunchResultIntent; 907 return this; 908 } 909 910 /** 911 * Builds the {@link ProvisioningParams} object. Note that {@link 912 * #setProvisioningAction(String)} and {@link #setDeviceAdminComponentName(ComponentName)} 913 * methods must be called with a non-null parameter before this is called. 914 */ build()915 public ProvisioningParams build() { 916 return new ProvisioningParams(this); 917 } 918 builder()919 public static Builder builder() { 920 return new Builder(); 921 } 922 923 /** 924 * Creates a {@link Builder} with the option to skip validation. 925 */ builder(boolean skipValidation)926 public static Builder builder(boolean skipValidation) { 927 return new Builder(skipValidation); 928 } 929 } 930 } 931