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_ICON_URI;
23 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL;
24 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
25 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DISCLAIMERS;
26 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION;
27 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED;
28 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE;
29 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME;
30 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR;
31 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ORGANIZATION_NAME;
32 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
33 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_USER_CONSENT;
34 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS;
35 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_USER_SETUP;
36 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SUPPORT_URL;
37 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE;
38 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_USE_MOBILE_DATA;
39 
40 import static com.android.internal.util.Preconditions.checkArgument;
41 import static com.android.internal.util.Preconditions.checkNotNull;
42 import static com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences.DEFAULT_PROVISIONING_ID;
43 import static com.android.managedprovisioning.common.StoreUtils.accountToPersistableBundle;
44 import static com.android.managedprovisioning.common.StoreUtils.getIntegerAttrFromPersistableBundle;
45 import static com.android.managedprovisioning.common.StoreUtils.getObjectAttrFromPersistableBundle;
46 import static com.android.managedprovisioning.common.StoreUtils.getStringAttrFromPersistableBundle;
47 import static com.android.managedprovisioning.common.StoreUtils.putIntegerIfNotNull;
48 import static com.android.managedprovisioning.common.StoreUtils.putPersistableBundlableIfNotNull;
49 
50 import android.accounts.Account;
51 import android.annotation.IntDef;
52 import android.content.ComponentName;
53 import android.content.Context;
54 import android.os.Parcel;
55 import android.os.Parcelable;
56 import android.os.PersistableBundle;
57 import android.util.AtomicFile;
58 import android.util.Xml;
59 
60 import androidx.annotation.Nullable;
61 
62 import com.android.internal.util.FastXmlSerializer;
63 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException;
64 import com.android.managedprovisioning.common.PersistableBundlable;
65 import com.android.managedprovisioning.common.ProvisionLogger;
66 import com.android.managedprovisioning.common.StoreUtils;
67 import com.android.managedprovisioning.common.Utils;
68 
69 import org.xmlpull.v1.XmlPullParser;
70 import org.xmlpull.v1.XmlPullParserException;
71 import org.xmlpull.v1.XmlSerializer;
72 
73 import java.io.File;
74 import java.io.FileInputStream;
75 import java.io.FileOutputStream;
76 import java.io.IOException;
77 import java.lang.annotation.Retention;
78 import java.lang.annotation.RetentionPolicy;
79 import java.nio.charset.StandardCharsets;
80 import java.util.Locale;
81 
82 /**
83  * Provisioning parameters for Device Owner and Profile Owner provisioning.
84  */
85 public final class ProvisioningParams extends PersistableBundlable {
86     public static final long DEFAULT_LOCAL_TIME = -1;
87     public static final Integer DEFAULT_MAIN_COLOR = null;
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_USER_CONSENT = 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_SKIP_USER_SETUP = true;
97     public static final boolean DEFAULT_EXTRA_PROVISIONING_USE_MOBILE_DATA = false;
98     // Intent extra used internally for passing data between activities and service.
99     public static final String EXTRA_PROVISIONING_PARAMS = "provisioningParams";
100 
101     // Possible provisioning modes for organization owned provisioning.
102     public static final int PROVISIONING_MODE_UNDECIDED = 0;
103     public static final int PROVISIONING_MODE_FULLY_MANAGED_DEVICE = 1;
104     public static final int PROVISIONING_MODE_MANAGED_PROFILE = 2;
105     public static final int PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_NAMAGED_DEVICE = 3;
106     public static final int PROVISIONING_MODE_FULLY_MANAGED_DEVICE_LEGACY = 4;
107 
108     // Provisioning mode for financed device provisioning
109     public static final int PROVISIONING_MODE_FINANCED_DEVICE = 5;
110 
111     @IntDef(prefix = { "PROVISIONING_MODE_" }, value = {
112             PROVISIONING_MODE_UNDECIDED,
113             PROVISIONING_MODE_FULLY_MANAGED_DEVICE,
114             PROVISIONING_MODE_MANAGED_PROFILE,
115             PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_NAMAGED_DEVICE,
116             PROVISIONING_MODE_FULLY_MANAGED_DEVICE_LEGACY,
117             PROVISIONING_MODE_FINANCED_DEVICE
118     })
119     @Retention(RetentionPolicy.SOURCE)
120     public @interface ProvisioningMode {}
121 
122     private static final String TAG_PROVISIONING_ID = "provisioning-id";
123     private static final String TAG_PROVISIONING_PARAMS = "provisioning-params";
124     private static final String TAG_WIFI_INFO = "wifi-info";
125     private static final String TAG_PACKAGE_DOWNLOAD_INFO = "download-info";
126     private static final String TAG_STARTED_BY_TRUSTED_SOURCE = "started-by-trusted-source";
127     private static final String TAG_IS_NFC = "started-is-nfc";
128     private static final String TAG_IS_QR_PROVISIONING = "is-qr-provisioning";
129     private static final String TAG_PROVISIONING_ACTION = "provisioning-action";
130     private static final String TAG_IS_ORGANIZATION_OWNED_PROVISIONING =
131             "is-organization-owned-provisioning";
132     private static final String TAG_IS_TRANSITIONING_FROM_REGULAR_TO_CHILD =
133             "is-transitioning-from-regular-to-child";
134     private static final String TAG_PROVISIONING_MODE = "provisioning-mode";
135 
136     public static final Parcelable.Creator<ProvisioningParams> CREATOR
137             = new Parcelable.Creator<ProvisioningParams>() {
138         @Override
139         public ProvisioningParams createFromParcel(Parcel in) {
140             return new ProvisioningParams(in);
141         }
142 
143         @Override
144         public ProvisioningParams[] newArray(int size) {
145             return new ProvisioningParams[size];
146         }
147     };
148 
149     public final long provisioningId;
150 
151     @Nullable
152     public final String timeZone;
153 
154     public final long localTime;
155 
156     @Nullable
157     public final Locale locale;
158 
159     /** WiFi configuration. */
160     @Nullable
161     public final WifiInfo wifiInfo;
162 
163     public final boolean useMobileData;
164 
165     /**
166      * Package name of the device admin package.
167      *
168      * <p>At least one one of deviceAdminPackageName and deviceAdminComponentName should be
169      * non-null.
170      * <p>
171      * In most cases, it is preferable to access the admin package name using
172      * {@link #inferDeviceAdminPackageName}.
173      */
174     @Deprecated
175     @Nullable
176     public final String deviceAdminPackageName;
177 
178     /**
179      * {@link ComponentName} of the device admin package.
180      *
181      * <p>At least one one of deviceAdminPackageName and deviceAdminComponentName should be
182      * non-null.
183      * <p>
184      * In most cases, it is preferable to access the admin component name using
185      * {@link #inferDeviceAdminComponentName(Utils, Context, int)} .
186      */
187     @Nullable
188     public final ComponentName deviceAdminComponentName;
189 
190     public final String deviceAdminLabel;
191     public final String organizationName;
192     public final String supportUrl;
193     public final String deviceAdminIconFilePath;
194 
195     /** {@link Account} that should be migrated to the managed profile. */
196     @Nullable
197     public final Account accountToMigrate;
198 
199     /** True if the account will not be removed from the calling user after it is migrated. */
200     public final boolean keepAccountMigrated;
201 
202     /** Provisioning action comes along with the provisioning data. */
203     public final String provisioningAction;
204 
205     /**
206      * The main color theme used in managed profile only.
207      *
208      * <p>{@code null} means the default value.
209      */
210     @Nullable
211     public final Integer mainColor;
212 
213     /** The download information of device admin package. */
214     @Nullable
215     public final PackageDownloadInfo deviceAdminDownloadInfo;
216 
217     /** List of disclaimers */
218     @Nullable
219     public final DisclaimersParam disclaimersParam;
220 
221     /**
222      * Custom key-value pairs from enterprise mobility management which are passed to device admin
223      * package after provisioning.
224      *
225      * <p>Note that {@link ProvisioningParams} is not immutable because this field is mutable.
226      */
227     @Nullable
228     public final PersistableBundle adminExtrasBundle;
229 
230     /**
231      * True iff provisioning flow was started by a trusted app. This includes Nfc bump and QR code.
232      */
233     public final boolean startedByTrustedSource;
234 
235     public final boolean isNfc;
236 
237     public final boolean isQrProvisioning;
238 
239     /** True if all system apps should be enabled after provisioning. */
240     public final boolean leaveAllSystemAppsEnabled;
241 
242     /** True if device encryption should be skipped. */
243     public final boolean skipEncryption;
244 
245     /** True if user setup can be skipped. */
246     public final boolean skipUserSetup;
247 
248     public final boolean skipEducationScreens;
249 
250     /** True if user consent page in pre-provisioning can be skipped. */
251     public final boolean skipUserConsent;
252 
253     /** True if the provisioning is done on a device owned by the organization. */
254     public final boolean isOrganizationOwnedProvisioning;
255 
256     /** True if the device is transitioning from regular to child user. */
257     public final boolean isTransitioningFromRegularToChild;
258 
259     /**
260      * The provisioning mode for organization owned provisioning. This is only used for
261      * admin integrated flow.
262      */
263     public final @ProvisioningMode int provisioningMode;
264 
inferStaticDeviceAdminPackageName(ComponentName deviceAdminComponentName, String deviceAdminPackageName)265     public static String inferStaticDeviceAdminPackageName(ComponentName deviceAdminComponentName,
266             String deviceAdminPackageName) {
267         if (deviceAdminComponentName != null) {
268             return deviceAdminComponentName.getPackageName();
269         }
270         return deviceAdminPackageName;
271     }
272 
inferDeviceAdminPackageName()273     public String inferDeviceAdminPackageName() {
274         return inferStaticDeviceAdminPackageName(deviceAdminComponentName, deviceAdminPackageName);
275     }
276 
277     /**
278      * Due to legacy reason, DPC is allowed to provide either package name or the component name.
279      * If component name is not {@code null}, we will return it right away. Otherwise, we will
280      * infer the component name.
281      * <p>
282      * In most cases, it is preferable to access the admin component name using this method.
283      * But if the purpose is to verify the device admin component name, you should use
284      * {@link Utils#findDeviceAdmin(String, ComponentName, Context, int)} instead.
285      */
inferDeviceAdminComponentName(Utils utils, Context context, int userId)286     public ComponentName inferDeviceAdminComponentName(Utils utils, Context context, int userId)
287             throws IllegalProvisioningArgumentException {
288         if (deviceAdminComponentName != null) {
289             return deviceAdminComponentName;
290         }
291         return utils.findDeviceAdmin(
292                 deviceAdminPackageName, deviceAdminComponentName, context, userId);
293     }
294 
ProvisioningParams(Builder builder)295     private ProvisioningParams(Builder builder) {
296         provisioningId = builder.mProvisioningId;
297         timeZone = builder.mTimeZone;
298         localTime = builder.mLocalTime;
299         locale = builder.mLocale;
300 
301         wifiInfo = builder.mWifiInfo;
302         useMobileData = builder.mUseMobileData;
303 
304         deviceAdminComponentName = builder.mDeviceAdminComponentName;
305         deviceAdminPackageName = builder.mDeviceAdminPackageName;
306         deviceAdminLabel = builder.mDeviceAdminLabel;
307         organizationName = builder.mOrganizationName;
308         supportUrl = builder.mSupportUrl;
309         deviceAdminIconFilePath = builder.mDeviceAdminIconFilePath;
310 
311         deviceAdminDownloadInfo = builder.mDeviceAdminDownloadInfo;
312         disclaimersParam = builder.mDisclaimersParam;
313 
314         adminExtrasBundle = builder.mAdminExtrasBundle;
315 
316         startedByTrustedSource = builder.mStartedByTrustedSource;
317         isNfc = builder.mIsNfc;
318         isQrProvisioning = builder.mIsQrProvisioning;
319         leaveAllSystemAppsEnabled = builder.mLeaveAllSystemAppsEnabled;
320         skipEncryption = builder.mSkipEncryption;
321         accountToMigrate = builder.mAccountToMigrate;
322         provisioningAction = checkNotNull(builder.mProvisioningAction);
323         mainColor = builder.mMainColor;
324         skipUserConsent = builder.mSkipUserConsent;
325         skipUserSetup = builder.mSkipUserSetup;
326         skipEducationScreens = builder.mSkipEducationScreens;
327         keepAccountMigrated = builder.mKeepAccountMigrated;
328 
329         isOrganizationOwnedProvisioning = builder.mIsOrganizationOwnedProvisioning;
330         isTransitioningFromRegularToChild = builder.mIsTransitioningFromRegularToChild;
331         provisioningMode = builder.mProvisioningMode;
332 
333         validateFields();
334     }
335 
ProvisioningParams(Parcel in)336     private ProvisioningParams(Parcel in) {
337         this(createBuilderFromPersistableBundle(
338                 PersistableBundlable.getPersistableBundleFromParcel(in)));
339     }
340 
validateFields()341     private void validateFields() {
342         checkArgument(deviceAdminPackageName != null || deviceAdminComponentName != null);
343     }
344 
345     @Override
toPersistableBundle()346     public PersistableBundle toPersistableBundle() {
347         final PersistableBundle bundle = new PersistableBundle();
348 
349         bundle.putLong(TAG_PROVISIONING_ID, provisioningId);
350         bundle.putString(EXTRA_PROVISIONING_TIME_ZONE, timeZone);
351         bundle.putLong(EXTRA_PROVISIONING_LOCAL_TIME, localTime);
352         bundle.putString(EXTRA_PROVISIONING_LOCALE, StoreUtils.localeToString(locale));
353         putPersistableBundlableIfNotNull(bundle, TAG_WIFI_INFO, wifiInfo);
354         bundle.putBoolean(EXTRA_PROVISIONING_USE_MOBILE_DATA, useMobileData);
355         bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, deviceAdminPackageName);
356         bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
357                 StoreUtils.componentNameToString(deviceAdminComponentName));
358         bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL, deviceAdminLabel);
359         bundle.putString(EXTRA_PROVISIONING_ORGANIZATION_NAME, organizationName);
360         bundle.putString(EXTRA_PROVISIONING_SUPPORT_URL, supportUrl);
361         bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI, deviceAdminIconFilePath);
362         bundle.putPersistableBundle(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, accountToMigrate == null
363                 ? null : accountToPersistableBundle(accountToMigrate));
364         bundle.putString(TAG_PROVISIONING_ACTION, provisioningAction);
365         putIntegerIfNotNull(bundle, EXTRA_PROVISIONING_MAIN_COLOR, mainColor);
366         putPersistableBundlableIfNotNull(bundle, TAG_PACKAGE_DOWNLOAD_INFO,
367                 deviceAdminDownloadInfo);
368         putPersistableBundlableIfNotNull(bundle, EXTRA_PROVISIONING_DISCLAIMERS,
369                 disclaimersParam);
370         bundle.putPersistableBundle(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, adminExtrasBundle);
371         bundle.putBoolean(TAG_STARTED_BY_TRUSTED_SOURCE, startedByTrustedSource);
372         bundle.putBoolean(TAG_IS_NFC, isNfc);
373         bundle.putBoolean(TAG_IS_QR_PROVISIONING, isQrProvisioning);
374         bundle.putBoolean(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED,
375                 leaveAllSystemAppsEnabled);
376         bundle.putBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION, skipEncryption);
377         bundle.putBoolean(EXTRA_PROVISIONING_SKIP_USER_SETUP, skipUserSetup);
378         bundle.putBoolean(EXTRA_PROVISIONING_SKIP_USER_CONSENT, skipUserConsent);
379         bundle.putBoolean(EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS, skipEducationScreens);
380         bundle.putBoolean(EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION, keepAccountMigrated);
381         bundle.putBoolean(TAG_IS_ORGANIZATION_OWNED_PROVISIONING, isOrganizationOwnedProvisioning);
382         bundle.putBoolean(TAG_IS_TRANSITIONING_FROM_REGULAR_TO_CHILD,
383                  isTransitioningFromRegularToChild);
384         bundle.putInt(TAG_PROVISIONING_MODE, provisioningMode);
385         return bundle;
386     }
387 
fromPersistableBundle(PersistableBundle bundle)388     /* package */ static ProvisioningParams fromPersistableBundle(PersistableBundle bundle) {
389         return createBuilderFromPersistableBundle(bundle).build();
390     }
391 
createBuilderFromPersistableBundle(PersistableBundle bundle)392     private static Builder createBuilderFromPersistableBundle(PersistableBundle bundle) {
393         Builder builder = new Builder();
394         builder.setProvisioningId(bundle.getLong(TAG_PROVISIONING_ID, DEFAULT_PROVISIONING_ID));
395         builder.setTimeZone(bundle.getString(EXTRA_PROVISIONING_TIME_ZONE));
396         builder.setLocalTime(bundle.getLong(EXTRA_PROVISIONING_LOCAL_TIME));
397         builder.setLocale(getStringAttrFromPersistableBundle(bundle,
398                 EXTRA_PROVISIONING_LOCALE, StoreUtils::stringToLocale));
399         builder.setUseMobileData(bundle.getBoolean(EXTRA_PROVISIONING_USE_MOBILE_DATA));
400         builder.setWifiInfo(getObjectAttrFromPersistableBundle(bundle,
401                 TAG_WIFI_INFO, WifiInfo::fromPersistableBundle));
402         builder.setDeviceAdminPackageName(bundle.getString(
403                 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME));
404         builder.setDeviceAdminComponentName(getStringAttrFromPersistableBundle(bundle,
405                 EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, StoreUtils::stringToComponentName));
406         builder.setDeviceAdminLabel(bundle.getString(
407                 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL));
408         builder.setOrganizationName(bundle.getString(EXTRA_PROVISIONING_ORGANIZATION_NAME));
409         builder.setSupportUrl(bundle.getString(EXTRA_PROVISIONING_SUPPORT_URL));
410         builder.setDeviceAdminIconFilePath(bundle.getString(
411                 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI));
412         builder.setAccountToMigrate(getObjectAttrFromPersistableBundle(bundle,
413                 EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, StoreUtils::persistableBundleToAccount));
414         builder.setProvisioningAction(bundle.getString(TAG_PROVISIONING_ACTION));
415         builder.setMainColor(getIntegerAttrFromPersistableBundle(bundle,
416                 EXTRA_PROVISIONING_MAIN_COLOR));
417         builder.setDeviceAdminDownloadInfo(getObjectAttrFromPersistableBundle(bundle,
418                 TAG_PACKAGE_DOWNLOAD_INFO, PackageDownloadInfo::fromPersistableBundle));
419         builder.setDisclaimersParam(getObjectAttrFromPersistableBundle(bundle,
420                 EXTRA_PROVISIONING_DISCLAIMERS, DisclaimersParam::fromPersistableBundle));
421         builder.setAdminExtrasBundle(bundle.getPersistableBundle(
422                 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE));
423         builder.setStartedByTrustedSource(bundle.getBoolean(TAG_STARTED_BY_TRUSTED_SOURCE));
424         builder.setIsNfc(bundle.getBoolean(TAG_IS_NFC));
425         builder.setIsQrProvisioning(bundle.getBoolean(TAG_IS_QR_PROVISIONING));
426         builder.setSkipEncryption(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION));
427         builder.setLeaveAllSystemAppsEnabled(bundle.getBoolean(
428                 EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED));
429         builder.setSkipUserSetup(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_USER_SETUP));
430         builder.setSkipUserConsent(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_USER_CONSENT));
431         builder.setSkipEducationScreens(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS));
432         builder.setKeepAccountMigrated(bundle.getBoolean(
433                 EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION));
434         builder.setIsOrganizationOwnedProvisioning(bundle.getBoolean(
435                 TAG_IS_ORGANIZATION_OWNED_PROVISIONING));
436         builder.setIsTransitioningFromRegularToChild(bundle.getBoolean(
437                 TAG_IS_TRANSITIONING_FROM_REGULAR_TO_CHILD));
438         builder.setProvisioningMode(bundle.getInt(TAG_PROVISIONING_MODE));
439         return builder;
440     }
441 
toBuilder()442     public Builder toBuilder() {
443         return createBuilderFromPersistableBundle(toPersistableBundle());
444     }
445 
446     @Override
toString()447     public String toString() {
448         return "ProvisioningParams values: " + toPersistableBundle().toString();
449     }
450 
451     /**
452      * Saves the ProvisioningParams to the specified file.
453      */
save(File file)454     public void save(File file) {
455         ProvisionLogger.logd("Saving ProvisioningParams to " + file);
456         AtomicFile atomicFile = null;
457         FileOutputStream stream = null;
458         try {
459             atomicFile = new AtomicFile(file);
460             stream = atomicFile.startWrite();
461             XmlSerializer serializer = new FastXmlSerializer();
462             serializer.setOutput(stream, StandardCharsets.UTF_8.name());
463             serializer.startDocument(null, true);
464             serializer.startTag(null, TAG_PROVISIONING_PARAMS);
465             toPersistableBundle().saveToXml(serializer);
466             serializer.endTag(null, TAG_PROVISIONING_PARAMS);
467             serializer.endDocument();
468             atomicFile.finishWrite(stream);
469         } catch (IOException | XmlPullParserException e) {
470             ProvisionLogger.loge("Caught exception while trying to save Provisioning Params to "
471                     + " file " + file, e);
472             file.delete();
473             if (atomicFile != null) {
474                 atomicFile.failWrite(stream);
475             }
476         }
477     }
478 
cleanUp()479     public void cleanUp() {
480         if (disclaimersParam != null) {
481             disclaimersParam.cleanUp();
482         }
483         if (deviceAdminIconFilePath != null) {
484             new File(deviceAdminIconFilePath).delete();
485         }
486     }
487 
488     /**
489      * Loads the ProvisioningParams From the specified file.
490      */
load(File file)491     public static ProvisioningParams load(File file) {
492         if (!file.exists()) {
493             return null;
494         }
495         ProvisionLogger.logd("Loading ProvisioningParams from " + file);
496         try (FileInputStream stream = new FileInputStream(file)) {
497             XmlPullParser parser = Xml.newPullParser();
498             parser.setInput(stream, null);
499             return load(parser);
500         } catch (IOException | XmlPullParserException e) {
501             ProvisionLogger.loge("Caught exception while trying to load the provisioning params"
502                     + " from file " + file, e);
503             return null;
504         }
505     }
506 
load(XmlPullParser parser)507     private static ProvisioningParams load(XmlPullParser parser) throws XmlPullParserException,
508             IOException {
509         int type;
510         int outerDepth = parser.getDepth();
511         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
512                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
513              if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
514                  continue;
515              }
516              String tag = parser.getName();
517              switch (tag) {
518                  case TAG_PROVISIONING_PARAMS:
519                      return createBuilderFromPersistableBundle(
520                              PersistableBundle.restoreFromXml(parser)).build();
521              }
522         }
523         return new Builder().build();
524     }
525 
526     public final static class Builder {
527         private long mProvisioningId;
528         private String mTimeZone;
529         private long mLocalTime = DEFAULT_LOCAL_TIME;
530         private Locale mLocale;
531         private WifiInfo mWifiInfo;
532         private String mDeviceAdminPackageName;
533         private ComponentName mDeviceAdminComponentName;
534         private String mDeviceAdminLabel;
535         private String mOrganizationName;
536         private String mSupportUrl;
537         private String mDeviceAdminIconFilePath;
538         private Account mAccountToMigrate;
539         private String mProvisioningAction;
540         private Integer mMainColor = DEFAULT_MAIN_COLOR;
541         private PackageDownloadInfo mDeviceAdminDownloadInfo;
542         private DisclaimersParam mDisclaimersParam;
543         private PersistableBundle mAdminExtrasBundle;
544         private boolean mStartedByTrustedSource = DEFAULT_STARTED_BY_TRUSTED_SOURCE;
545         private boolean mIsNfc = DEFAULT_IS_NFC;
546         private boolean mIsQrProvisioning = DEFAULT_IS_QR_PROVISIONING;
547         private boolean mLeaveAllSystemAppsEnabled = DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED;
548         private boolean mSkipEncryption = DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION;
549         private boolean mSkipUserConsent = DEFAULT_EXTRA_PROVISIONING_SKIP_USER_CONSENT;
550         private boolean mSkipEducationScreens = DEFAULT_EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS;
551         private boolean mSkipUserSetup = DEFAULT_SKIP_USER_SETUP;
552         private boolean mKeepAccountMigrated = DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED;
553         private boolean mUseMobileData = DEFAULT_EXTRA_PROVISIONING_USE_MOBILE_DATA;
554         private boolean mIsOrganizationOwnedProvisioning = false;
555         private boolean mIsTransitioningFromRegularToChild = false;
556         private @ProvisioningMode int mProvisioningMode = PROVISIONING_MODE_UNDECIDED;
557 
setProvisioningId(long provisioningId)558         public Builder setProvisioningId(long provisioningId) {
559             mProvisioningId = provisioningId;
560             return this;
561         }
562 
setTimeZone(String timeZone)563         public Builder setTimeZone(String timeZone) {
564             mTimeZone = timeZone;
565             return this;
566         }
567 
setLocalTime(long localTime)568         public Builder setLocalTime(long localTime) {
569             mLocalTime = localTime;
570             return this;
571         }
572 
setLocale(Locale locale)573         public Builder setLocale(Locale locale) {
574             mLocale = locale;
575             return this;
576         }
577 
setWifiInfo(WifiInfo wifiInfo)578         public Builder setWifiInfo(WifiInfo wifiInfo) {
579             mWifiInfo = wifiInfo;
580             return this;
581         }
582 
583         @Deprecated
setDeviceAdminPackageName(String deviceAdminPackageName)584         public Builder setDeviceAdminPackageName(String deviceAdminPackageName) {
585             mDeviceAdminPackageName = deviceAdminPackageName;
586             return this;
587         }
588 
setDeviceAdminComponentName(ComponentName deviceAdminComponentName)589         public Builder setDeviceAdminComponentName(ComponentName deviceAdminComponentName) {
590             mDeviceAdminComponentName = deviceAdminComponentName;
591             return this;
592         }
593 
setDeviceAdminLabel(String deviceAdminLabel)594         public Builder setDeviceAdminLabel(String deviceAdminLabel) {
595             mDeviceAdminLabel = deviceAdminLabel;
596             return this;
597         }
598 
setOrganizationName(String organizationName)599         public Builder setOrganizationName(String organizationName) {
600             mOrganizationName = organizationName;
601             return this;
602         }
603 
setSupportUrl(String supportUrl)604         public Builder setSupportUrl(String supportUrl) {
605             mSupportUrl = supportUrl;
606             return this;
607         }
608 
setDeviceAdminIconFilePath(String deviceAdminIconFilePath)609         public Builder setDeviceAdminIconFilePath(String deviceAdminIconFilePath) {
610             mDeviceAdminIconFilePath = deviceAdminIconFilePath;
611             return this;
612         }
613 
setAccountToMigrate(Account accountToMigrate)614         public Builder setAccountToMigrate(Account accountToMigrate) {
615             mAccountToMigrate = accountToMigrate;
616             return this;
617         }
618 
setProvisioningAction(String provisioningAction)619         public Builder setProvisioningAction(String provisioningAction) {
620             mProvisioningAction = provisioningAction;
621             return this;
622         }
623 
setMainColor(Integer mainColor)624         public Builder setMainColor(Integer mainColor) {
625             mMainColor = mainColor;
626             return this;
627         }
628 
setDeviceAdminDownloadInfo(PackageDownloadInfo deviceAdminDownloadInfo)629         public Builder setDeviceAdminDownloadInfo(PackageDownloadInfo deviceAdminDownloadInfo) {
630             mDeviceAdminDownloadInfo = deviceAdminDownloadInfo;
631             return this;
632         }
633 
setDisclaimersParam(DisclaimersParam disclaimersParam)634         public Builder setDisclaimersParam(DisclaimersParam disclaimersParam) {
635             mDisclaimersParam = disclaimersParam;
636             return this;
637         }
638 
setAdminExtrasBundle(PersistableBundle adminExtrasBundle)639         public Builder setAdminExtrasBundle(PersistableBundle adminExtrasBundle) {
640             mAdminExtrasBundle = adminExtrasBundle;
641             return this;
642         }
643 
setStartedByTrustedSource(boolean startedByTrustedSource)644         public Builder setStartedByTrustedSource(boolean startedByTrustedSource) {
645             mStartedByTrustedSource = startedByTrustedSource;
646             return this;
647         }
648 
setIsNfc(boolean isNfc)649         public Builder setIsNfc(boolean isNfc) {
650             mIsNfc = isNfc;
651             return this;
652         }
653 
setIsQrProvisioning(boolean qrProvisioning)654         public Builder setIsQrProvisioning(boolean qrProvisioning) {
655             mIsQrProvisioning = qrProvisioning;
656             return this;
657         }
658 
setLeaveAllSystemAppsEnabled(boolean leaveAllSystemAppsEnabled)659         public Builder setLeaveAllSystemAppsEnabled(boolean leaveAllSystemAppsEnabled) {
660             mLeaveAllSystemAppsEnabled = leaveAllSystemAppsEnabled;
661             return this;
662         }
663 
setSkipEncryption(boolean skipEncryption)664         public Builder setSkipEncryption(boolean skipEncryption) {
665             mSkipEncryption = skipEncryption;
666             return this;
667         }
668 
setSkipUserConsent(boolean skipUserConsent)669         public Builder setSkipUserConsent(boolean skipUserConsent) {
670             mSkipUserConsent = skipUserConsent;
671             return this;
672         }
673 
setSkipEducationScreens(boolean skipEducationScreens)674         public Builder setSkipEducationScreens(boolean skipEducationScreens) {
675             mSkipEducationScreens = skipEducationScreens;
676             return this;
677         }
678 
setSkipUserSetup(boolean skipUserSetup)679         public Builder setSkipUserSetup(boolean skipUserSetup) {
680             mSkipUserSetup = skipUserSetup;
681             return this;
682         }
683 
setKeepAccountMigrated(boolean keepAccountMigrated)684         public Builder setKeepAccountMigrated(boolean keepAccountMigrated) {
685             mKeepAccountMigrated = keepAccountMigrated;
686             return this;
687         }
688 
setUseMobileData(boolean useMobileData)689         public Builder setUseMobileData(boolean useMobileData) {
690             mUseMobileData = useMobileData;
691             return this;
692         }
693 
setIsOrganizationOwnedProvisioning(boolean isOrganizationOwnedProvisioning)694         public Builder setIsOrganizationOwnedProvisioning(boolean isOrganizationOwnedProvisioning) {
695             mIsOrganizationOwnedProvisioning = isOrganizationOwnedProvisioning;
696             return this;
697         }
698 
setIsTransitioningFromRegularToChild( boolean isTransitioningFromRegularToChild)699         public Builder setIsTransitioningFromRegularToChild(
700                 boolean isTransitioningFromRegularToChild) {
701             mIsTransitioningFromRegularToChild = isTransitioningFromRegularToChild;
702             return this;
703         }
704 
setProvisioningMode(@rovisioningMode int provisioningMode)705         public Builder setProvisioningMode(@ProvisioningMode int provisioningMode) {
706             mProvisioningMode = provisioningMode;
707             return this;
708         }
709 
710         /**
711          * Builds the {@link ProvisioningParams} object. Note that {@link
712          * #setProvisioningAction(String)} and {@link #setDeviceAdminComponentName(ComponentName)}
713          * methods must be called with a non-null parameter before this is called.
714          */
build()715         public ProvisioningParams build() {
716             return new ProvisioningParams(this);
717         }
718 
builder()719         public static Builder builder() {
720             return new Builder();
721         }
722     }
723 }
724