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