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