/* * 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 com.android.internal.util.Preconditions.checkArgument; import static com.android.internal.util.Preconditions.checkNotNull; import android.accounts.Account; import android.content.Context; import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; import android.support.annotation.Nullable; import android.text.TextUtils; import java.util.Arrays; import java.util.Locale; import java.util.Objects; import java.util.Set; import com.android.internal.annotations.Immutable; import com.android.managedprovisioning.common.IllegalProvisioningArgumentException; import com.android.managedprovisioning.common.Utils; /** * Provisioning parameters for Device Owner and Profile Owner provisioning. */ public final class ProvisioningParams implements Parcelable { 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_LEAVE_ALL_SYSTEM_APPS_ENABLED = false; public static final boolean DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION = false; public static final boolean DEFAULT_SKIP_USER_SETUP = true; // Intent extra used internally for passing data between activities and service. public static final String EXTRA_PROVISIONING_PARAMS = "provisioningParams"; 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]; } }; @Nullable public final String timeZone; public final long localTime; @Nullable public final Locale locale; /** WiFi configuration. */ @Nullable public final WifiInfo wifiInfo; /** * Package name of the device admin package. * *

At least one one of deviceAdminPackageName and deviceAdminComponentName should be * non-null. */ @Deprecated public final String deviceAdminPackageName; /** * {@link ComponentName} of the device admin package. * *

At least one one of deviceAdminPackageName and deviceAdminComponentName should be * non-null. */ public final ComponentName deviceAdminComponentName; /** {@link Account} that should be migrated to the managed profile. */ @Nullable public final Account accountToMigrate; /** 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; /** * 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; /** 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; // TODO (stevenckng): This shouldn't belong here. Remove this logic from ProvisioningParams. private ComponentName inferedDeviceAdminComponentName; private final Utils mUtils = new Utils(); public String inferDeviceAdminPackageName() { if (deviceAdminComponentName != null) { return deviceAdminComponentName.getPackageName(); } return deviceAdminPackageName; } // This should not be called if the app has not been installed yet. public ComponentName inferDeviceAdminComponentName(Context c) throws IllegalProvisioningArgumentException { if (inferedDeviceAdminComponentName == null) { inferedDeviceAdminComponentName = mUtils.findDeviceAdmin( deviceAdminPackageName, deviceAdminComponentName, c); } return inferedDeviceAdminComponentName; } private ProvisioningParams(Builder builder) { timeZone = builder.mTimeZone; localTime = builder.mLocalTime; locale = builder.mLocale; wifiInfo = builder.mWifiInfo; deviceAdminComponentName = builder.mDeviceAdminComponentName; deviceAdminPackageName = builder.mDeviceAdminPackageName; deviceAdminDownloadInfo = builder.mDeviceAdminDownloadInfo; adminExtrasBundle = builder.mAdminExtrasBundle; startedByTrustedSource = builder.mStartedByTrustedSource; leaveAllSystemAppsEnabled = builder.mLeaveAllSystemAppsEnabled; skipEncryption = builder.mSkipEncryption; accountToMigrate = builder.mAccountToMigrate; provisioningAction = checkNotNull(builder.mProvisioningAction); mainColor = builder.mMainColor; skipUserSetup = builder.mSkipUserSetup; validateFields(); } private ProvisioningParams(Parcel in) { timeZone = in.readString(); localTime = in.readLong(); locale = (Locale) in.readSerializable(); wifiInfo = (WifiInfo) in.readParcelable(WifiInfo.class.getClassLoader()); deviceAdminPackageName = in.readString(); deviceAdminComponentName = (ComponentName) in.readParcelable(null /* use default classloader */); deviceAdminDownloadInfo = (PackageDownloadInfo) in.readParcelable(PackageDownloadInfo.class.getClassLoader()); adminExtrasBundle = in.readParcelable(null /* use default classloader */); startedByTrustedSource = in.readInt() == 1; leaveAllSystemAppsEnabled = in.readInt() == 1; skipEncryption = in.readInt() == 1; accountToMigrate = (Account) in.readParcelable(null /* use default classloader */); provisioningAction = checkNotNull(in.readString()); if (in.readInt() != 0) { mainColor = in.readInt(); } else { mainColor = null; } skipUserSetup = in.readInt() == 1; validateFields(); } private void validateFields() { checkArgument(deviceAdminPackageName != null || deviceAdminComponentName != null); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { out.writeString(timeZone); out.writeLong(localTime); out.writeSerializable(locale); out.writeParcelable(wifiInfo, 0 /* default */ ); out.writeString(deviceAdminPackageName); out.writeParcelable(deviceAdminComponentName, 0 /* default */); out.writeParcelable(deviceAdminDownloadInfo, 0 /* default */); out.writeParcelable(adminExtrasBundle, 0 /* default */); out.writeInt(startedByTrustedSource ? 1 : 0); out.writeInt(leaveAllSystemAppsEnabled ? 1 : 0); out.writeInt(skipEncryption ? 1 : 0); out.writeParcelable(accountToMigrate, 0 /* default */); out.writeString(provisioningAction); if (mainColor != null) { out.writeInt(1); out.writeInt(mainColor); } else { out.writeInt(0); } out.writeInt(skipUserSetup ? 1 : 0); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ProvisioningParams that = (ProvisioningParams) o; return localTime == that.localTime && startedByTrustedSource == that.startedByTrustedSource && leaveAllSystemAppsEnabled == that.leaveAllSystemAppsEnabled && skipEncryption == that.skipEncryption && skipUserSetup == that.skipUserSetup && Objects.equals(timeZone, that.timeZone) && Objects.equals(locale, that.locale) && Objects.equals(wifiInfo, that.wifiInfo) && Objects.equals(deviceAdminPackageName, that.deviceAdminPackageName) && Objects.equals(deviceAdminComponentName, that.deviceAdminComponentName) && Objects.equals(accountToMigrate, that.accountToMigrate) && Objects.equals(provisioningAction, that.provisioningAction) && Objects.equals(mainColor, that.mainColor) && Objects.equals(deviceAdminDownloadInfo, that.deviceAdminDownloadInfo) && isPersistableBundleEquals(adminExtrasBundle, that.adminExtrasBundle) && Objects.equals( inferedDeviceAdminComponentName, that.inferedDeviceAdminComponentName); } /** * Compares two {@link PersistableBundle} objects are equals. */ private static boolean isPersistableBundleEquals( PersistableBundle obj1, PersistableBundle obj2) { if (obj1 == obj2) { return true; } if (obj1 == null || obj2 == null || obj1.size() != obj2.size()) { return false; } Set keys = obj1.keySet(); for (String key : keys) { Object val1 = obj1.get(key); Object val2 = obj2.get(key); if (!isPersistableBundleSupportedValueEquals(val1, val2)) { return false; } } return true; } /** * Compares two values which type is supported by {@link PersistableBundle}. * *

If the type isn't supported. The equality is done by {@link Object#equals(Object)}. */ private static boolean isPersistableBundleSupportedValueEquals(Object val1, Object val2) { if (val1 == val2) { return true; } else if (val1 == null || val2 == null || !val1.getClass().equals(val2.getClass())) { return false; } else if (val1 instanceof PersistableBundle && val2 instanceof PersistableBundle) { return isPersistableBundleEquals((PersistableBundle) val1, (PersistableBundle) val2); } else if (val1 instanceof int[]) { return Arrays.equals((int[]) val1, (int[]) val2); } else if (val1 instanceof long[]) { return Arrays.equals((long[]) val1, (long[]) val2); } else if (val1 instanceof double[]) { return Arrays.equals((double[]) val1, (double[]) val2); } else if (val1 instanceof boolean[]) { return Arrays.equals((boolean[]) val1, (boolean[]) val2); } else if (val1 instanceof String[]) { return Arrays.equals((String[]) val1, (String[]) val2); } else { return Objects.equals(val1, val2); } } public final static class Builder { private String mTimeZone; private long mLocalTime = DEFAULT_LOCAL_TIME; private Locale mLocale; private WifiInfo mWifiInfo; private String mDeviceAdminPackageName; private ComponentName mDeviceAdminComponentName; private Account mAccountToMigrate; private String mProvisioningAction; private Integer mMainColor = DEFAULT_MAIN_COLOR; private PackageDownloadInfo mDeviceAdminDownloadInfo; private PersistableBundle mAdminExtrasBundle; private boolean mStartedByTrustedSource = DEFAULT_STARTED_BY_TRUSTED_SOURCE; private boolean mLeaveAllSystemAppsEnabled = DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED; private boolean mSkipEncryption = DEFAULT_EXTRA_PROVISIONING_SKIP_ENCRYPTION; private boolean mSkipUserSetup = DEFAULT_SKIP_USER_SETUP; 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 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 setAdminExtrasBundle(PersistableBundle adminExtrasBundle) { mAdminExtrasBundle = adminExtrasBundle; return this; } public Builder setStartedByTrustedSource(boolean startedByTrustedSource) { mStartedByTrustedSource = startedByTrustedSource; return this; } public Builder setLeaveAllSystemAppsEnabled(boolean leaveAllSystemAppsEnabled) { mLeaveAllSystemAppsEnabled = leaveAllSystemAppsEnabled; return this; } public Builder setSkipEncryption(boolean skipEncryption) { mSkipEncryption = skipEncryption; return this; } public Builder setSkipUserSetup(boolean skipUserSetup) { mSkipUserSetup = skipUserSetup; return this; } public ProvisioningParams build() { return new ProvisioningParams(this); } public static Builder builder() { return new Builder(); } } }