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