From ec6c3d35db0234b8316147683eab0fd6352b06d6 Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Mon, 9 Mar 2020 16:19:36 +0000 Subject: [PATCH] Changed how user restrictions are pushed to UM * Sort the user restrictions to local restriction set and global bundle in DPMS instead of User Manager. * Simplify pushUserRestrictions. * Split the list of user restrictions the profile owner of an organization-owned device can set into a global and local list. The user restrictions in the local list will only be applied to the personal profile as opposed to the whole device. Bug: 149743941 148453838 Test: atest com.android.cts.devicepolicy.UserRestrictionsTest atest com.android.server.devicepolicy.DevicePolicyManagerTest atest com.android.server.pm.UserRestrictionsUtilsTest atest com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testUserRestrictionSetOnParentLogged atest com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testUserRestrictionsSetOnParentAreNotPersisted Change-Id: I1faa1f4776deb98e38595a358c01c3fbabfb1840 --- .../java/android/os/UserManagerInternal.java | 25 ++- .../android/server/pm/UserManagerService.java | 27 +-- .../server/pm/UserRestrictionsUtils.java | 42 ++-- .../DevicePolicyManagerService.java | 187 ++++++++++-------- .../devicepolicy/DevicePolicyManagerTest.java | 101 +++++----- .../server/devicepolicy/MockUtils.java | 53 ++++- .../server/pm/UserRestrictionsUtilsTest.java | 130 ------------ 7 files changed, 242 insertions(+), 323 deletions(-) diff --git a/services/core/java/android/os/UserManagerInternal.java b/services/core/java/android/os/UserManagerInternal.java index aedafbbf16622..94f5741fe8282 100644 --- a/services/core/java/android/os/UserManagerInternal.java +++ b/services/core/java/android/os/UserManagerInternal.java @@ -23,6 +23,8 @@ import android.content.Context; import android.content.pm.UserInfo; import android.graphics.Bitmap; +import com.android.server.pm.RestrictionsSet; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -57,21 +59,18 @@ public abstract class UserManagerInternal { * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to set * restrictions enforced by the user. * - * @param originatingUserId user id of the user where the restriction originated. - * @param restrictions a bundle of user restrictions. - * @param restrictionOwnerType determines which admin {@code userId} corresponds to. - * The admin can be either - * {@link UserManagerInternal#OWNER_TYPE_DEVICE_OWNER}, - * {@link UserManagerInternal#OWNER_TYPE_PROFILE_OWNER}, - * {@link UserManagerInternal#OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE} - * or {@link UserManagerInternal#OWNER_TYPE_NO_OWNER}. - * If the admin is a DEVICE_OWNER or a PROFILE_OWNER_ORG_OWNED_DEVICE then - * a restriction may be applied globally depending on which restriction it is, - * otherwise it will be applied just on the current user. - * @see OwnerType + * @param originatingUserId user id of the user where the restrictions originated. + * @param global a bundle of global user restrictions. Global restrictions are + * restrictions that apply device-wide: to the managed profile, + * primary profile and secondary users and any profile created in + * any secondary user. + * @param local a restriction set of local user restrictions. The key is the user + * id of the user whom the restrictions are targeting. + * @param isDeviceOwner whether {@code originatingUserId} corresponds to device owner + * user id. */ public abstract void setDevicePolicyUserRestrictions(int originatingUserId, - @Nullable Bundle restrictions, @OwnerType int restrictionOwnerType); + @Nullable Bundle global, @Nullable RestrictionsSet local, boolean isDeviceOwner); /** * Returns the "base" user restrictions. diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index ef8cad15290c7..23cd0118e3798 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1716,27 +1716,6 @@ public class UserManagerService extends IUserManager.Stub { } } - private void setDevicePolicyUserRestrictionsInner(@UserIdInt int originatingUserId, - @Nullable Bundle restrictions, - @UserManagerInternal.OwnerType int restrictionOwnerType) { - final Bundle global = new Bundle(); - final Bundle local = new Bundle(); - - // Sort restrictions into local and global ensuring they don't overlap. - UserRestrictionsUtils.sortToGlobalAndLocal(restrictions, restrictionOwnerType, global, - local); - boolean isDeviceOwner = restrictionOwnerType == UserManagerInternal.OWNER_TYPE_DEVICE_OWNER; - - RestrictionsSet localRestrictionsSet; - if (UserRestrictionsUtils.isEmpty(local)) { - localRestrictionsSet = new RestrictionsSet(); - } else { - localRestrictionsSet = new RestrictionsSet(originatingUserId, local); - } - setDevicePolicyUserRestrictionsInner(originatingUserId, global, localRestrictionsSet, - isDeviceOwner); - } - /** * See {@link UserManagerInternal#setDevicePolicyUserRestrictions} */ @@ -4752,10 +4731,10 @@ public class UserManagerService extends IUserManager.Stub { private class LocalService extends UserManagerInternal { @Override public void setDevicePolicyUserRestrictions(@UserIdInt int originatingUserId, - @Nullable Bundle restrictions, - @OwnerType int restrictionOwnerType) { + @NonNull Bundle global, @NonNull RestrictionsSet local, + boolean isDeviceOwner) { UserManagerService.this.setDevicePolicyUserRestrictionsInner(originatingUserId, - restrictions, restrictionOwnerType); + global, local, isDeviceOwner); } @Override diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index eec6e024fef27..c0502b8a068c2 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -232,6 +232,13 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_UNMUTE_MICROPHONE ); + /** + * Special user restrictions that profile owner of an organization-owned managed profile can + * set on the parent profile instance to apply them on the personal profile. + */ + private static final Set PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS = + Sets.newArraySet(); + /** * User restrictions that default to {@code true} for managed profile owners. * @@ -416,7 +423,8 @@ public class UserRestrictionsUtils { * @return true if a restriction is settable by profile owner of an organization owned device. */ public static boolean canProfileOwnerOfOrganizationOwnedDeviceChange(String restriction) { - return PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(restriction); + return PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(restriction) + || PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS.contains(restriction); } /** @@ -426,32 +434,10 @@ public class UserRestrictionsUtils { return DEFAULT_ENABLED_FOR_MANAGED_PROFILES; } - /** - * Takes restrictions that can be set by device owner, and sort them into what should be applied - * globally and what should be applied only on the current user. - */ - public static void sortToGlobalAndLocal(@Nullable Bundle in, - @UserManagerInternal.OwnerType int restrictionOwnerType, @NonNull Bundle global, - @NonNull Bundle local) { - if (in == null || in.size() == 0) { - return; - } - for (String key : in.keySet()) { - if (!in.getBoolean(key)) { - continue; - } - if (isGlobal(restrictionOwnerType, key)) { - global.putBoolean(key, true); - } else { - local.putBoolean(key, true); - } - } - } - /** * Whether given user restriction should be enforced globally. */ - private static boolean isGlobal(@UserManagerInternal.OwnerType int restrictionOwnerType, + public static boolean isGlobal(@UserManagerInternal.OwnerType int restrictionOwnerType, String key) { return ((restrictionOwnerType == UserManagerInternal.OWNER_TYPE_DEVICE_OWNER) && ( PRIMARY_USER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key))) @@ -462,6 +448,14 @@ public class UserRestrictionsUtils { || DEVICE_OWNER_ONLY_RESTRICTIONS.contains(key); } + /** + * Whether given user restriction should be enforced locally. + */ + public static boolean isLocal(@UserManagerInternal.OwnerType int restrictionOwnerType, + String key) { + return !isGlobal(restrictionOwnerType, key); + } + /** * @return true if two Bundles contain the same user restriction. * A null bundle and an empty bundle are considered to be equal. diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 1544ff1271210..a16f3cda17d42 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -87,6 +87,9 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; +import static android.os.UserManagerInternal.OWNER_TYPE_DEVICE_OWNER; +import static android.os.UserManagerInternal.OWNER_TYPE_PROFILE_OWNER; +import static android.os.UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE; import static android.provider.Settings.Global.PRIVATE_DNS_MODE; import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; import static android.provider.Telephony.Carriers.DPC_URI; @@ -284,6 +287,7 @@ import com.android.server.SystemService; import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.net.NetworkPolicyManagerInternal; +import com.android.server.pm.RestrictionsSet; import com.android.server.pm.UserRestrictionsUtils; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.storage.DeviceStorageMonitorInternal; @@ -322,6 +326,7 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; +import java.util.function.Predicate; /** * Implementation of the device policy APIs. @@ -1828,6 +1833,50 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { info = deviceAdminInfo; } + Bundle addSyntheticRestrictions(Bundle restrictions) { + if (disableCamera) { + restrictions.putBoolean(UserManager.DISALLOW_CAMERA, true); + } else { + restrictions.remove(UserManager.DISALLOW_CAMERA); + } + return restrictions; + } + + static Bundle removeDeprecatedRestrictions(Bundle restrictions) { + for (String deprecatedRestriction: DEPRECATED_USER_RESTRICTIONS) { + restrictions.remove(deprecatedRestriction); + } + return restrictions; + } + + static Bundle filterRestrictions(Bundle restrictions, Predicate filter) { + Bundle result = new Bundle(); + for (String key : restrictions.keySet()) { + if (!restrictions.getBoolean(key)) { + continue; + } + if (filter.test(key)) { + result.putBoolean(key, true); + } + } + return result; + } + + Bundle getEffectiveRestrictions() { + return addSyntheticRestrictions( + removeDeprecatedRestrictions(ensureUserRestrictions())); + } + + Bundle getLocalUserRestrictions(int adminType) { + return filterRestrictions(getEffectiveRestrictions(), + key -> UserRestrictionsUtils.isLocal(adminType, key)); + } + + Bundle getGlobalUserRestrictions(int adminType) { + return filterRestrictions(getEffectiveRestrictions(), + key -> UserRestrictionsUtils.isGlobal(adminType, key)); + } + void dump(IndentingPrintWriter pw) { pw.print("uid="); pw.println(getUid()); pw.print("testOnlyAdmin="); @@ -2772,7 +2821,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId) != 0) { profileOwner.ensureUserRestrictions().putBoolean( UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true); - saveUserRestrictionsLocked(userId, /* parent = */ false); + saveUserRestrictionsLocked(userId); mInjector.settingsSecurePutIntForUser( Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId); } @@ -2803,7 +2852,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } admin.defaultEnabledRestrictionsAlreadySet.addAll(restrictionsToSet); Slog.i(LOG_TAG, "Enabled the following restrictions by default: " + restrictionsToSet); - saveUserRestrictionsLocked(userId, /* parent = */ false); + saveUserRestrictionsLocked(userId); } } @@ -8222,9 +8271,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } // Tell the user manager that the restrictions have changed. - final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; - pushUserRestrictions(affectedUserId); + pushUserRestrictions(userHandle); + final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; if (SecurityLog.isLoggingEnabled()) { SecurityLog.writeEvent(SecurityLog.TAG_CAMERA_POLICY_SET, who.getPackageName(), userHandle, affectedUserId, disabled ? 1 : 0); @@ -10781,10 +10830,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { "Cannot use the parent instance in Device Owner mode"); } } else { - if (!(UserRestrictionsUtils.canProfileOwnerChange(key, userHandle) || ( - isProfileOwnerOfOrganizationOwnedDevice(activeAdmin) && parent - && UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange( - key)))) { + boolean profileOwnerCanChangeOnItself = !parent + && UserRestrictionsUtils.canProfileOwnerChange(key, userHandle); + boolean orgOwnedProfileOwnerCanChangesGlobally = parent + && isProfileOwnerOfOrganizationOwnedDevice(activeAdmin) + && UserRestrictionsUtils + .canProfileOwnerOfOrganizationOwnedDeviceChange(key); + + if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangesGlobally) { throw new SecurityException("Profile owner cannot set user restriction " + key); } } @@ -10796,7 +10849,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } else { restrictions.remove(key); } - saveUserRestrictionsLocked(userHandle, parent); + saveUserRestrictionsLocked(userHandle); } final int eventId = enabledFromThisOwner ? DevicePolicyEnums.ADD_USER_RESTRICTION @@ -10814,91 +10867,65 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private void saveUserRestrictionsLocked(int userId, boolean parent) { + private void saveUserRestrictionsLocked(int userId) { saveSettingsLocked(userId); - pushUserRestrictions(parent ? getProfileParentId(userId) : userId); + pushUserRestrictions(userId); sendChangedNotification(userId); } - private void pushUserRestrictions(int userId) { + /** + * Pushes the user restrictions originating from a specific user. + * + * If called by the profile owner of an organization-owned device, the global and local + * user restrictions will be an accumulation of the global user restrictions from the profile + * owner active admin and its parent active admin. The key of the local user restrictions set + * will be the target user id. + */ + private void pushUserRestrictions(int originatingUserId) { + final Bundle global; + final RestrictionsSet local = new RestrictionsSet(); + final boolean isDeviceOwner; synchronized (getLockObject()) { - final boolean isDeviceOwner = mOwners.isDeviceOwnerUserId(userId); - Bundle userRestrictions = null; - final int restrictionOwnerType; - final int originatingUserId; - + isDeviceOwner = mOwners.isDeviceOwnerUserId(originatingUserId); if (isDeviceOwner) { final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); if (deviceOwner == null) { return; // Shouldn't happen. } - userRestrictions = addOrRemoveDisableCameraRestriction( - deviceOwner.userRestrictions, deviceOwner); - restrictionOwnerType = UserManagerInternal.OWNER_TYPE_DEVICE_OWNER; - originatingUserId = deviceOwner.getUserHandle().getIdentifier(); + global = deviceOwner.getGlobalUserRestrictions(OWNER_TYPE_DEVICE_OWNER); + local.updateRestrictions(originatingUserId, deviceOwner.getLocalUserRestrictions( + OWNER_TYPE_DEVICE_OWNER)); } else { - final ActiveAdmin profileOwnerOfOrganizationOwnedDevice = - getProfileOwnerOfOrganizationOwnedDeviceLocked(userId); - - // If profile owner of an organization owned device, the restrictions will be - // pushed to the parent instance. - if (profileOwnerOfOrganizationOwnedDevice != null && !isManagedProfile(userId)) { - restrictionOwnerType = - UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE; - final ActiveAdmin parent = profileOwnerOfOrganizationOwnedDevice - .getParentActiveAdmin(); - userRestrictions = parent.userRestrictions; - userRestrictions = addOrRemoveDisableCameraRestriction(userRestrictions, - parent); - originatingUserId = - profileOwnerOfOrganizationOwnedDevice.getUserHandle().getIdentifier(); - } else { - final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId); - - if (profileOwner != null) { - userRestrictions = profileOwner.userRestrictions; - restrictionOwnerType = UserManagerInternal.OWNER_TYPE_PROFILE_OWNER; - originatingUserId = profileOwner.getUserHandle().getIdentifier(); - } else { - restrictionOwnerType = UserManagerInternal.OWNER_TYPE_NO_OWNER; - originatingUserId = userId; - } - userRestrictions = addOrRemoveDisableCameraRestriction( - userRestrictions, userId); + final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(originatingUserId); + if (profileOwner == null) { + return; + } + global = profileOwner.getGlobalUserRestrictions(OWNER_TYPE_PROFILE_OWNER); + local.updateRestrictions(originatingUserId, profileOwner.getLocalUserRestrictions( + OWNER_TYPE_PROFILE_OWNER)); + // Global (device-wide) and local user restrictions set by the profile owner of an + // organization-owned device are stored in the parent ActiveAdmin instance. + if (isProfileOwnerOfOrganizationOwnedDevice( + profileOwner.getUserHandle().getIdentifier())) { + // The global restrictions set on the parent ActiveAdmin instance need to be + // merged with the global restrictions set on the profile owner ActiveAdmin + // instance, since both are to be applied device-wide. + UserRestrictionsUtils.merge(global, + profileOwner.getParentActiveAdmin().getGlobalUserRestrictions( + OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); + // The local restrictions set on the parent ActiveAdmin instance are only to be + // applied to the primary user. They therefore need to be added the local + // restriction set with the primary user id as the key, in this case the + // primary user id is the target user. + local.updateRestrictions( + getProfileParentId(profileOwner.getUserHandle().getIdentifier()), + profileOwner.getParentActiveAdmin().getLocalUserRestrictions( + OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); } } - // Remove deprecated restrictions. - for (String deprecatedRestriction: DEPRECATED_USER_RESTRICTIONS) { - userRestrictions.remove(deprecatedRestriction); - } - mUserManagerInternal.setDevicePolicyUserRestrictions(originatingUserId, - userRestrictions, restrictionOwnerType); } - } - - private Bundle addOrRemoveDisableCameraRestriction(Bundle userRestrictions, ActiveAdmin admin) { - if (userRestrictions == null) { - userRestrictions = new Bundle(); - } - if (admin.disableCamera) { - userRestrictions.putBoolean(UserManager.DISALLOW_CAMERA, true); - } else { - userRestrictions.remove(UserManager.DISALLOW_CAMERA); - } - return userRestrictions; - } - - private Bundle addOrRemoveDisableCameraRestriction(Bundle userRestrictions, int userId) { - if (userRestrictions == null) { - userRestrictions = new Bundle(); - } - if (getCameraDisabled(/* who= */ null, userId, /* mergeDeviceOwnerRestriction= */ - false)) { - userRestrictions.putBoolean(UserManager.DISALLOW_CAMERA, true); - } else { - userRestrictions.remove(UserManager.DISALLOW_CAMERA); - } - return userRestrictions; + mUserManagerInternal.setDevicePolicyUserRestrictions(originatingUserId, global, local, + isDeviceOwner); } @Override diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index baf551e756e80..01dfbd78be879 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -83,7 +83,6 @@ import android.os.Bundle; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; -import android.os.UserManagerInternal; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.security.KeyChain; @@ -1170,7 +1169,6 @@ public class DevicePolicyManagerTest extends DpmTestBase { () -> dpm.clearDeviceOwnerApp(admin1.getPackageName())); when(getServices().userManager.isUserUnlocked(anyInt())).thenReturn(true); - reset(getServices().userManagerInternal); dpm.clearDeviceOwnerApp(admin1.getPackageName()); // Now DO shouldn't be set. @@ -1181,9 +1179,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { MockUtils.checkUserHandle(UserHandle.USER_SYSTEM)); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( - eq(UserHandle.USER_SYSTEM), - MockUtils.checkUserRestrictions(), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(), + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, UserHandle.USER_SYSTEM); @@ -1745,15 +1742,16 @@ public class DevicePolicyManagerTest extends DpmTestBase { verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true)); reset(getServices().userManagerInternal); dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(UserHandle.USER_SYSTEM), - MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS, - UserManager.DISALLOW_ADD_USER), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER), + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM, + UserManager.DISALLOW_OUTGOING_CALLS), + eq(true)); reset(getServices().userManagerInternal); DpmTestUtils.assertRestrictions( @@ -1770,8 +1768,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.clearUserRestriction(admin1, UserManager.DISALLOW_ADD_USER); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(UserHandle.USER_SYSTEM), - MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + MockUtils.checkUserRestrictions(), + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM, + UserManager.DISALLOW_OUTGOING_CALLS), + eq(true)); reset(getServices().userManagerInternal); DpmTestUtils.assertRestrictions( @@ -1787,7 +1787,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true)); reset(getServices().userManagerInternal); assertNoDeviceOwnerRestrictions(); @@ -1801,7 +1801,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME, UserManager.DISALLOW_UNMUTE_MICROPHONE), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true)); reset(getServices().userManagerInternal); dpm.clearUserRestriction(admin1, UserManager.DISALLOW_ADJUST_VOLUME); @@ -1813,7 +1813,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true)); reset(getServices().userManagerInternal); dpm.addUserRestriction(admin1, UserManager.DISALLOW_FUN); @@ -1821,7 +1821,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN, UserManager.DISALLOW_ADD_USER), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true)); reset(getServices().userManagerInternal); dpm.setCameraDisabled(admin1, true); @@ -1830,7 +1830,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { // DISALLOW_CAMERA will be applied globally. MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN, UserManager.DISALLOW_ADD_USER, UserManager.DISALLOW_CAMERA), - eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)); + MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true)); reset(getServices().userManagerInternal); } @@ -1887,17 +1887,19 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.addUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), - MockUtils.checkUserRestrictions(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER)); - reset(getServices().userManagerInternal); + MockUtils.checkUserRestrictions(), + MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE, + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES), + eq(false)); dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), - MockUtils.checkUserRestrictions(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, + MockUtils.checkUserRestrictions(), + MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE, + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserManager.DISALLOW_OUTGOING_CALLS), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER)); - reset(getServices().userManagerInternal); + eq(false)); DpmTestUtils.assertRestrictions( DpmTestUtils.newRestrictions( @@ -1918,9 +1920,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.clearUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), - MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER)); - reset(getServices().userManagerInternal); + MockUtils.checkUserRestrictions(), + MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE, + UserManager.DISALLOW_OUTGOING_CALLS), + eq(false)); DpmTestUtils.assertRestrictions( DpmTestUtils.newRestrictions( @@ -1940,8 +1943,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), MockUtils.checkUserRestrictions(), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER)); - reset(getServices().userManagerInternal); + MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE), eq(false)); DpmTestUtils.assertRestrictions( DpmTestUtils.newRestrictions(), @@ -1956,21 +1958,25 @@ public class DevicePolicyManagerTest extends DpmTestBase { // DISALLOW_ADJUST_VOLUME and DISALLOW_UNMUTE_MICROPHONE can be set by PO too, even // though when DO sets them they'll be applied globally. dpm.addUserRestriction(admin1, UserManager.DISALLOW_ADJUST_VOLUME); - reset(getServices().userManagerInternal); + dpm.addUserRestriction(admin1, UserManager.DISALLOW_UNMUTE_MICROPHONE); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), - MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME, + MockUtils.checkUserRestrictions(), + MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE, + UserManager.DISALLOW_ADJUST_VOLUME, UserManager.DISALLOW_UNMUTE_MICROPHONE), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER)); - reset(getServices().userManagerInternal); + eq(false)); dpm.setCameraDisabled(admin1, true); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), - MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME, - UserManager.DISALLOW_UNMUTE_MICROPHONE, UserManager.DISALLOW_CAMERA), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER)); + MockUtils.checkUserRestrictions(), + MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE, + UserManager.DISALLOW_ADJUST_VOLUME, + UserManager.DISALLOW_UNMUTE_MICROPHONE, + UserManager.DISALLOW_CAMERA), + eq(false)); reset(getServices().userManagerInternal); // TODO Make sure restrictions are written to the file. @@ -2004,15 +2010,14 @@ public class DevicePolicyManagerTest extends DpmTestBase { ); public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception { - final int MANAGED_PROFILE_USER_ID = DpmMockContext.CALLER_USER_HANDLE; final int MANAGED_PROFILE_ADMIN_UID = - UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID); + UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); - when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID)) + when(getServices().userManager.getProfileParent(DpmMockContext.CALLER_USER_HANDLE)) .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0)); for (String restriction : PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS) { @@ -2021,16 +2026,20 @@ public class DevicePolicyManagerTest extends DpmTestBase { parentDpm.setCameraDisabled(admin1, true); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( - eq(MANAGED_PROFILE_USER_ID), + eq(DpmMockContext.CALLER_USER_HANDLE), MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); - reset(getServices().userManagerInternal); + MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE), + eq(false)); + DpmTestUtils.assertRestrictions( + DpmTestUtils.newRestrictions(UserManager.DISALLOW_CAMERA), + parentDpm.getUserRestrictions(admin1) + ); parentDpm.setCameraDisabled(admin1, false); - verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( - eq(MANAGED_PROFILE_USER_ID), - MockUtils.checkUserRestrictions(), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); + DpmTestUtils.assertRestrictions( + DpmTestUtils.newRestrictions(), + parentDpm.getUserRestrictions(admin1) + ); reset(getServices().userManagerInternal); } @@ -2039,13 +2048,13 @@ public class DevicePolicyManagerTest extends DpmTestBase { verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), MockUtils.checkUserRestrictions(restriction), - eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); + MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE), + eq(false)); parentDpm.clearUserRestriction(admin1, restriction); DpmTestUtils.assertRestrictions( DpmTestUtils.newRestrictions(), parentDpm.getUserRestrictions(admin1) ); - reset(getServices().userManagerInternal); } public void testNoDefaultEnabledUserRestrictions() throws Exception { diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java index 09a681913e459..15f3ed1be552e 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java @@ -15,10 +15,6 @@ */ package com.android.server.devicepolicy; -import com.google.common.base.Objects; - -import com.android.server.pm.UserRestrictionsUtils; - import android.content.ComponentName; import android.content.Intent; import android.os.BaseBundle; @@ -26,6 +22,11 @@ import android.os.Bundle; import android.os.UserHandle; import android.util.ArraySet; +import com.android.server.pm.RestrictionsSet; +import com.android.server.pm.UserRestrictionsUtils; + +import com.google.common.base.Objects; + import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; @@ -106,11 +107,14 @@ public class MockUtils { } public static Bundle checkUserRestrictions(String... keys) { - final Bundle expected = DpmTestUtils.newRestrictions(java.util.Objects.requireNonNull(keys)); + final Bundle expected = DpmTestUtils.newRestrictions( + java.util.Objects.requireNonNull(keys)); final Matcher m = new BaseMatcher() { @Override public boolean matches(Object item) { - if (item == null) return false; + if (item == null) { + return false; + } return UserRestrictionsUtils.areEqual((Bundle) item, expected); } @@ -122,6 +126,26 @@ public class MockUtils { return MockitoHamcrest.argThat(m); } + public static RestrictionsSet checkUserRestrictions(int userId, String... keys) { + final RestrictionsSet expected = DpmTestUtils.newRestrictions(userId, + java.util.Objects.requireNonNull(keys)); + final Matcher m = new BaseMatcher() { + @Override + public boolean matches(Object item) { + if (item == null) return false; + RestrictionsSet actual = (RestrictionsSet) item; + return UserRestrictionsUtils.areEqual(expected.getRestrictions(userId), + actual.getRestrictions(userId)); + } + + @Override + public void describeTo(Description description) { + description.appendText("User restrictions=" + getRestrictionsAsString(expected)); + } + }; + return MockitoHamcrest.argThat(m); + } + public static Set checkApps(String... adminApps) { final Matcher> m = new BaseMatcher>() { @Override @@ -146,6 +170,23 @@ public class MockUtils { return MockitoHamcrest.argThat(m); } + private static String getRestrictionsAsString(RestrictionsSet r) { + final StringBuilder sb = new StringBuilder(); + sb.append("{"); + + if (r != null) { + String sep = ""; + for (int i = 0; i < r.size(); i++) { + sb.append(sep); + sep = ","; + sb.append( + String.format("%s= %s", r.keyAt(i), getRestrictionsAsString(r.valueAt(i)))); + } + } + sb.append("}"); + return sb.toString(); + } + private static String getRestrictionsAsString(Bundle b) { final StringBuilder sb = new StringBuilder(); sb.append("["); diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java index 1c2313e3e32f2..dc181a959d836 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java @@ -22,7 +22,6 @@ import static com.android.server.devicepolicy.DpmTestUtils.newRestrictions; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; -import android.os.UserManagerInternal; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.util.SparseArray; @@ -118,135 +117,6 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase { UserManager.DISALLOW_ADJUST_VOLUME, user)); } - public void testSortToGlobalAndLocal() { - final Bundle local = new Bundle(); - final Bundle global = new Bundle(); - - UserRestrictionsUtils.sortToGlobalAndLocal(null, - UserManagerInternal.OWNER_TYPE_PROFILE_OWNER, - global, local); - assertEquals(0, global.size()); - assertEquals(0, local.size()); - - UserRestrictionsUtils.sortToGlobalAndLocal(Bundle.EMPTY, - UserManagerInternal.OWNER_TYPE_PROFILE_OWNER, - global, local); - assertEquals(0, global.size()); - assertEquals(0, local.size()); - - // Restrictions set by DO. - UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions( - UserManager.DISALLOW_ADJUST_VOLUME, - UserManager.DISALLOW_UNMUTE_MICROPHONE, - UserManager.DISALLOW_USB_FILE_TRANSFER, - UserManager.DISALLOW_CONFIG_TETHERING, - UserManager.DISALLOW_OUTGOING_BEAM, - UserManager.DISALLOW_APPS_CONTROL, - UserManager.ENSURE_VERIFY_APPS, - UserManager.DISALLOW_CAMERA - ), UserManagerInternal.OWNER_TYPE_DEVICE_OWNER, - global, local); - - - assertRestrictions(newRestrictions( - // This one is global no matter who sets it. - UserManager.ENSURE_VERIFY_APPS, - - // These can be set by PO too, but when DO sets them, they're global. - UserManager.DISALLOW_ADJUST_VOLUME, - UserManager.DISALLOW_UNMUTE_MICROPHONE, - - // These can only be set by DO. - UserManager.DISALLOW_USB_FILE_TRANSFER, - UserManager.DISALLOW_CONFIG_TETHERING, - - // This can be set by DO or PO of organisation owned device - UserManager.DISALLOW_CAMERA - ), global); - - assertRestrictions(newRestrictions( - // They can be set by both DO/PO. - UserManager.DISALLOW_OUTGOING_BEAM, - UserManager.DISALLOW_APPS_CONTROL - ), local); - - local.clear(); - global.clear(); - - // Restrictions set by PO. - UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions( - UserManager.DISALLOW_ADJUST_VOLUME, - UserManager.DISALLOW_UNMUTE_MICROPHONE, - UserManager.DISALLOW_USB_FILE_TRANSFER, - UserManager.DISALLOW_CONFIG_TETHERING, - UserManager.DISALLOW_OUTGOING_BEAM, - UserManager.DISALLOW_APPS_CONTROL, - UserManager.ENSURE_VERIFY_APPS, - UserManager.DISALLOW_CAMERA - ), UserManagerInternal.OWNER_TYPE_PROFILE_OWNER, - global, local); - - assertRestrictions(newRestrictions( - // This one is global no matter who sets it. - UserManager.ENSURE_VERIFY_APPS - ), global); - - assertRestrictions(newRestrictions( - // These can be set by PO too, but when PO sets them, they're local. - UserManager.DISALLOW_ADJUST_VOLUME, - UserManager.DISALLOW_UNMUTE_MICROPHONE, - - // They can be set by both DO/PO. - UserManager.DISALLOW_OUTGOING_BEAM, - UserManager.DISALLOW_APPS_CONTROL, - - // These can only be set by DO. - UserManager.DISALLOW_USB_FILE_TRANSFER, - UserManager.DISALLOW_CONFIG_TETHERING, - - // This can be set by DO or PO of organisation owned device - UserManager.DISALLOW_CAMERA - ), local); - - local.clear(); - global.clear(); - - // Restrictions set by PO of organisation owned device - UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions( - UserManager.DISALLOW_CONFIG_DATE_TIME - ), UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE, - global, local); - - assertRestrictions(newRestrictions( - // This user restriction is global when set by PO of org owned device - UserManager.DISALLOW_CONFIG_DATE_TIME - ), global); - assertEquals(0, local.size()); - } - - public void testSortToLocalAndGlobalWithCameraDisabled() { - final Bundle local = new Bundle(); - final Bundle global = new Bundle(); - - UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(UserManager.DISALLOW_CAMERA), - UserManagerInternal.OWNER_TYPE_DEVICE_OWNER, global, local); - assertRestrictions(newRestrictions(UserManager.DISALLOW_CAMERA), global); - assertEquals(0, local.size()); - global.clear(); - - UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(UserManager.DISALLOW_CAMERA), - UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE, global, - local); - assertRestrictions(newRestrictions(UserManager.DISALLOW_CAMERA), global); - assertEquals(0, local.size()); - global.clear(); - - UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(UserManager.DISALLOW_CAMERA), - UserManagerInternal.OWNER_TYPE_PROFILE_OWNER, global, local); - assertEquals(0, global.size()); - assertRestrictions(newRestrictions(UserManager.DISALLOW_CAMERA), local); - } - public void testMoveRestriction() { SparseArray localRestrictions = new SparseArray<>(); RestrictionsSet globalRestrictions = new RestrictionsSet();