diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 15666017f4319..5a6e8ee22128e 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -234,6 +234,7 @@ package android { field public static final String POWER_SAVER = "android.permission.POWER_SAVER"; field public static final String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE"; field public static final String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT"; + field public static final String PROVISION_DEMO_DEVICE = "android.permission.PROVISION_DEMO_DEVICE"; field public static final String QUERY_ADMIN_POLICY = "android.permission.QUERY_ADMIN_POLICY"; field public static final String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES"; field public static final String QUERY_USERS = "android.permission.QUERY_USERS"; @@ -1101,7 +1102,7 @@ package android.app.admin { method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long); method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String); - method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException; + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, android.Manifest.permission.PROVISION_DEMO_DEVICE}) public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException; method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void resetDrawables(@NonNull String[]); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void resetStrings(@NonNull String[]); method @RequiresPermission(android.Manifest.permission.SEND_LOST_MODE_LOCATION_UPDATES) public void sendLostModeLocationUpdate(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); @@ -1254,6 +1255,7 @@ package android.app.admin { method @Nullable public java.util.Locale getLocale(); method @NonNull public String getOwnerName(); method @Nullable public String getTimeZone(); + method public boolean isDemoDevice(); method public boolean isLeaveAllSystemAppsEnabled(); method public void writeToParcel(@NonNull android.os.Parcel, @Nullable int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; @@ -1264,6 +1266,7 @@ package android.app.admin { method @NonNull public android.app.admin.FullyManagedDeviceProvisioningParams build(); method @NonNull public android.app.admin.FullyManagedDeviceProvisioningParams.Builder setAdminExtras(@NonNull android.os.PersistableBundle); method @NonNull public android.app.admin.FullyManagedDeviceProvisioningParams.Builder setCanDeviceOwnerGrantSensorsPermissions(boolean); + method @NonNull public android.app.admin.FullyManagedDeviceProvisioningParams.Builder setDemoDevice(boolean); method @NonNull public android.app.admin.FullyManagedDeviceProvisioningParams.Builder setLeaveAllSystemAppsEnabled(boolean); method @NonNull public android.app.admin.FullyManagedDeviceProvisioningParams.Builder setLocalTime(long); method @NonNull public android.app.admin.FullyManagedDeviceProvisioningParams.Builder setLocale(@Nullable java.util.Locale); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index b436f6e7374f4..9bfdbd4595745 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -14776,17 +14776,20 @@ public class DevicePolicyManager { *

The method {@link #checkProvisioningPrecondition} must be returning {@link #STATUS_OK} * before calling this method. * + *

Holders of {@link android.Manifest.permission#PROVISION_DEMO_DEVICE} can call this API + * only if {@link FullyManagedDeviceProvisioningParams#isDemoDevice()} is {@code true}.

+ * * @param provisioningParams Params required to provision a fully managed device, * see {@link FullyManagedDeviceProvisioningParams}. * - * @throws SecurityException if the caller does not hold - * {@link android.Manifest.permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}. * @throws ProvisioningException if an error occurred during provisioning. * * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, + android.Manifest.permission.PROVISION_DEMO_DEVICE}) public void provisionFullyManagedDevice( @NonNull FullyManagedDeviceProvisioningParams provisioningParams) throws ProvisioningException { diff --git a/core/java/android/app/admin/FullyManagedDeviceProvisioningParams.java b/core/java/android/app/admin/FullyManagedDeviceProvisioningParams.java index 1f7ae4ad35de0..49992452df86b 100644 --- a/core/java/android/app/admin/FullyManagedDeviceProvisioningParams.java +++ b/core/java/android/app/admin/FullyManagedDeviceProvisioningParams.java @@ -26,6 +26,7 @@ import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; +import android.provider.Settings; import android.stats.devicepolicy.DevicePolicyEnums; import java.util.Locale; @@ -44,6 +45,7 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { "CAN_DEVICE_OWNER_GRANT_SENSOR_PERMISSIONS"; private static final String TIME_ZONE_PROVIDED_PARAM = "TIME_ZONE_PROVIDED"; private static final String LOCALE_PROVIDED_PARAM = "LOCALE_PROVIDED"; + private static final String DEMO_DEVICE = "DEMO_DEVICE"; @NonNull private final ComponentName mDeviceAdminComponentName; @NonNull private final String mOwnerName; @@ -54,6 +56,8 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { @Nullable private final Locale mLocale; private final boolean mDeviceOwnerCanGrantSensorsPermissions; @NonNull private final PersistableBundle mAdminExtras; + private final boolean mDemoDevice; + private FullyManagedDeviceProvisioningParams( @NonNull ComponentName deviceAdminComponentName, @@ -63,7 +67,8 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { long localTime, @Nullable @SuppressLint("UseIcu") Locale locale, boolean deviceOwnerCanGrantSensorsPermissions, - @NonNull PersistableBundle adminExtras) { + @NonNull PersistableBundle adminExtras, + boolean demoDevice) { this.mDeviceAdminComponentName = requireNonNull(deviceAdminComponentName); this.mOwnerName = requireNonNull(ownerName); this.mLeaveAllSystemAppsEnabled = leaveAllSystemAppsEnabled; @@ -73,6 +78,7 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { this.mDeviceOwnerCanGrantSensorsPermissions = deviceOwnerCanGrantSensorsPermissions; this.mAdminExtras = adminExtras; + this.mDemoDevice = demoDevice; } private FullyManagedDeviceProvisioningParams( @@ -83,7 +89,8 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { long localTime, @Nullable String localeStr, boolean deviceOwnerCanGrantSensorsPermissions, - @Nullable PersistableBundle adminExtras) { + @Nullable PersistableBundle adminExtras, + boolean demoDevice) { this(deviceAdminComponentName, ownerName, leaveAllSystemAppsEnabled, @@ -91,7 +98,8 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { localTime, getLocale(localeStr), deviceOwnerCanGrantSensorsPermissions, - adminExtras); + adminExtras, + demoDevice); } @Nullable @@ -165,6 +173,14 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { return new PersistableBundle(mAdminExtras); } + /** + * @return true if this device is being setup as a retail demo device, see + * {@link Settings.Global#DEVICE_DEMO_MODE}. + */ + public boolean isDemoDevice() { + return mDemoDevice; + } + /** * Logs the provisioning params using {@link DevicePolicyEventLogger}. * @@ -178,6 +194,7 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { mDeviceOwnerCanGrantSensorsPermissions); logParam(callerPackage, TIME_ZONE_PROVIDED_PARAM, /* value= */ mTimeZone != null); logParam(callerPackage, LOCALE_PROVIDED_PARAM, /* value= */ mLocale != null); + logParam(callerPackage, DEMO_DEVICE, mDemoDevice); } private void logParam(String callerPackage, String param, boolean value) { @@ -204,6 +221,9 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { // Default to allowing control over sensor permission grants. boolean mDeviceOwnerCanGrantSensorsPermissions = true; @NonNull private PersistableBundle mAdminExtras; + // Default is normal user devices + boolean mDemoDevice = false; + /** * Initialize a new {@link Builder} to construct a @@ -288,6 +308,16 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { return this; } + /** + * Marks the device as a demo device, see {@link Settings.Global#DEVICE_DEMO_MODE}. The + * default value if unset is {@code false}. + */ + @NonNull + public Builder setDemoDevice(boolean demoDevice) { + this.mDemoDevice = demoDevice; + return this; + } + /** * Combines all of the attributes that have been set on this {@code Builder} * @@ -303,7 +333,8 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { mLocalTime, mLocale, mDeviceOwnerCanGrantSensorsPermissions, - mAdminExtras); + mAdminExtras, + mDemoDevice); } } @@ -327,6 +358,7 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { + ", mDeviceOwnerCanGrantSensorsPermissions=" + mDeviceOwnerCanGrantSensorsPermissions + ", mAdminExtras=" + mAdminExtras + + ", mDemoDevice=" + mDemoDevice + '}'; } @@ -340,6 +372,7 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { dest.writeString(mLocale == null ? null : mLocale.toLanguageTag()); dest.writeBoolean(mDeviceOwnerCanGrantSensorsPermissions); dest.writePersistableBundle(mAdminExtras); + dest.writeBoolean(mDemoDevice); } @NonNull @@ -355,6 +388,7 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { String locale = in.readString(); boolean deviceOwnerCanGrantSensorsPermissions = in.readBoolean(); PersistableBundle adminExtras = in.readPersistableBundle(); + boolean demoDevice = in.readBoolean(); return new FullyManagedDeviceProvisioningParams( componentName, @@ -364,7 +398,8 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { localtime, locale, deviceOwnerCanGrantSensorsPermissions, - adminExtras); + adminExtras, + demoDevice); } @Override diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 434222ae80162..a7f749c6bfbfe 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2937,7 +2937,7 @@ @@ -2946,6 +2946,10 @@ + + + + diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 7178cbd460c03..5388f171854df 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -87,6 +87,7 @@ import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_UNKNOWN; import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_ERROR_FAILURE_SETTING; import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_NO_ERROR; import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER; +import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_FINALIZED; import static android.app.admin.DevicePolicyManager.STATE_USER_UNMANAGED; import static android.app.admin.DevicePolicyManager.STATUS_ACCOUNTS_NOT_EMPTY; import static android.app.admin.DevicePolicyManager.STATUS_CANNOT_ADD_MANAGED_PROFILE; @@ -9225,7 +9226,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // directly setting profile-owner or device-owner. if (getUserProvisioningState(userId) != DevicePolicyManager.STATE_USER_UNMANAGED - || newState != DevicePolicyManager.STATE_USER_SETUP_FINALIZED) { + || newState != STATE_USER_SETUP_FINALIZED) { throw new IllegalStateException("Not allowed to change provisioning state " + "unless current provisioning state is unmanaged, and new state" + "is finalized."); @@ -9259,7 +9260,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { case DevicePolicyManager.STATE_USER_SETUP_INCOMPLETE: case DevicePolicyManager.STATE_USER_SETUP_COMPLETE: // Can only move to finalized from these states. - if (newState == DevicePolicyManager.STATE_USER_SETUP_FINALIZED) { + if (newState == STATE_USER_SETUP_FINALIZED) { return; } break; @@ -9271,7 +9272,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } break; - case DevicePolicyManager.STATE_USER_SETUP_FINALIZED: + case STATE_USER_SETUP_FINALIZED: // Cannot transition out of finalized. break; case DevicePolicyManager.STATE_USER_PROFILE_FINALIZED: @@ -18092,7 +18093,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization( - hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); + hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) + || (hasCallingOrSelfPermission(permission.PROVISION_DEMO_DEVICE) + && provisioningParams.isDemoDevice())); provisioningParams.logParams(callerPackage); @@ -18129,8 +18132,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } disallowAddUser(); - setAdminCanGrantSensorsPermissionForUserUnchecked(deviceOwnerUserId, - provisioningParams.canDeviceOwnerGrantSensorsPermissions()); + setAdminCanGrantSensorsPermissionForUserUnchecked( + deviceOwnerUserId, provisioningParams.canDeviceOwnerGrantSensorsPermissions()); + setDemoDeviceStateUnchecked(deviceOwnerUserId, provisioningParams.isDemoDevice()); onProvisionFullyManagedDeviceCompleted(provisioningParams); sendProvisioningCompletedBroadcast( deviceOwnerUserId, @@ -18329,6 +18333,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + private void setDemoDeviceStateUnchecked(@UserIdInt int userId, boolean isDemoDevice) { + Slogf.d(LOG_TAG, "setDemoDeviceStateUnchecked(%d, %b)", + userId, isDemoDevice); + if (!isDemoDevice) { + return; + } + synchronized (getLockObject()) { + mInjector.settingsGlobalPutStringForUser( + Settings.Global.DEVICE_DEMO_MODE, Integer.toString(/* value= */ 1), userId); + } + setUserProvisioningState(STATE_USER_SETUP_FINALIZED, userId); + } + private void updateAdminCanGrantSensorsPermissionCache(@UserIdInt int userId) { synchronized (getLockObject()) {