blob: a5517982a2f2aea7b68ad0bcac8b0a78343acc86 [file] [log] [blame]
/*
* Copyright 2016, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.managedprovisioning.model;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DISCLAIMERS;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ORGANIZATION_NAME;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SUPPORT_URL;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_USE_MOBILE_DATA;
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_CLOUD_ENROLLMENT;
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_MANAGED_ACCOUNT;
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_QR_CODE;
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_UNSPECIFIED;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences.DEFAULT_PROVISIONING_ID;
import static com.android.managedprovisioning.common.StoreUtils.accountToPersistableBundle;
import static com.android.managedprovisioning.common.StoreUtils.getObjectAttrFromPersistableBundle;
import static com.android.managedprovisioning.common.StoreUtils.getStringAttrFromPersistableBundle;
import static com.android.managedprovisioning.common.StoreUtils.putPersistableBundlableIfNotNull;
import android.accounts.Account;
import android.annotation.IntDef;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.util.AtomicFile;
import android.util.Xml;
import androidx.annotation.Nullable;
import com.android.internal.util.FastXmlSerializer;
import com.android.managedprovisioning.common.IllegalProvisioningArgumentException;
import com.android.managedprovisioning.common.PersistableBundlable;
import com.android.managedprovisioning.common.ProvisionLogger;
import com.android.managedprovisioning.common.StoreUtils;
import com.android.managedprovisioning.common.Utils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import java.util.stream.Collectors;
/**
* Provisioning parameters for Device Owner and Profile Owner provisioning.
*/
public final class ProvisioningParams extends PersistableBundlable {
public static final long DEFAULT_LOCAL_TIME = -1;
public static final boolean DEFAULT_STARTED_BY_TRUSTED_SOURCE = false;
public static final boolean DEFAULT_IS_NFC = false;
public static final boolean DEFAULT_IS_QR_PROVISIONING = false;
public static final boolean DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED = false;
public static final boolean DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION = false;
public static final boolean DEFAULT_EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS = false;
public static final boolean DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED = false;
public static final boolean DEFAULT_EXTRA_PROVISIONING_USE_MOBILE_DATA = false;
public static final boolean DEFAULT_EXTRA_PROVISIONING_IS_ORGANIZATION_OWNED = false;
public static final ArrayList<Integer> DEFAULT_EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES =
new ArrayList<>();
public static final int DEFAULT_EXTRA_PROVISIONING_SUPPORTED_MODES = 0;
public static final boolean DEFAULT_EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER = false;
public static final boolean DEFAULT_EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE = false;
public static final boolean DEFAULT_EXTRA_PROVISIONING_PERMISSION_GRANT_OPT_OUT = false;
public static final boolean DEFAULT_EXTRA_PROVISIONING_KEEP_SCREEN_ON = false;
// Intent extra used internally for passing data between activities and service.
public static final String EXTRA_PROVISIONING_PARAMS = "provisioningParams";
public static final int FLOW_TYPE_UNSPECIFIED = 0;
public static final int FLOW_TYPE_LEGACY = 1;
public static final int FLOW_TYPE_ADMIN_INTEGRATED = 2;
@IntDef(prefix = { "PROVISIONING_TRIGGER_" }, value = {
PROVISIONING_TRIGGER_UNSPECIFIED,
PROVISIONING_TRIGGER_CLOUD_ENROLLMENT,
PROVISIONING_TRIGGER_QR_CODE,
PROVISIONING_TRIGGER_MANAGED_ACCOUNT
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProvisioningTrigger {}
@IntDef(prefix = { "FLOW_TYPE_" }, value = {
FLOW_TYPE_UNSPECIFIED,
FLOW_TYPE_LEGACY,
FLOW_TYPE_ADMIN_INTEGRATED
})
@Retention(RetentionPolicy.SOURCE)
public @interface FlowType {}
private static final String TAG_PROVISIONING_ID = "provisioning-id";
private static final String TAG_PROVISIONING_PARAMS = "provisioning-params";
private static final String TAG_WIFI_INFO = "wifi-info";
private static final String TAG_PACKAGE_DOWNLOAD_INFO = "download-info";
private static final String TAG_STARTED_BY_TRUSTED_SOURCE = "started-by-trusted-source";
private static final String TAG_IS_NFC = "started-is-nfc";
private static final String TAG_IS_QR_PROVISIONING = "is-qr-provisioning";
private static final String TAG_PROVISIONING_ACTION = "provisioning-action";
private static final String TAG_IS_ORGANIZATION_OWNED_PROVISIONING =
"is-organization-owned-provisioning";
private static final String TAG_ALLOWED_PROVISIONING_MODES =
"allowed-provisioning-modes";
private static final String TAG_INITIATOR_REQUESTED_PROVISIONING_MODES =
"initiator-requested-provisioning-modes";
private static final String TAG_FLOW_TYPE = "flow-type";
private static final String TAG_ALLOW_PROVISIONING_AFTER_USER_SETUP_COMPLETE =
"allow-provisioning-after-user-setup-complete";
private static final String TAG_PROVISIONING_TRIGGER = "provisioning-trigger";
private static final String TAG_SKIP_OWNERSHIP_DISCLAIMER = "skip-ownership-disclaimer";
private static final String TAG_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE =
"provisioning-return-before-policy-compliance";
private static final String TAG_DEVICE_OWNER_PERMISSION_GRANT_OPT_OUT =
"device-owner-opt-out-of-permission-grants";
private static final String TAG_KEEP_SCREEN_ON = "keep-screen-on";
public static final Parcelable.Creator<ProvisioningParams> CREATOR
= new Parcelable.Creator<ProvisioningParams>() {
@Override
public ProvisioningParams createFromParcel(Parcel in) {
return new ProvisioningParams(in);
}
@Override
public ProvisioningParams[] newArray(int size) {
return new ProvisioningParams[size];
}
};
public final long provisioningId;
@Nullable
public final String timeZone;
public final long localTime;
@Nullable
public final Locale locale;
/** WiFi configuration. */
@Nullable
public final WifiInfo wifiInfo;
public final boolean useMobileData;
/**
* Package name of the device admin package.
*
* <p>At least one one of deviceAdminPackageName and deviceAdminComponentName should be
* non-null.
* <p>
* In most cases, it is preferable to access the admin package name using
* {@link #inferDeviceAdminPackageName}.
*/
@Deprecated
@Nullable
public final String deviceAdminPackageName;
/**
* {@link ComponentName} of the device admin package.
*
* <p>At least one one of deviceAdminPackageName and deviceAdminComponentName should be
* non-null.
* <p>
* In most cases, it is preferable to access the admin component name using
* {@link #inferDeviceAdminComponentName(Utils, Context, int)} .
*/
@Nullable
public final ComponentName deviceAdminComponentName;
public final String organizationName;
public final String supportUrl;
/** {@link Account} that should be migrated to the managed profile. */
@Nullable
public final Account accountToMigrate;
/** True if the account will not be removed from the calling user after it is migrated. */
public final boolean keepAccountMigrated;
/** Provisioning action comes along with the provisioning data. */
public final String provisioningAction;
/** The download information of device admin package. */
@Nullable
public final PackageDownloadInfo deviceAdminDownloadInfo;
/** List of disclaimers */
@Nullable
public final DisclaimersParam disclaimersParam;
/**
* Custom key-value pairs from enterprise mobility management which are passed to device admin
* package after provisioning.
*
* <p>Note that {@link ProvisioningParams} is not immutable because this field is mutable.
*/
@Nullable
public final PersistableBundle adminExtrasBundle;
/**
* True iff provisioning flow was started by a trusted app. This includes Nfc bump and QR code.
*/
public final boolean startedByTrustedSource;
public final boolean isNfc;
public final boolean isQrProvisioning;
/** True if all system apps should be enabled after provisioning. */
public final boolean leaveAllSystemAppsEnabled;
/** True if device encryption should be skipped. */
public final boolean skipEncryption;
public final boolean skipEducationScreens;
/**
* True if the provisioning is done on a device owned by the organization.
*
* <p>For the admin-integrated flow, this field is only set after the admin app
* picks a provisioning mode.
*/
public final boolean isOrganizationOwnedProvisioning;
/**
* {@link ArrayList} of {@link Integer} containing a subset of {{@link
* DevicePolicyManager#PROVISIONING_MODE_MANAGED_PROFILE}, {@link
* DevicePolicyManager#PROVISIONING_MODE_FULLY_MANAGED_DEVICE}, {@link
* DevicePolicyManager#PROVISIONING_MODE_MANAGED_PROFILE_ON_PERSONAL_DEVICE}}.
**/
public final ArrayList<Integer> allowedProvisioningModes;
/**
* Integer specifying what provisioning modes have been specified by the provisioning
* initiator.
*
* <p>Can be a combination of {@link
* DevicePolicyManager#FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED}, {@link
* DevicePolicyManager#FLAG_SUPPORTED_MODES_PERSONALLY_OWNED}, {@link
* DevicePolicyManager#FLAG_SUPPORTED_MODES_DEVICE_OWNER} or if not relevant to the
* admin-integrated flow, {@link ProvisioningParams#DEFAULT_EXTRA_PROVISIONING_SUPPORTED_MODES}.
*
*/
public final int initiatorRequestedProvisioningModes;
/** True if provisioning after user setup complete should be allowed. */
public final boolean allowProvisioningAfterUserSetupComplete;
/**
* The type of flow to be performed.
* <p>Must be one of {@link #FLOW_TYPE_UNSPECIFIED}, {@link #FLOW_TYPE_LEGACY} or {@link
* #FLOW_TYPE_ADMIN_INTEGRATED}.
**/
public final @FlowType int flowType;
/**
* The way provisioning was started.
* <p>Can be one of {@link DevicePolicyManager#PROVISIONING_TRIGGER_CLOUD_ENROLLMENT}, {@link
* DevicePolicyManager#PROVISIONING_TRIGGER_QR_CODE}, {@link
* DevicePolicyManager#PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER} or {@link
* DevicePolicyManager#PROVISIONING_TRIGGER_UNSPECIFIED}.
*/
public final @ProvisioningTrigger int provisioningTrigger;
/**
* Whether to skip the ownership disclaimer.
*/
public final boolean skipOwnershipDisclaimer;
/**
* True if the provisioning flow should return before starting the admin app's {@link
* DevicePolicyManager#ACTION_ADMIN_POLICY_COMPLIANCE} handler. Default value is {@code true}.
*/
public final boolean returnBeforePolicyCompliance;
/**
* True if the device owner has opted out of controlling permission grants for
* sensors-related permissions. See {@link DevicePolicyManager#setPermissionGrantState}
*/
public final boolean deviceOwnerPermissionGrantOptOut;
/**
* {@code true} if the screen should be on throughout the provisioning flow
*/
public final boolean keepScreenOn;
public static String inferStaticDeviceAdminPackageName(ComponentName deviceAdminComponentName,
String deviceAdminPackageName) {
if (deviceAdminComponentName != null) {
return deviceAdminComponentName.getPackageName();
}
return deviceAdminPackageName;
}
public String inferDeviceAdminPackageName() {
return inferStaticDeviceAdminPackageName(deviceAdminComponentName, deviceAdminPackageName);
}
/**
* Due to legacy reason, DPC is allowed to provide either package name or the component name.
* If component name is not {@code null}, we will return it right away. Otherwise, we will
* infer the component name.
* <p>
* In most cases, it is preferable to access the admin component name using this method.
* But if the purpose is to verify the device admin component name, you should use
* {@link Utils#findDeviceAdmin(String, ComponentName, Context, int)} instead.
*/
public ComponentName inferDeviceAdminComponentName(Utils utils, Context context, int userId)
throws IllegalProvisioningArgumentException {
if (deviceAdminComponentName != null) {
return deviceAdminComponentName;
}
return utils.findDeviceAdmin(
deviceAdminPackageName, deviceAdminComponentName, context, userId);
}
private ProvisioningParams(Builder builder) {
provisioningId = builder.mProvisioningId;
timeZone = builder.mTimeZone;
localTime = builder.mLocalTime;
locale = builder.mLocale;
wifiInfo = builder.mWifiInfo;
useMobileData = builder.mUseMobileData;
deviceAdminComponentName = builder.mDeviceAdminComponentName;
deviceAdminPackageName = builder.mDeviceAdminPackageName;
organizationName = builder.mOrganizationName;
supportUrl = builder.mSupportUrl;
deviceAdminDownloadInfo = builder.mDeviceAdminDownloadInfo;
disclaimersParam = builder.mDisclaimersParam;
adminExtrasBundle = builder.mAdminExtrasBundle;
startedByTrustedSource = builder.mStartedByTrustedSource;
isNfc = builder.mIsNfc;
isQrProvisioning = builder.mIsQrProvisioning;
leaveAllSystemAppsEnabled = builder.mLeaveAllSystemAppsEnabled;
skipEncryption = builder.mSkipEncryption;
accountToMigrate = builder.mAccountToMigrate;
provisioningAction = checkNotNull(builder.mProvisioningAction);
skipEducationScreens = builder.mSkipEducationScreens;
keepAccountMigrated = builder.mKeepAccountMigrated;
isOrganizationOwnedProvisioning = builder.mIsOrganizationOwnedProvisioning;
allowedProvisioningModes = builder.mAllowedProvisioningModes;
initiatorRequestedProvisioningModes = builder.mInitiatorRequestedProvisioningModes;
flowType = builder.mFlowType;
allowProvisioningAfterUserSetupComplete = builder.mAllowProvisioningAfterUserSetupComplete;
provisioningTrigger = builder.mProvisioningTrigger;
skipOwnershipDisclaimer = builder.mSkipOwnershipDisclaimer;
returnBeforePolicyCompliance = builder.mReturnBeforePolicyCompliance;
deviceOwnerPermissionGrantOptOut = builder.mDeviceOwnerPermissionGrantOptOut;
keepScreenOn = builder.mKeepScreenOn;
validateFields();
}
private ProvisioningParams(Parcel in) {
this(createBuilderFromPersistableBundle(
PersistableBundlable.getPersistableBundleFromParcel(in)));
}
private void validateFields() {
checkArgument(deviceAdminPackageName != null || deviceAdminComponentName != null);
}
@Override
public PersistableBundle toPersistableBundle() {
final PersistableBundle bundle = new PersistableBundle();
bundle.putLong(TAG_PROVISIONING_ID, provisioningId);
bundle.putString(EXTRA_PROVISIONING_TIME_ZONE, timeZone);
bundle.putLong(EXTRA_PROVISIONING_LOCAL_TIME, localTime);
bundle.putString(EXTRA_PROVISIONING_LOCALE, StoreUtils.localeToString(locale));
putPersistableBundlableIfNotNull(bundle, TAG_WIFI_INFO, wifiInfo);
bundle.putBoolean(EXTRA_PROVISIONING_USE_MOBILE_DATA, useMobileData);
bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, deviceAdminPackageName);
bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
StoreUtils.componentNameToString(deviceAdminComponentName));
bundle.putString(EXTRA_PROVISIONING_ORGANIZATION_NAME, organizationName);
bundle.putString(EXTRA_PROVISIONING_SUPPORT_URL, supportUrl);
bundle.putPersistableBundle(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, accountToMigrate == null
? null : accountToPersistableBundle(accountToMigrate));
bundle.putString(TAG_PROVISIONING_ACTION, provisioningAction);
putPersistableBundlableIfNotNull(bundle, TAG_PACKAGE_DOWNLOAD_INFO,
deviceAdminDownloadInfo);
putPersistableBundlableIfNotNull(bundle, EXTRA_PROVISIONING_DISCLAIMERS,
disclaimersParam);
bundle.putPersistableBundle(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, adminExtrasBundle);
bundle.putBoolean(TAG_STARTED_BY_TRUSTED_SOURCE, startedByTrustedSource);
bundle.putBoolean(TAG_IS_NFC, isNfc);
bundle.putBoolean(TAG_IS_QR_PROVISIONING, isQrProvisioning);
bundle.putBoolean(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED,
leaveAllSystemAppsEnabled);
bundle.putBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION, skipEncryption);
bundle.putBoolean(EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS, skipEducationScreens);
bundle.putBoolean(EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION, keepAccountMigrated);
bundle.putBoolean(TAG_IS_ORGANIZATION_OWNED_PROVISIONING, isOrganizationOwnedProvisioning);
bundle.putIntArray(TAG_ALLOWED_PROVISIONING_MODES,
integerArrayListToIntArray(allowedProvisioningModes));
bundle.putInt(TAG_INITIATOR_REQUESTED_PROVISIONING_MODES,
initiatorRequestedProvisioningModes);
bundle.putInt(TAG_FLOW_TYPE, flowType);
bundle.putBoolean(TAG_ALLOW_PROVISIONING_AFTER_USER_SETUP_COMPLETE,
allowProvisioningAfterUserSetupComplete);
bundle.putInt(TAG_PROVISIONING_TRIGGER, provisioningTrigger);
bundle.putBoolean(TAG_SKIP_OWNERSHIP_DISCLAIMER, skipOwnershipDisclaimer);
bundle.putBoolean(TAG_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE,
returnBeforePolicyCompliance);
bundle.putBoolean(TAG_DEVICE_OWNER_PERMISSION_GRANT_OPT_OUT,
deviceOwnerPermissionGrantOptOut);
bundle.putBoolean(TAG_KEEP_SCREEN_ON, keepScreenOn);
return bundle;
}
/* package */ static ProvisioningParams fromPersistableBundle(PersistableBundle bundle) {
return createBuilderFromPersistableBundle(bundle).build();
}
private static Builder createBuilderFromPersistableBundle(PersistableBundle bundle) {
Builder builder = new Builder();
builder.setProvisioningId(bundle.getLong(TAG_PROVISIONING_ID, DEFAULT_PROVISIONING_ID));
builder.setTimeZone(bundle.getString(EXTRA_PROVISIONING_TIME_ZONE));
builder.setLocalTime(bundle.getLong(EXTRA_PROVISIONING_LOCAL_TIME));
builder.setLocale(getStringAttrFromPersistableBundle(bundle,
EXTRA_PROVISIONING_LOCALE, StoreUtils::stringToLocale));
builder.setUseMobileData(bundle.getBoolean(EXTRA_PROVISIONING_USE_MOBILE_DATA));
builder.setWifiInfo(getObjectAttrFromPersistableBundle(bundle,
TAG_WIFI_INFO, WifiInfo::fromPersistableBundle));
builder.setDeviceAdminPackageName(bundle.getString(
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME));
builder.setDeviceAdminComponentName(getStringAttrFromPersistableBundle(bundle,
EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, StoreUtils::stringToComponentName));
builder.setOrganizationName(bundle.getString(EXTRA_PROVISIONING_ORGANIZATION_NAME));
builder.setSupportUrl(bundle.getString(EXTRA_PROVISIONING_SUPPORT_URL));
builder.setAccountToMigrate(getObjectAttrFromPersistableBundle(bundle,
EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, StoreUtils::persistableBundleToAccount));
builder.setProvisioningAction(bundle.getString(TAG_PROVISIONING_ACTION));
builder.setDeviceAdminDownloadInfo(getObjectAttrFromPersistableBundle(bundle,
TAG_PACKAGE_DOWNLOAD_INFO, PackageDownloadInfo::fromPersistableBundle));
builder.setDisclaimersParam(getObjectAttrFromPersistableBundle(bundle,
EXTRA_PROVISIONING_DISCLAIMERS, DisclaimersParam::fromPersistableBundle));
builder.setAdminExtrasBundle(bundle.getPersistableBundle(
EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE));
builder.setStartedByTrustedSource(bundle.getBoolean(TAG_STARTED_BY_TRUSTED_SOURCE));
builder.setIsNfc(bundle.getBoolean(TAG_IS_NFC));
builder.setIsQrProvisioning(bundle.getBoolean(TAG_IS_QR_PROVISIONING));
builder.setSkipEncryption(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION));
builder.setLeaveAllSystemAppsEnabled(bundle.getBoolean(
EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED));
builder.setSkipEducationScreens(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS));
builder.setKeepAccountMigrated(bundle.getBoolean(
EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION));
builder.setIsOrganizationOwnedProvisioning(bundle.getBoolean(
TAG_IS_ORGANIZATION_OWNED_PROVISIONING));
builder.setAllowedProvisioningModes(
intArrayToIntegerArrayList(bundle.getIntArray(TAG_ALLOWED_PROVISIONING_MODES)));
builder.setInitiatorRequestedProvisioningModes(bundle.getInt(
TAG_INITIATOR_REQUESTED_PROVISIONING_MODES));
builder.setFlowType(bundle.getInt(TAG_FLOW_TYPE));
builder.setAllowProvisioningAfterUserSetupComplete(bundle.getBoolean(
TAG_ALLOW_PROVISIONING_AFTER_USER_SETUP_COMPLETE));
builder.setProvisioningTrigger(bundle.getInt(TAG_PROVISIONING_TRIGGER));
builder.setSkipOwnershipDisclaimer(bundle.getBoolean(TAG_SKIP_OWNERSHIP_DISCLAIMER));
builder.setReturnBeforePolicyCompliance(bundle.getBoolean(
TAG_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE));
builder.setDeviceOwnerPermissionGrantOptOut(
bundle.getBoolean(TAG_DEVICE_OWNER_PERMISSION_GRANT_OPT_OUT));
builder.setKeepScreenOn(bundle.getBoolean(TAG_KEEP_SCREEN_ON));
return builder;
}
private static ArrayList<Integer> intArrayToIntegerArrayList(int[] intArray) {
return Arrays.stream(intArray).boxed().collect(Collectors.toCollection(ArrayList::new));
}
private static int[] integerArrayListToIntArray(ArrayList<Integer> arrayList) {
return arrayList.stream().mapToInt(Integer::valueOf).toArray();
}
public Builder toBuilder() {
return createBuilderFromPersistableBundle(toPersistableBundle());
}
@Override
public String toString() {
return "ProvisioningParams values: " + toPersistableBundle().toString();
}
/**
* Saves the ProvisioningParams to the specified file.
*/
public void save(File file) {
ProvisionLogger.logd("Saving ProvisioningParams to " + file);
AtomicFile atomicFile = null;
FileOutputStream stream = null;
try {
atomicFile = new AtomicFile(file);
stream = atomicFile.startWrite();
XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(stream, StandardCharsets.UTF_8.name());
serializer.startDocument(null, true);
serializer.startTag(null, TAG_PROVISIONING_PARAMS);
toPersistableBundle().saveToXml(serializer);
serializer.endTag(null, TAG_PROVISIONING_PARAMS);
serializer.endDocument();
atomicFile.finishWrite(stream);
} catch (IOException | XmlPullParserException e) {
ProvisionLogger.loge("Caught exception while trying to save Provisioning Params to "
+ " file " + file, e);
file.delete();
if (atomicFile != null) {
atomicFile.failWrite(stream);
}
}
}
public void cleanUp() {
if (disclaimersParam != null) {
disclaimersParam.cleanUp();
}
}
/**
* Loads the ProvisioningParams From the specified file.
*/
public static ProvisioningParams load(File file) {
if (!file.exists()) {
return null;
}
ProvisionLogger.logd("Loading ProvisioningParams from " + file);
try (FileInputStream stream = new FileInputStream(file)) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(stream, null);
return load(parser);
} catch (IOException | XmlPullParserException e) {
ProvisionLogger.loge("Caught exception while trying to load the provisioning params"
+ " from file " + file, e);
return null;
}
}
private static ProvisioningParams load(XmlPullParser parser) throws XmlPullParserException,
IOException {
int type;
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tag = parser.getName();
switch (tag) {
case TAG_PROVISIONING_PARAMS:
return createBuilderFromPersistableBundle(
PersistableBundle.restoreFromXml(parser)).build();
}
}
return new Builder().build();
}
public final static class Builder {
private long mProvisioningId;
private String mTimeZone;
private long mLocalTime = DEFAULT_LOCAL_TIME;
private Locale mLocale;
private WifiInfo mWifiInfo;
private String mDeviceAdminPackageName;
private ComponentName mDeviceAdminComponentName;
private String mOrganizationName;
private String mSupportUrl;
private Account mAccountToMigrate;
private String mProvisioningAction;
private PackageDownloadInfo mDeviceAdminDownloadInfo;
private DisclaimersParam mDisclaimersParam;
private PersistableBundle mAdminExtrasBundle;
private boolean mStartedByTrustedSource = DEFAULT_STARTED_BY_TRUSTED_SOURCE;
private boolean mIsNfc = DEFAULT_IS_NFC;
private boolean mIsQrProvisioning = DEFAULT_IS_QR_PROVISIONING;
private boolean mLeaveAllSystemAppsEnabled = DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED;
private boolean mSkipEncryption = DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION;
private boolean mSkipEducationScreens = DEFAULT_EXTRA_PROVISIONING_SKIP_EDUCATION_SCREENS;
private boolean mKeepAccountMigrated = DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED;
private boolean mUseMobileData = DEFAULT_EXTRA_PROVISIONING_USE_MOBILE_DATA;
private boolean mIsOrganizationOwnedProvisioning =
DEFAULT_EXTRA_PROVISIONING_IS_ORGANIZATION_OWNED;
private ArrayList<Integer> mAllowedProvisioningModes =
DEFAULT_EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES;
private int mInitiatorRequestedProvisioningModes =
DEFAULT_EXTRA_PROVISIONING_SUPPORTED_MODES;
private @FlowType int mFlowType = FLOW_TYPE_UNSPECIFIED;
private boolean mAllowProvisioningAfterUserSetupComplete = false;
private @ProvisioningTrigger int mProvisioningTrigger = PROVISIONING_TRIGGER_UNSPECIFIED;
private boolean mSkipOwnershipDisclaimer =
DEFAULT_EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER;
private boolean mReturnBeforePolicyCompliance =
DEFAULT_EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE;
private boolean mDeviceOwnerPermissionGrantOptOut =
DEFAULT_EXTRA_PROVISIONING_PERMISSION_GRANT_OPT_OUT;
private boolean mKeepScreenOn = DEFAULT_EXTRA_PROVISIONING_KEEP_SCREEN_ON;
public Builder setProvisioningId(long provisioningId) {
mProvisioningId = provisioningId;
return this;
}
public Builder setTimeZone(String timeZone) {
mTimeZone = timeZone;
return this;
}
public Builder setLocalTime(long localTime) {
mLocalTime = localTime;
return this;
}
public Builder setLocale(Locale locale) {
mLocale = locale;
return this;
}
public Builder setWifiInfo(WifiInfo wifiInfo) {
mWifiInfo = wifiInfo;
return this;
}
@Deprecated
public Builder setDeviceAdminPackageName(String deviceAdminPackageName) {
mDeviceAdminPackageName = deviceAdminPackageName;
return this;
}
public Builder setDeviceAdminComponentName(ComponentName deviceAdminComponentName) {
mDeviceAdminComponentName = deviceAdminComponentName;
return this;
}
public Builder setOrganizationName(String organizationName) {
mOrganizationName = organizationName;
return this;
}
public Builder setSupportUrl(String supportUrl) {
mSupportUrl = supportUrl;
return this;
}
public Builder setAccountToMigrate(Account accountToMigrate) {
mAccountToMigrate = accountToMigrate;
return this;
}
public Builder setProvisioningAction(String provisioningAction) {
mProvisioningAction = provisioningAction;
return this;
}
public Builder setDeviceAdminDownloadInfo(PackageDownloadInfo deviceAdminDownloadInfo) {
mDeviceAdminDownloadInfo = deviceAdminDownloadInfo;
return this;
}
public Builder setDisclaimersParam(DisclaimersParam disclaimersParam) {
mDisclaimersParam = disclaimersParam;
return this;
}
public Builder setAdminExtrasBundle(PersistableBundle adminExtrasBundle) {
mAdminExtrasBundle = adminExtrasBundle;
return this;
}
public Builder setStartedByTrustedSource(boolean startedByTrustedSource) {
mStartedByTrustedSource = startedByTrustedSource;
return this;
}
public Builder setIsNfc(boolean isNfc) {
mIsNfc = isNfc;
return this;
}
public Builder setIsQrProvisioning(boolean qrProvisioning) {
mIsQrProvisioning = qrProvisioning;
return this;
}
public Builder setLeaveAllSystemAppsEnabled(boolean leaveAllSystemAppsEnabled) {
mLeaveAllSystemAppsEnabled = leaveAllSystemAppsEnabled;
return this;
}
public Builder setSkipEncryption(boolean skipEncryption) {
mSkipEncryption = skipEncryption;
return this;
}
public Builder setSkipEducationScreens(boolean skipEducationScreens) {
mSkipEducationScreens = skipEducationScreens;
return this;
}
public Builder setKeepAccountMigrated(boolean keepAccountMigrated) {
mKeepAccountMigrated = keepAccountMigrated;
return this;
}
public Builder setUseMobileData(boolean useMobileData) {
mUseMobileData = useMobileData;
return this;
}
public Builder setIsOrganizationOwnedProvisioning(boolean isOrganizationOwnedProvisioning) {
mIsOrganizationOwnedProvisioning = isOrganizationOwnedProvisioning;
return this;
}
public Builder setFlowType(@FlowType int flowType) {
mFlowType = flowType;
return this;
}
public Builder setAllowProvisioningAfterUserSetupComplete(
boolean allowProvisioningAfterUserSetupComplete) {
mAllowProvisioningAfterUserSetupComplete = allowProvisioningAfterUserSetupComplete;
return this;
}
public Builder setProvisioningTrigger(@ProvisioningTrigger int provisioningTrigger) {
mProvisioningTrigger = provisioningTrigger;
return this;
}
public Builder setAllowedProvisioningModes(ArrayList<Integer> provisioningModes) {
mAllowedProvisioningModes = new ArrayList<>(provisioningModes);
return this;
}
public Builder setInitiatorRequestedProvisioningModes(
int initiatorRequestedProvisioningModes) {
mInitiatorRequestedProvisioningModes = initiatorRequestedProvisioningModes;
return this;
}
/**
* See {@link ProvisioningParams#skipOwnershipDisclaimer}.
*/
public Builder setSkipOwnershipDisclaimer(boolean skipOwnershipDisclaimer) {
mSkipOwnershipDisclaimer = skipOwnershipDisclaimer;
return this;
}
/**
* Setter for {@link #returnBeforePolicyCompliance}.
*/
public Builder setReturnBeforePolicyCompliance(boolean returnBeforePolicyCompliance) {
mReturnBeforePolicyCompliance = returnBeforePolicyCompliance;
return this;
}
/**
* Setter for whether the admin has opted out of controlling permission grants.
*/
public Builder setDeviceOwnerPermissionGrantOptOut(boolean optout) {
mDeviceOwnerPermissionGrantOptOut = optout;
return this;
}
/**
* Setter for whether the screen should be on throughout the provisioning flow.
*/
public Builder setKeepScreenOn(boolean keepScreenOn) {
mKeepScreenOn = keepScreenOn;
return this;
}
/**
* Builds the {@link ProvisioningParams} object. Note that {@link
* #setProvisioningAction(String)} and {@link #setDeviceAdminComponentName(ComponentName)}
* methods must be called with a non-null parameter before this is called.
*/
public ProvisioningParams build() {
return new ProvisioningParams(this);
}
public static Builder builder() {
return new Builder();
}
}
}