Loading core/java/android/app/admin/DevicePolicyManager.java +21 −6 Original line number Diff line number Diff line Loading @@ -5570,7 +5570,12 @@ public class DevicePolicyManager { * device, for this user. After setting this, no applications running as this user will be able * to access any cameras on the device. * <p> * If the caller is device owner, then the restriction will be applied to all users. * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be * the profile owner of an organization-owned managed profile. * <p> * If the caller is device owner or called on the parent instance, then the * restriction will be applied to all users. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call this method; if it has Loading @@ -5582,10 +5587,9 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}. */ public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) { throwIfParentInstance("setCameraDisabled"); if (mService != null) { try { mService.setCameraDisabled(admin, disabled); mService.setCameraDisabled(admin, disabled, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -5595,11 +5599,15 @@ public class DevicePolicyManager { /** * Determine whether or not the device's cameras have been disabled for this user, * either by the calling admin, if specified, or all admins. * <p> * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be * the profile owner of an organization-owned managed profile. * * @param admin The name of the admin component to check, or {@code null} to check whether any admins * have disabled the camera */ public boolean getCameraDisabled(@Nullable ComponentName admin) { throwIfParentInstance("getCameraDisabled"); return getCameraDisabled(admin, myUserId()); } Loading @@ -5608,7 +5616,7 @@ public class DevicePolicyManager { public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getCameraDisabled(admin, userHandle); return mService.getCameraDisabled(admin, userHandle, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -9359,7 +9367,6 @@ public class DevicePolicyManager { * <li>{@link #setPasswordExpirationTimeout}</li> * <li>{@link #getPasswordExpiration}</li> * <li>{@link #getPasswordMaximumLength}</li> * <li>{@link #getPasswordComplexity}</li> * <li>{@link #isActivePasswordSufficient}</li> * <li>{@link #getCurrentFailedPasswordAttempts}</li> * <li>{@link #getMaximumFailedPasswordsForWipe}</li> Loading @@ -9374,6 +9381,14 @@ public class DevicePolicyManager { * <li>{@link #getRequiredStrongAuthTimeout}</li> * <li>{@link #setRequiredStrongAuthTimeout}</li> * </ul> * <p> * The following methods are supported for the parent instance but can only be called by the * profile owner of a managed profile that was created during the device provisioning flow: * <ul> * <li>{@link #getPasswordComplexity}</li> * <li>{@link #setCameraDisabled}</li> * <li>{@link #getCameraDisabled}</li> * </ul> * * <p>The following methods can be called by the profile owner of a managed profile * on an organization-owned device: Loading core/java/android/app/admin/IDevicePolicyManager.aidl +2 −2 Original line number Diff line number Diff line Loading @@ -114,8 +114,8 @@ interface IDevicePolicyManager { boolean requestBugreport(in ComponentName who); void setCameraDisabled(in ComponentName who, boolean disabled); boolean getCameraDisabled(in ComponentName who, int userHandle); void setCameraDisabled(in ComponentName who, boolean disabled, boolean parent); boolean getCameraDisabled(in ComponentName who, int userHandle, boolean parent); void setScreenCaptureDisabled(in ComponentName who, boolean disabled); boolean getScreenCaptureDisabled(in ComponentName who, int userHandle); Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +103 −27 Original line number Diff line number Diff line Loading @@ -4345,6 +4345,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } /** * Get the list of active admins for an affected user: * <ul> * <li>The active admins associated with the userHandle itself</li> * <li>The parent active admins for each managed profile associated with the userHandle</li> * </ul> * * @param userHandle the affected user for whom to get the active admins * @param parent whether the parent active admins should be included in the list of active * admins or not * @return the list of active admins for the affected user */ private List<ActiveAdmin> getActiveAdminsForAffectedUser(int userHandle, boolean parent) { if (!parent) { return getUserDataUnchecked(userHandle).mAdminList; } ArrayList<ActiveAdmin> admins = new ArrayList<>(); for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) { DevicePolicyData policy = getUserData(userInfo.id); if (!userInfo.isManagedProfile()) { admins.addAll(policy.mAdminList); } else { // For managed profiles, policies set on the parent profile will be included for (int i = 0; i < policy.mAdminList.size(); i++) { ActiveAdmin admin = policy.mAdminList.get(i); if (admin.hasParentActiveAdmin()) { admins.add(admin.getParentActiveAdmin()); } } } } return admins; } private boolean isSeparateProfileChallengeEnabled(int userHandle) { long ident = mInjector.binderClearCallingIdentity(); try { Loading Loading @@ -7707,22 +7741,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * Disables all device cameras according to the specified admin. */ @Override public void setCameraDisabled(ComponentName who, boolean disabled) { public void setCameraDisabled(ComponentName who, boolean disabled, boolean parent) { if (!mHasFeature) { return; } Preconditions.checkNotNull(who, "ComponentName is null"); final int userHandle = mInjector.userHandleGetCallingUserId(); int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (getLockObject()) { ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA); DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA, parent); if (parent) { enforceProfileOwnerOfOrganizationOwnedDevice(ap); } if (ap.disableCamera != disabled) { ap.disableCamera = disabled; saveSettingsLocked(userHandle); } } // Tell the user manager that the restrictions have changed. pushUserRestrictions(userHandle); pushUserRestrictions(parent ? getProfileParentId(userHandle) : userHandle); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_CAMERA_DISABLED) .setAdmin(who) Loading @@ -7735,18 +7772,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * active admins. */ @Override public boolean getCameraDisabled(ComponentName who, int userHandle) { return getCameraDisabled(who, userHandle, /* mergeDeviceOwnerRestriction= */ true); public boolean getCameraDisabled(ComponentName who, int userHandle, boolean parent) { return getCameraDisabled(who, userHandle, /* mergeDeviceOwnerRestriction= */ true, parent); } private boolean getCameraDisabled(ComponentName who, int userHandle, boolean mergeDeviceOwnerRestriction) { boolean mergeDeviceOwnerRestriction, boolean parent) { if (!mHasFeature) { return false; } if (parent) { ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA, parent); enforceProfileOwnerOfOrganizationOwnedDevice(ap); } synchronized (getLockObject()) { if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); return (admin != null) ? admin.disableCamera : false; } // First, see if DO has set it. If so, it's device-wide. Loading @@ -7756,13 +7798,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return true; } } // Then check each device admin on the user. DevicePolicyData policy = getUserData(userHandle); // Return the strictest policy across all participating admins. List<ActiveAdmin> admins = getActiveAdminsForAffectedUser(userHandle, parent); // Determine whether or not the device camera is disabled for any active admins. final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { ActiveAdmin admin = policy.mAdminList.get(i); for (ActiveAdmin admin: admins) { if (admin.disableCamera) { return true; } Loading Loading @@ -8574,6 +8613,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } @GuardedBy("getLockObject()") ActiveAdmin getProfileOwnerOfOrganizationOwnedDeviceLocked(int userHandle) { final long ident = mInjector.binderClearCallingIdentity(); try { for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) { if (userInfo.isManagedProfile()) { if (getProfileOwner(userInfo.id) != null && canProfileOwnerAccessDeviceIds(userInfo.id)) { ComponentName who = getProfileOwner(userInfo.id); return getActiveAdminUncheckedLocked(who, userInfo.id); } } } } finally { mInjector.binderRestoreCallingIdentity(ident); } return null; } @Override public String getProfileOwnerName(int userHandle) { if (!mHasFeature) { Loading Loading @@ -10261,7 +10319,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private void pushUserRestrictions(int userId) { synchronized (getLockObject()) { final boolean isDeviceOwner = mOwners.isDeviceOwnerUserId(userId); final Bundle userRestrictions; Bundle userRestrictions = null; final int restrictionOwnerType; if (isDeviceOwner) { Loading @@ -10273,42 +10331,60 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { addOrRemoveDisableCameraRestriction(userRestrictions, deviceOwner); restrictionOwnerType = UserManagerInternal.OWNER_TYPE_DEVICE_OWNER; } else { final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId); userRestrictions = profileOwner != null ? profileOwner.userRestrictions : null; addOrRemoveDisableCameraRestriction(userRestrictions, userId); final ActiveAdmin profileOwnerOfOrganizationOwnedDevice = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId); if (isProfileOwnerOfOrganizationOwnedDevice(profileOwner)) { // 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; } else if (profileOwner != null) { final ActiveAdmin parent = profileOwnerOfOrganizationOwnedDevice .getParentActiveAdmin(); userRestrictions = parent.userRestrictions; userRestrictions = addOrRemoveDisableCameraRestriction(userRestrictions, parent); } else { final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId); if (profileOwner != null) { userRestrictions = profileOwner.userRestrictions; restrictionOwnerType = UserManagerInternal.OWNER_TYPE_PROFILE_OWNER; } else { restrictionOwnerType = UserManagerInternal.OWNER_TYPE_NO_OWNER; } userRestrictions = addOrRemoveDisableCameraRestriction( userRestrictions, userId); } } mUserManagerInternal.setDevicePolicyUserRestrictions(userId, userRestrictions, restrictionOwnerType); } } private void addOrRemoveDisableCameraRestriction(Bundle userRestrictions, ActiveAdmin admin) { if (userRestrictions == null) return; 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 void addOrRemoveDisableCameraRestriction(Bundle userRestrictions, int userId) { if (userRestrictions == null) return; 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; } @Override Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java +9 −5 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManagerInternal; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; Loading @@ -39,6 +38,9 @@ import java.util.Map; import java.util.Set; public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { private static final String USER_TYPE_EMPTY = ""; private DpmMockContext mContext; @Override Loading @@ -52,9 +54,10 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { } public void testMigration() throws Exception { final File user10dir = getServices().addUser(10, 0); final File user11dir = getServices().addUser(11, UserInfo.FLAG_MANAGED_PROFILE); getServices().addUser(12, 0); final File user10dir = getServices().addUser(10, 0, USER_TYPE_EMPTY); final File user11dir = getServices().addUser(11, 0, UserManager.USER_TYPE_PROFILE_MANAGED); getServices().addUser(12, 0, USER_TYPE_EMPTY); setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID); setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123)); Loading Loading @@ -273,7 +276,8 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { // Test setting default restrictions for managed profile. public void testMigration3_managedProfileOwner() throws Exception { // Create a managed profile user. final File user10dir = getServices().addUser(10, UserInfo.FLAG_MANAGED_PROFILE); final File user10dir = getServices().addUser(10, 0, UserManager.USER_TYPE_PROFILE_MANAGED); // Profile owner package for managed profile user. setUpPackageManagerForAdmin(admin1, UserHandle.getUid(10, 123)); // Set up fake UserManager to make it look like a managed profile. Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +34 −37 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { private DpmMockContext mServiceContext; private DpmMockContext mAdmin1Context; public DevicePolicyManager dpm; public DevicePolicyManager parentDpm; public DevicePolicyManagerServiceTestable dpms; /* Loading Loading @@ -240,6 +241,9 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm = new DevicePolicyManagerTestable(mContext, dpms); parentDpm = new DevicePolicyManagerTestable(mServiceContext, dpms, /* parentInstance= */true); mContext.binder.restoreCallingIdentity(ident); } Loading Loading @@ -269,7 +273,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { anyString(), any(UserHandle.class)); // Add the first secondary user. getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0); getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0, UserManager.USER_TYPE_FULL_SECONDARY); } private void setAsProfileOwner(ComponentName admin) { Loading Loading @@ -330,7 +335,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { public void testLoadAdminData_noAdmins() throws Exception { final int ANOTHER_USER_ID = 15; getServices().addUser(ANOTHER_USER_ID, 0); getServices().addUser(ANOTHER_USER_ID, 0, ""); initializeDpms(); Loading Loading @@ -477,7 +482,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { final int ANOTHER_USER_ID = 100; final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 20456); getServices().addUser(ANOTHER_USER_ID, 0); // Add one more user. getServices().addUser(ANOTHER_USER_ID, 0, ""); // Add one more user. // Set up pacakge manager for the other user. setUpPackageManagerForAdmin(admin2, ANOTHER_ADMIN_UID); Loading Loading @@ -1343,7 +1348,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { final int ANOTHER_USER_ID = 100; final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 456); getServices().addUser(ANOTHER_USER_ID, 0); // Add one more user. getServices().addUser(ANOTHER_USER_ID, 0, ""); // Add one more user. mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); mContext.callerPermissions.add(permission.MANAGE_USERS); Loading Loading @@ -1961,35 +1966,30 @@ public class DevicePolicyManagerTest extends DpmTestBase { // TODO Make sure restrictions are written to the file. } // TODO: (b/138709470) test addUserRestriction as PO of an organization-owned device public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception { setupProfileOwner(); 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); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; final long ident = mServiceContext.binder.clearCallingIdentity(); configureContextForAccess(mServiceContext, true); addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); mServiceContext.binder.callingUid = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, DpmMockContext.CALLER_MANAGED_PROVISIONING_UID); try { runAsCaller(mServiceContext, dpms, dpm -> { dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1); }); } finally { mServiceContext.binder.restoreCallingIdentity(ident); } when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID)) .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0)); dpm.addUserRestriction(admin1, UserManager.DISALLOW_CONFIG_DATE_TIME); parentDpm.setCameraDisabled(admin1, true); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), MockUtils.checkUserRestrictions(UserManager.DISALLOW_CONFIG_DATE_TIME), eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA), eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); reset(getServices().userManagerInternal); dpm.setCameraDisabled(admin1, true); parentDpm.setCameraDisabled(admin1, false); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), MockUtils.checkUserRestrictions(UserManager.DISALLOW_CONFIG_DATE_TIME, UserManager.DISALLOW_CAMERA), eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(), eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); reset(getServices().userManagerInternal); } Loading Loading @@ -3861,7 +3861,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { // Add a secondary user, it should never talk with. final int ANOTHER_USER_ID = 36; getServices().addUser(ANOTHER_USER_ID, 0); getServices().addUser(ANOTHER_USER_ID, 0, UserManager.USER_TYPE_FULL_SECONDARY); // Since the managed profile is not affiliated, they should not be allowed to talk to each // other. Loading Loading @@ -5206,8 +5206,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { } public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception { getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM); getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0, UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM); DpmTestUtils.writeInputStreamToFile( getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated), getProfileOwnerPoliciesFile()); Loading @@ -5218,8 +5218,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { } public void testRevertProfileOwnership_profileNotMigrated() throws Exception { getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM); getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0, UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM); DpmTestUtils.writeInputStreamToFile( getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated), getProfileOwnerPoliciesFile()); Loading @@ -5230,8 +5230,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { } public void testRevertProfileOwnership_adminAndProfileNotMigrated() throws Exception { getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM); getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0, UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM); DpmTestUtils.writeInputStreamToFile( getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_not_migrated), getProfileOwnerPoliciesFile()); Loading Loading @@ -5405,11 +5405,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { mServiceContext.permissions.add(permission.REQUEST_PASSWORD_COMPLEXITY); setAsProfileOwner(admin1); new DevicePolicyManagerTestable( mServiceContext, dpms, /* parentInstance= */ true) .getPasswordComplexity(); parentDpm.getPasswordComplexity(); assertEquals(PASSWORD_COMPLEXITY_NONE, dpm.getPasswordComplexity()); } Loading Loading @@ -5685,7 +5681,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { private void addManagedProfile( ComponentName admin, int adminUid, ComponentName copyFromAdmin) throws Exception { final int userId = UserHandle.getUserId(adminUid); getServices().addUser(userId, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM); getServices().addUser(userId, 0, UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM); mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS); setUpPackageManagerForFakeAdmin(admin, adminUid, copyFromAdmin); dpm.setActiveAdmin(admin, false, userId); Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +21 −6 Original line number Diff line number Diff line Loading @@ -5570,7 +5570,12 @@ public class DevicePolicyManager { * device, for this user. After setting this, no applications running as this user will be able * to access any cameras on the device. * <p> * If the caller is device owner, then the restriction will be applied to all users. * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be * the profile owner of an organization-owned managed profile. * <p> * If the caller is device owner or called on the parent instance, then the * restriction will be applied to all users. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call this method; if it has Loading @@ -5582,10 +5587,9 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}. */ public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) { throwIfParentInstance("setCameraDisabled"); if (mService != null) { try { mService.setCameraDisabled(admin, disabled); mService.setCameraDisabled(admin, disabled, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -5595,11 +5599,15 @@ public class DevicePolicyManager { /** * Determine whether or not the device's cameras have been disabled for this user, * either by the calling admin, if specified, or all admins. * <p> * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be * the profile owner of an organization-owned managed profile. * * @param admin The name of the admin component to check, or {@code null} to check whether any admins * have disabled the camera */ public boolean getCameraDisabled(@Nullable ComponentName admin) { throwIfParentInstance("getCameraDisabled"); return getCameraDisabled(admin, myUserId()); } Loading @@ -5608,7 +5616,7 @@ public class DevicePolicyManager { public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getCameraDisabled(admin, userHandle); return mService.getCameraDisabled(admin, userHandle, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -9359,7 +9367,6 @@ public class DevicePolicyManager { * <li>{@link #setPasswordExpirationTimeout}</li> * <li>{@link #getPasswordExpiration}</li> * <li>{@link #getPasswordMaximumLength}</li> * <li>{@link #getPasswordComplexity}</li> * <li>{@link #isActivePasswordSufficient}</li> * <li>{@link #getCurrentFailedPasswordAttempts}</li> * <li>{@link #getMaximumFailedPasswordsForWipe}</li> Loading @@ -9374,6 +9381,14 @@ public class DevicePolicyManager { * <li>{@link #getRequiredStrongAuthTimeout}</li> * <li>{@link #setRequiredStrongAuthTimeout}</li> * </ul> * <p> * The following methods are supported for the parent instance but can only be called by the * profile owner of a managed profile that was created during the device provisioning flow: * <ul> * <li>{@link #getPasswordComplexity}</li> * <li>{@link #setCameraDisabled}</li> * <li>{@link #getCameraDisabled}</li> * </ul> * * <p>The following methods can be called by the profile owner of a managed profile * on an organization-owned device: Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +2 −2 Original line number Diff line number Diff line Loading @@ -114,8 +114,8 @@ interface IDevicePolicyManager { boolean requestBugreport(in ComponentName who); void setCameraDisabled(in ComponentName who, boolean disabled); boolean getCameraDisabled(in ComponentName who, int userHandle); void setCameraDisabled(in ComponentName who, boolean disabled, boolean parent); boolean getCameraDisabled(in ComponentName who, int userHandle, boolean parent); void setScreenCaptureDisabled(in ComponentName who, boolean disabled); boolean getScreenCaptureDisabled(in ComponentName who, int userHandle); Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +103 −27 Original line number Diff line number Diff line Loading @@ -4345,6 +4345,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } /** * Get the list of active admins for an affected user: * <ul> * <li>The active admins associated with the userHandle itself</li> * <li>The parent active admins for each managed profile associated with the userHandle</li> * </ul> * * @param userHandle the affected user for whom to get the active admins * @param parent whether the parent active admins should be included in the list of active * admins or not * @return the list of active admins for the affected user */ private List<ActiveAdmin> getActiveAdminsForAffectedUser(int userHandle, boolean parent) { if (!parent) { return getUserDataUnchecked(userHandle).mAdminList; } ArrayList<ActiveAdmin> admins = new ArrayList<>(); for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) { DevicePolicyData policy = getUserData(userInfo.id); if (!userInfo.isManagedProfile()) { admins.addAll(policy.mAdminList); } else { // For managed profiles, policies set on the parent profile will be included for (int i = 0; i < policy.mAdminList.size(); i++) { ActiveAdmin admin = policy.mAdminList.get(i); if (admin.hasParentActiveAdmin()) { admins.add(admin.getParentActiveAdmin()); } } } } return admins; } private boolean isSeparateProfileChallengeEnabled(int userHandle) { long ident = mInjector.binderClearCallingIdentity(); try { Loading Loading @@ -7707,22 +7741,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * Disables all device cameras according to the specified admin. */ @Override public void setCameraDisabled(ComponentName who, boolean disabled) { public void setCameraDisabled(ComponentName who, boolean disabled, boolean parent) { if (!mHasFeature) { return; } Preconditions.checkNotNull(who, "ComponentName is null"); final int userHandle = mInjector.userHandleGetCallingUserId(); int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (getLockObject()) { ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA); DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA, parent); if (parent) { enforceProfileOwnerOfOrganizationOwnedDevice(ap); } if (ap.disableCamera != disabled) { ap.disableCamera = disabled; saveSettingsLocked(userHandle); } } // Tell the user manager that the restrictions have changed. pushUserRestrictions(userHandle); pushUserRestrictions(parent ? getProfileParentId(userHandle) : userHandle); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_CAMERA_DISABLED) .setAdmin(who) Loading @@ -7735,18 +7772,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * active admins. */ @Override public boolean getCameraDisabled(ComponentName who, int userHandle) { return getCameraDisabled(who, userHandle, /* mergeDeviceOwnerRestriction= */ true); public boolean getCameraDisabled(ComponentName who, int userHandle, boolean parent) { return getCameraDisabled(who, userHandle, /* mergeDeviceOwnerRestriction= */ true, parent); } private boolean getCameraDisabled(ComponentName who, int userHandle, boolean mergeDeviceOwnerRestriction) { boolean mergeDeviceOwnerRestriction, boolean parent) { if (!mHasFeature) { return false; } if (parent) { ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA, parent); enforceProfileOwnerOfOrganizationOwnedDevice(ap); } synchronized (getLockObject()) { if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); return (admin != null) ? admin.disableCamera : false; } // First, see if DO has set it. If so, it's device-wide. Loading @@ -7756,13 +7798,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return true; } } // Then check each device admin on the user. DevicePolicyData policy = getUserData(userHandle); // Return the strictest policy across all participating admins. List<ActiveAdmin> admins = getActiveAdminsForAffectedUser(userHandle, parent); // Determine whether or not the device camera is disabled for any active admins. final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { ActiveAdmin admin = policy.mAdminList.get(i); for (ActiveAdmin admin: admins) { if (admin.disableCamera) { return true; } Loading Loading @@ -8574,6 +8613,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } @GuardedBy("getLockObject()") ActiveAdmin getProfileOwnerOfOrganizationOwnedDeviceLocked(int userHandle) { final long ident = mInjector.binderClearCallingIdentity(); try { for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) { if (userInfo.isManagedProfile()) { if (getProfileOwner(userInfo.id) != null && canProfileOwnerAccessDeviceIds(userInfo.id)) { ComponentName who = getProfileOwner(userInfo.id); return getActiveAdminUncheckedLocked(who, userInfo.id); } } } } finally { mInjector.binderRestoreCallingIdentity(ident); } return null; } @Override public String getProfileOwnerName(int userHandle) { if (!mHasFeature) { Loading Loading @@ -10261,7 +10319,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private void pushUserRestrictions(int userId) { synchronized (getLockObject()) { final boolean isDeviceOwner = mOwners.isDeviceOwnerUserId(userId); final Bundle userRestrictions; Bundle userRestrictions = null; final int restrictionOwnerType; if (isDeviceOwner) { Loading @@ -10273,42 +10331,60 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { addOrRemoveDisableCameraRestriction(userRestrictions, deviceOwner); restrictionOwnerType = UserManagerInternal.OWNER_TYPE_DEVICE_OWNER; } else { final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId); userRestrictions = profileOwner != null ? profileOwner.userRestrictions : null; addOrRemoveDisableCameraRestriction(userRestrictions, userId); final ActiveAdmin profileOwnerOfOrganizationOwnedDevice = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId); if (isProfileOwnerOfOrganizationOwnedDevice(profileOwner)) { // 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; } else if (profileOwner != null) { final ActiveAdmin parent = profileOwnerOfOrganizationOwnedDevice .getParentActiveAdmin(); userRestrictions = parent.userRestrictions; userRestrictions = addOrRemoveDisableCameraRestriction(userRestrictions, parent); } else { final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId); if (profileOwner != null) { userRestrictions = profileOwner.userRestrictions; restrictionOwnerType = UserManagerInternal.OWNER_TYPE_PROFILE_OWNER; } else { restrictionOwnerType = UserManagerInternal.OWNER_TYPE_NO_OWNER; } userRestrictions = addOrRemoveDisableCameraRestriction( userRestrictions, userId); } } mUserManagerInternal.setDevicePolicyUserRestrictions(userId, userRestrictions, restrictionOwnerType); } } private void addOrRemoveDisableCameraRestriction(Bundle userRestrictions, ActiveAdmin admin) { if (userRestrictions == null) return; 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 void addOrRemoveDisableCameraRestriction(Bundle userRestrictions, int userId) { if (userRestrictions == null) return; 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; } @Override Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java +9 −5 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManagerInternal; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; Loading @@ -39,6 +38,9 @@ import java.util.Map; import java.util.Set; public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { private static final String USER_TYPE_EMPTY = ""; private DpmMockContext mContext; @Override Loading @@ -52,9 +54,10 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { } public void testMigration() throws Exception { final File user10dir = getServices().addUser(10, 0); final File user11dir = getServices().addUser(11, UserInfo.FLAG_MANAGED_PROFILE); getServices().addUser(12, 0); final File user10dir = getServices().addUser(10, 0, USER_TYPE_EMPTY); final File user11dir = getServices().addUser(11, 0, UserManager.USER_TYPE_PROFILE_MANAGED); getServices().addUser(12, 0, USER_TYPE_EMPTY); setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID); setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123)); Loading Loading @@ -273,7 +276,8 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { // Test setting default restrictions for managed profile. public void testMigration3_managedProfileOwner() throws Exception { // Create a managed profile user. final File user10dir = getServices().addUser(10, UserInfo.FLAG_MANAGED_PROFILE); final File user10dir = getServices().addUser(10, 0, UserManager.USER_TYPE_PROFILE_MANAGED); // Profile owner package for managed profile user. setUpPackageManagerForAdmin(admin1, UserHandle.getUid(10, 123)); // Set up fake UserManager to make it look like a managed profile. Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +34 −37 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { private DpmMockContext mServiceContext; private DpmMockContext mAdmin1Context; public DevicePolicyManager dpm; public DevicePolicyManager parentDpm; public DevicePolicyManagerServiceTestable dpms; /* Loading Loading @@ -240,6 +241,9 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm = new DevicePolicyManagerTestable(mContext, dpms); parentDpm = new DevicePolicyManagerTestable(mServiceContext, dpms, /* parentInstance= */true); mContext.binder.restoreCallingIdentity(ident); } Loading Loading @@ -269,7 +273,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { anyString(), any(UserHandle.class)); // Add the first secondary user. getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0); getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0, UserManager.USER_TYPE_FULL_SECONDARY); } private void setAsProfileOwner(ComponentName admin) { Loading Loading @@ -330,7 +335,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { public void testLoadAdminData_noAdmins() throws Exception { final int ANOTHER_USER_ID = 15; getServices().addUser(ANOTHER_USER_ID, 0); getServices().addUser(ANOTHER_USER_ID, 0, ""); initializeDpms(); Loading Loading @@ -477,7 +482,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { final int ANOTHER_USER_ID = 100; final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 20456); getServices().addUser(ANOTHER_USER_ID, 0); // Add one more user. getServices().addUser(ANOTHER_USER_ID, 0, ""); // Add one more user. // Set up pacakge manager for the other user. setUpPackageManagerForAdmin(admin2, ANOTHER_ADMIN_UID); Loading Loading @@ -1343,7 +1348,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { final int ANOTHER_USER_ID = 100; final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 456); getServices().addUser(ANOTHER_USER_ID, 0); // Add one more user. getServices().addUser(ANOTHER_USER_ID, 0, ""); // Add one more user. mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); mContext.callerPermissions.add(permission.MANAGE_USERS); Loading Loading @@ -1961,35 +1966,30 @@ public class DevicePolicyManagerTest extends DpmTestBase { // TODO Make sure restrictions are written to the file. } // TODO: (b/138709470) test addUserRestriction as PO of an organization-owned device public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception { setupProfileOwner(); 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); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; final long ident = mServiceContext.binder.clearCallingIdentity(); configureContextForAccess(mServiceContext, true); addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); mServiceContext.binder.callingUid = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, DpmMockContext.CALLER_MANAGED_PROVISIONING_UID); try { runAsCaller(mServiceContext, dpms, dpm -> { dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1); }); } finally { mServiceContext.binder.restoreCallingIdentity(ident); } when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID)) .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0)); dpm.addUserRestriction(admin1, UserManager.DISALLOW_CONFIG_DATE_TIME); parentDpm.setCameraDisabled(admin1, true); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), MockUtils.checkUserRestrictions(UserManager.DISALLOW_CONFIG_DATE_TIME), eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA), eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); reset(getServices().userManagerInternal); dpm.setCameraDisabled(admin1, true); parentDpm.setCameraDisabled(admin1, false); verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions( eq(DpmMockContext.CALLER_USER_HANDLE), MockUtils.checkUserRestrictions(UserManager.DISALLOW_CONFIG_DATE_TIME, UserManager.DISALLOW_CAMERA), eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(), eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)); reset(getServices().userManagerInternal); } Loading Loading @@ -3861,7 +3861,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { // Add a secondary user, it should never talk with. final int ANOTHER_USER_ID = 36; getServices().addUser(ANOTHER_USER_ID, 0); getServices().addUser(ANOTHER_USER_ID, 0, UserManager.USER_TYPE_FULL_SECONDARY); // Since the managed profile is not affiliated, they should not be allowed to talk to each // other. Loading Loading @@ -5206,8 +5206,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { } public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception { getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM); getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0, UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM); DpmTestUtils.writeInputStreamToFile( getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated), getProfileOwnerPoliciesFile()); Loading @@ -5218,8 +5218,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { } public void testRevertProfileOwnership_profileNotMigrated() throws Exception { getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM); getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0, UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM); DpmTestUtils.writeInputStreamToFile( getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated), getProfileOwnerPoliciesFile()); Loading @@ -5230,8 +5230,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { } public void testRevertProfileOwnership_adminAndProfileNotMigrated() throws Exception { getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM); getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0, UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM); DpmTestUtils.writeInputStreamToFile( getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_not_migrated), getProfileOwnerPoliciesFile()); Loading Loading @@ -5405,11 +5405,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { mServiceContext.permissions.add(permission.REQUEST_PASSWORD_COMPLEXITY); setAsProfileOwner(admin1); new DevicePolicyManagerTestable( mServiceContext, dpms, /* parentInstance= */ true) .getPasswordComplexity(); parentDpm.getPasswordComplexity(); assertEquals(PASSWORD_COMPLEXITY_NONE, dpm.getPasswordComplexity()); } Loading Loading @@ -5685,7 +5681,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { private void addManagedProfile( ComponentName admin, int adminUid, ComponentName copyFromAdmin) throws Exception { final int userId = UserHandle.getUserId(adminUid); getServices().addUser(userId, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM); getServices().addUser(userId, 0, UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM); mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS); setUpPackageManagerForFakeAdmin(admin, adminUid, copyFromAdmin); dpm.setActiveAdmin(admin, false, userId); Loading