/* * 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_ICON_URI; import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL; 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_MAIN_COLOR; import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ORGANIZATION_NAME; import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION; import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_USER_CONSENT; import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_USER_SETUP; 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 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.getIntegerAttrFromPersistableBundle; import static com.android.managedprovisioning.common.StoreUtils.getObjectAttrFromPersistableBundle; import static com.android.managedprovisioning.common.StoreUtils.getStringAttrFromPersistableBundle; import static com.android.managedprovisioning.common.StoreUtils.putIntegerIfNotNull; import static com.android.managedprovisioning.common.StoreUtils.putPersistableBundlableIfNotNull; import android.accounts.Account; import android.content.ComponentName; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; import android.support.annotation.Nullable; import android.util.AtomicFile; import android.util.Xml; 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.nio.charset.StandardCharsets; import java.util.Locale; /** * 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 Integer DEFAULT_MAIN_COLOR = null; public static final boolean DEFAULT_STARTED_BY_TRUSTED_SOURCE = false; public static final boolean DEFAULT_IS_NFC = 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_USER_CONSENT = false; public static final boolean DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED = false; public static final boolean DEFAULT_SKIP_USER_SETUP = true; public static final boolean DEFAULT_EXTRA_PROVISIONING_USE_MOBILE_DATA = false; // Intent extra used internally for passing data between activities and service. public static final String EXTRA_PROVISIONING_PARAMS = "provisioningParams"; 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_PROVISIONING_ACTION = "provisioning-action"; public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @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. * *

At least one one of deviceAdminPackageName and deviceAdminComponentName should be * non-null. *

* 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. * *

At least one one of deviceAdminPackageName and deviceAdminComponentName should be * non-null. *

* 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 deviceAdminLabel; public final String organizationName; public final String supportUrl; public final String deviceAdminIconFilePath; /** {@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 main color theme used in managed profile only. * *

{@code null} means the default value. */ @Nullable public final Integer mainColor; /** 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. * *

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; /** 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; /** True if user setup can be skipped. */ public final boolean skipUserSetup; /** True if user consent page in pre-provisioning can be skipped. */ public final boolean skipUserConsent; 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. *

* 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; deviceAdminLabel = builder.mDeviceAdminLabel; organizationName = builder.mOrganizationName; supportUrl = builder.mSupportUrl; deviceAdminIconFilePath = builder.mDeviceAdminIconFilePath; deviceAdminDownloadInfo = builder.mDeviceAdminDownloadInfo; disclaimersParam = builder.mDisclaimersParam; adminExtrasBundle = builder.mAdminExtrasBundle; startedByTrustedSource = builder.mStartedByTrustedSource; isNfc = builder.mIsNfc; leaveAllSystemAppsEnabled = builder.mLeaveAllSystemAppsEnabled; skipEncryption = builder.mSkipEncryption; accountToMigrate = builder.mAccountToMigrate; provisioningAction = checkNotNull(builder.mProvisioningAction); mainColor = builder.mMainColor; skipUserConsent = builder.mSkipUserConsent; skipUserSetup = builder.mSkipUserSetup; keepAccountMigrated = builder.mKeepAccountMigrated; 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_DEVICE_ADMIN_PACKAGE_LABEL, deviceAdminLabel); bundle.putString(EXTRA_PROVISIONING_ORGANIZATION_NAME, organizationName); bundle.putString(EXTRA_PROVISIONING_SUPPORT_URL, supportUrl); bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI, deviceAdminIconFilePath); bundle.putPersistableBundle(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, accountToMigrate == null ? null : accountToPersistableBundle(accountToMigrate)); bundle.putString(TAG_PROVISIONING_ACTION, provisioningAction); putIntegerIfNotNull(bundle, EXTRA_PROVISIONING_MAIN_COLOR, mainColor); 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(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED, leaveAllSystemAppsEnabled); bundle.putBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION, skipEncryption); bundle.putBoolean(EXTRA_PROVISIONING_SKIP_USER_SETUP, skipUserSetup); bundle.putBoolean(EXTRA_PROVISIONING_SKIP_USER_CONSENT, skipUserConsent); bundle.putBoolean(EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION, keepAccountMigrated); 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.setDeviceAdminLabel(bundle.getString( EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL)); builder.setOrganizationName(bundle.getString(EXTRA_PROVISIONING_ORGANIZATION_NAME)); builder.setSupportUrl(bundle.getString(EXTRA_PROVISIONING_SUPPORT_URL)); builder.setDeviceAdminIconFilePath(bundle.getString( EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI)); builder.setAccountToMigrate(getObjectAttrFromPersistableBundle(bundle, EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, StoreUtils::persistableBundleToAccount)); builder.setProvisioningAction(bundle.getString(TAG_PROVISIONING_ACTION)); builder.setMainColor(getIntegerAttrFromPersistableBundle(bundle, EXTRA_PROVISIONING_MAIN_COLOR)); 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.setSkipEncryption(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_ENCRYPTION)); builder.setLeaveAllSystemAppsEnabled(bundle.getBoolean( EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED)); builder.setSkipUserSetup(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_USER_SETUP)); builder.setSkipUserConsent(bundle.getBoolean(EXTRA_PROVISIONING_SKIP_USER_CONSENT)); builder.setKeepAccountMigrated(bundle.getBoolean( EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION)); return builder; } @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(); } if (deviceAdminIconFilePath != null) { new File(deviceAdminIconFilePath).delete(); } } /** * 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 mDeviceAdminLabel; private String mOrganizationName; private String mSupportUrl; private String mDeviceAdminIconFilePath; private Account mAccountToMigrate; private String mProvisioningAction; private Integer mMainColor = DEFAULT_MAIN_COLOR; 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 mLeaveAllSystemAppsEnabled = DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED; private boolean mSkipEncryption = DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION; private boolean mSkipUserConsent = DEFAULT_EXTRA_PROVISIONING_SKIP_USER_CONSENT; private boolean mSkipUserSetup = DEFAULT_SKIP_USER_SETUP; private boolean mKeepAccountMigrated = DEFAULT_EXTRA_PROVISIONING_KEEP_ACCOUNT_MIGRATED; private boolean mUseMobileData = DEFAULT_EXTRA_PROVISIONING_USE_MOBILE_DATA; 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 setDeviceAdminLabel(String deviceAdminLabel) { mDeviceAdminLabel = deviceAdminLabel; return this; } public Builder setOrganizationName(String organizationName) { mOrganizationName = organizationName; return this; } public Builder setSupportUrl(String supportUrl) { mSupportUrl = supportUrl; return this; } public Builder setDeviceAdminIconFilePath(String deviceAdminIconFilePath) { mDeviceAdminIconFilePath = deviceAdminIconFilePath; return this; } public Builder setAccountToMigrate(Account accountToMigrate) { mAccountToMigrate = accountToMigrate; return this; } public Builder setProvisioningAction(String provisioningAction) { mProvisioningAction = provisioningAction; return this; } public Builder setMainColor(Integer mainColor) { mMainColor = mainColor; 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 setLeaveAllSystemAppsEnabled(boolean leaveAllSystemAppsEnabled) { mLeaveAllSystemAppsEnabled = leaveAllSystemAppsEnabled; return this; } public Builder setSkipEncryption(boolean skipEncryption) { mSkipEncryption = skipEncryption; return this; } public Builder setSkipUserConsent(boolean skipUserConsent) { mSkipUserConsent = skipUserConsent; return this; } public Builder setSkipUserSetup(boolean skipUserSetup) { mSkipUserSetup = skipUserSetup; return this; } public Builder setKeepAccountMigrated(boolean keepAccountMigrated) { mKeepAccountMigrated = keepAccountMigrated; return this; } public Builder setUseMobileData(boolean useMobileData) { mUseMobileData = useMobileData; return this; } public ProvisioningParams build() { return new ProvisioningParams(this); } public static Builder builder() { return new Builder(); } } }