From 895f3ba3f0cf1f9753efb38760ae21eb77558d6f Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Tue, 28 Sep 2021 17:51:34 -0700 Subject: [PATCH] Added a DevicePolicyManager.setDeviceOwnerOnly() method. It will be used by the test infra to just set the device owner, without setting the profile owner on current user on systems using headless system user. Test: atest com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerSetup Test: adb shell dpm set-device-owner --user 0 --device-owner-only com.afwsamples.testdpc/.DeviceAdminReceiver Test: m update-api Fixes: 201313785 Bug: 192395248 Change-Id: I41c2cf187c1eceebe7c6ef30f9cff693b9dcbc15 --- core/api/test-current.txt | 1 + .../app/admin/DevicePolicyManager.java | 57 +++++++++++++++---- .../app/admin/IDevicePolicyManager.aidl | 2 +- .../DevicePolicyManagerService.java | 9 ++- ...evicePolicyManagerServiceShellCommand.java | 11 +++- 5 files changed, 63 insertions(+), 17 deletions(-) diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 2ecf088fb5d06..9bedbddb48a5b 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -448,6 +448,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 b1364b500d4ae..d14eb1a29f584 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 6b4b0c94f657e..9b98ff98e1045 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8353,7 +8353,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); @@ -8416,7 +8417,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Slogf.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId); - if (mInjector.userManagerIsHeadlessSystemUserMode()) { + if (setProfileOwnerOnCurrentUserIfNecessary + && mInjector.userManagerIsHeadlessSystemUserMode()) { int currentForegroundUser = getCurrentForegroundUserId(); Slogf.i(LOG_TAG, "setDeviceOwner(): setting " + admin + " as profile owner on user " + currentForegroundUser); @@ -17426,7 +17428,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 | current ] \n", CMD_SET_ACTIVE_ADMIN, USER_OPTION); pw.printf(" Sets the given component as active admin for an existing user.\n\n"); - pw.printf(" %s [ %s | current *EXPERIMENTAL* ] [ %s ] " - + "\n", CMD_SET_DEVICE_OWNER, USER_OPTION, NAME_OPTION); + pw.printf(" %s [ %s | current *EXPERIMENTAL* ] [ %s ] [ %s ]" + + "\n", CMD_SET_DEVICE_OWNER, USER_OPTION, NAME_OPTION, DO_ONLY_OPTION); pw.printf(" Sets the given component as active admin, and its package as device owner." + "\n\n"); pw.printf(" %s [ %s | current ] [ %s ] \n", @@ -254,7 +256,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand { mService.setActiveAdmin(mComponent, /* refreshing= */ true, mUserId); try { - if (!mService.setDeviceOwner(mComponent, mName, mUserId)) { + if (!mService.setDeviceOwner(mComponent, mName, mUserId, + /* setProfileOwnerOnCurrentUserIfNecessary= */ !mSetDoOnly)) { throw new RuntimeException( "Can't set package " + mComponent + " as device owner."); } @@ -351,6 +354,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand { if (mUserId == UserHandle.USER_CURRENT) { mUserId = ActivityManager.getCurrentUser(); } + } else if (DO_ONLY_OPTION.equals(opt)) { + mSetDoOnly = true; } else if (canHaveName && NAME_OPTION.equals(opt)) { mName = getNextArgRequired(); } else {