diff --git a/core/api/test-current.txt b/core/api/test-current.txt index e8b91fe1e07e2..b798bbae854f1 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -454,6 +454,7 @@ package android.app.admin { method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void resetDefaultCrossProfileIntentFilters(int); method @RequiresPermission(allOf={"android.permission.MANAGE_DEVICE_ADMINS", android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int); method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public boolean setDeviceOwner(@NonNull android.content.ComponentName, @Nullable String, int); + method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, @Nullable String, int); method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, int); field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final String ACTION_DEVICE_POLICY_CONSTANTS_CHANGED = "android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED"; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 12444ab9ab091..d8fe2e616485e 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -7726,27 +7726,64 @@ public class DevicePolicyManager { } /** - * @hide - * Sets the given package as the device owner. The package must already be installed. There - * must not already be a device owner. - * Only apps with the MANAGE_PROFILE_AND_DEVICE_OWNERS permission and the shell uid can call - * this method. - * Calling this after the setup phase of the primary user has completed is allowed only if - * the caller is the shell uid, and there are no additional users and no accounts. + * Sets the given package as the device owner. + * + *
Preconditions: + *
Calling this after the setup phase of the device owner user has completed is allowed only
+ * if the caller is the {@link Process#SHELL_UID Shell UID}, and there are no additional users
+ * (except when the device runs on headless system user mode, in which case it could have exact
+ * one extra user, which is the current user - the device owner will be set in the
+ * {@link UserHandle#SYSTEM system} user and a profile owner will be set in the current user)
+ * and no accounts.
+ *
* @param who the component name to be registered as device owner.
* @param ownerName the human readable name of the institution that owns this device.
* @param userId ID of the user on which the device owner runs.
+ *
* @return whether the package was successfully registered as the device owner.
- * @throws IllegalArgumentException if the package name is null or invalid
+ *
+ * @throws IllegalArgumentException if the package name is {@code null} or invalid.
* @throws IllegalStateException If the preconditions mentioned are not met.
+ *
+ * @hide
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
- public boolean setDeviceOwner(
+ public boolean setDeviceOwner(@NonNull ComponentName who, @Nullable String ownerName,
+ @UserIdInt int userId) {
+ if (mService != null) {
+ try {
+ return mService.setDeviceOwner(who, ownerName, userId,
+ /* setProfileOwnerOnCurrentUserIfNecessary= */ true);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Same as {@link #setDeviceOwner(ComponentName, String, int)}, but without setting the profile
+ * owner on current user when running on headless system user mode - should be used only by
+ * testing infra.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ public boolean setDeviceOwnerOnly(
@NonNull ComponentName who, @Nullable String ownerName, @UserIdInt int userId) {
if (mService != null) {
try {
- return mService.setDeviceOwner(who, ownerName, userId);
+ return mService.setDeviceOwner(who, ownerName, userId,
+ /* setProfileOwnerOnCurrentUserIfNecessary= */ false);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7e7e80e1c6cdc..ffe2b39a25b72 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -159,7 +159,7 @@ interface IDevicePolicyManager {
void reportKeyguardDismissed(int userHandle);
void reportKeyguardSecured(int userHandle);
- boolean setDeviceOwner(in ComponentName who, String ownerName, int userId);
+ boolean setDeviceOwner(in ComponentName who, String ownerName, int userId, boolean setProfileOwnerOnCurrentUserIfNecessary);
ComponentName getDeviceOwnerComponent(boolean callingUserOnly);
boolean hasDeviceOwner();
String getDeviceOwnerName();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8814e231e54b2..bb2d746e6c87f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8356,7 +8356,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId) {
+ public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId,
+ boolean setProfileOwnerOnCurrentUserIfNecessary) {
if (!mHasFeature) {
logMissingFeatureAction("Cannot set " + ComponentName.flattenToShortString(admin)
+ " as device owner for user " + userId);
@@ -8420,7 +8421,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Slogf.i(LOG_TAG, "Device owner set: %s on user %d", admin.flattenToShortString(),
userId);
- if (mInjector.userManagerIsHeadlessSystemUserMode()) {
+ if (setProfileOwnerOnCurrentUserIfNecessary
+ && mInjector.userManagerIsHeadlessSystemUserMode()) {
int currentForegroundUser = getCurrentForegroundUserId();
Slogf.i(LOG_TAG, "setDeviceOwner(): setting %s as profile owner on user %d",
admin.flattenToShortString(), currentForegroundUser);
@@ -17433,7 +17435,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// TODO(b/178187130): Directly set DO and remove the check once silent provisioning is no
// longer used.
if (getDeviceOwnerComponent(/* callingUserOnly= */ true) == null) {
- return setDeviceOwner(adminComponent, name, userId);
+ return setDeviceOwner(adminComponent, name, userId,
+ /* setProfileOwnerOnCurrentUserIfNecessary= */ true);
}
return true;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
index 85fe65ca55635..e1d720ca25c86 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
@@ -46,11 +46,13 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
private static final String USER_OPTION = "--user";
private static final String NAME_OPTION = "--name";
+ private static final String DO_ONLY_OPTION = "--device-owner-only";
private final DevicePolicyManagerService mService;
private int mUserId = UserHandle.USER_SYSTEM;
private String mName = "";
private ComponentName mComponent;
+ private boolean mSetDoOnly;
DevicePolicyManagerServiceShellCommand(DevicePolicyManagerService service) {
mService = Objects.requireNonNull(service);
@@ -130,8 +132,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
pw.printf(" %s [ %s