Loading core/java/android/app/admin/DeviceAdminInfo.java +8 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,14 @@ import java.util.HashMap; public final class DeviceAdminInfo implements Parcelable { static final String TAG = "DeviceAdminInfo"; /** * A type of policy that this device admin can use: profile owner on an organization-owned * device. * * @hide */ public static final int USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER = -3; /** * A type of policy that this device admin can use: device owner meta-policy * for an admin that is designated as owner of the device. Loading core/java/android/app/admin/DevicePolicyManager.java +8 −1 Original line number Diff line number Diff line Loading @@ -9135,7 +9135,14 @@ public class DevicePolicyManager { } /** * Called by device owner to get the MAC address of the Wi-Fi device. * Called by device owner, or profile owner on organization-owned device, to get the MAC * address of the Wi-Fi device. * * NOTE: The MAC address returned here should only be used for inventory management and is * not likely to be the MAC address used by the device to connect to Wi-Fi networks: MAC * addresses used for scanning and connecting to Wi-Fi networks are randomized by default. * To get the randomized MAC address used, call * {@link android.net.wifi.WifiConfiguration#getRandomizedMacAddress}. * * @param admin Which device owner this request is associated with. * @return the MAC address of the Wi-Fi device, or null when the information is not available. Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +25 −16 Original line number Diff line number Diff line Loading @@ -2754,6 +2754,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } // Code for handling failure from getActiveAdminWithPolicyForUidLocked to find an admin // that satisfies the required policy. // Throws a security exception with the right error message. if (who != null) { final int userId = UserHandle.getUserId(callingUid); final DevicePolicyData policy = getUserData(userId); Loading @@ -2769,6 +2772,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { throw new SecurityException("Admin " + admin.info.getComponent() + " does not own the profile"); } if (reqPolicy == DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER) { throw new SecurityException("Admin " + admin.info.getComponent() + " is not the profile owner on organization-owned device"); } if (DA_DISALLOWED_POLICIES.contains(reqPolicy) && !isDeviceOwner && !isProfileOwner) { throw new SecurityException("Admin " + admin.info.getComponent() + " is not a device owner or profile owner, so may not use policy: " Loading Loading @@ -2875,12 +2882,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { ensureLocked(); final boolean ownsDevice = isDeviceOwner(admin.info.getComponent(), userId); final boolean ownsProfile = isProfileOwner(admin.info.getComponent(), userId); final boolean ownsProfileOnOrganizationOwnedDevice = isProfileOwnerOfOrganizationOwnedDevice(admin.info.getComponent(), userId); if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) { return ownsDevice; } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER) { return ownsDevice || ownsProfileOnOrganizationOwnedDevice; } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) { // DO always has the PO power. return ownsDevice || ownsProfile; return ownsDevice || ownsProfileOnOrganizationOwnedDevice || ownsProfile; } else { boolean allowedToUsePolicy = ownsDevice || ownsProfile || !DA_DISALLOWED_POLICIES.contains(reqPolicy) Loading Loading @@ -5580,6 +5591,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private void enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(ComponentName who) { synchronized (getLockObject()) { getActiveAdminForCallerLocked( who, DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER); } } private void enforceProfileOwnerOfOrganizationOwnedDevice(ActiveAdmin admin) { if (!isProfileOwnerOfOrganizationOwnedDevice(admin)) { throw new SecurityException(String.format("Provided admin %s is either not a profile " Loading Loading @@ -8077,21 +8095,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } final int adminUserId = admin.getUserHandle().getIdentifier(); if (!isProfileOwner(admin.info.getComponent(), adminUserId)) { Slog.w(LOG_TAG, String.format("%s is not profile owner of user %d", admin.info.getComponent(), adminUserId)); return false; return isProfileOwnerOfOrganizationOwnedDevice( admin.info.getComponent(), admin.getUserHandle().getIdentifier()); } if (!canProfileOwnerAccessDeviceIds(adminUserId)) { Slog.w(LOG_TAG, String.format("Profile owner of user %d does not own the device.", adminUserId)); return false; } return true; private boolean isProfileOwnerOfOrganizationOwnedDevice(ComponentName who, int userId) { return isProfileOwner(who, userId) && canProfileOwnerAccessDeviceIds(userId); } @Override Loading Loading @@ -12386,7 +12395,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public String getWifiMacAddress(ComponentName admin) { // Make sure caller has DO. enforceDeviceOwner(admin); enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(admin); final long ident = mInjector.binderClearCallingIdentity(); try { services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +15 −2 Original line number Diff line number Diff line Loading @@ -140,6 +140,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { permission.MANAGE_USERS, permission.INTERACT_ACROSS_USERS_FULL); public static final String NOT_DEVICE_OWNER_MSG = "does not own the device"; public static final String NOT_PROFILE_OWNER_MSG = "does not own the profile"; public static final String NOT_ORG_OWNED_PROFILE_OWNER_MSG = "not the profile owner on organization-owned device"; public static final String ONGOING_CALL_MSG = "ongoing call on the device"; // TODO replace all instances of this with explicit {@link #mServiceContext}. Loading Loading @@ -2116,12 +2118,14 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertTrue(dpm.isAdminActive(admin1)); // Test 2. Caller has DA, but not DO. assertExpectException(SecurityException.class, /* messageRegex= */ NOT_DEVICE_OWNER_MSG, assertExpectException(SecurityException.class, /* messageRegex= */ NOT_ORG_OWNED_PROFILE_OWNER_MSG, () -> dpm.getWifiMacAddress(admin1)); // Test 3. Caller has PO, but not DO. assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)); assertExpectException(SecurityException.class, /* messageRegex= */ NOT_DEVICE_OWNER_MSG, assertExpectException(SecurityException.class, /* messageRegex= */ NOT_ORG_OWNED_PROFILE_OWNER_MSG, () -> dpm.getWifiMacAddress(admin1)); // Remove PO. Loading @@ -2143,6 +2147,15 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1)); } public void testGetMacAddressByOrgOwnedPO() throws Exception { setupProfileOwner(); configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); final String[] macAddresses = new String[]{"11:22:33:44:55:66"}; when(getServices().wifiManager.getFactoryMacAddresses()).thenReturn(macAddresses); assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1)); } public void testReboot() throws Exception { mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); Loading Loading
core/java/android/app/admin/DeviceAdminInfo.java +8 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,14 @@ import java.util.HashMap; public final class DeviceAdminInfo implements Parcelable { static final String TAG = "DeviceAdminInfo"; /** * A type of policy that this device admin can use: profile owner on an organization-owned * device. * * @hide */ public static final int USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER = -3; /** * A type of policy that this device admin can use: device owner meta-policy * for an admin that is designated as owner of the device. Loading
core/java/android/app/admin/DevicePolicyManager.java +8 −1 Original line number Diff line number Diff line Loading @@ -9135,7 +9135,14 @@ public class DevicePolicyManager { } /** * Called by device owner to get the MAC address of the Wi-Fi device. * Called by device owner, or profile owner on organization-owned device, to get the MAC * address of the Wi-Fi device. * * NOTE: The MAC address returned here should only be used for inventory management and is * not likely to be the MAC address used by the device to connect to Wi-Fi networks: MAC * addresses used for scanning and connecting to Wi-Fi networks are randomized by default. * To get the randomized MAC address used, call * {@link android.net.wifi.WifiConfiguration#getRandomizedMacAddress}. * * @param admin Which device owner this request is associated with. * @return the MAC address of the Wi-Fi device, or null when the information is not available. Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +25 −16 Original line number Diff line number Diff line Loading @@ -2754,6 +2754,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } // Code for handling failure from getActiveAdminWithPolicyForUidLocked to find an admin // that satisfies the required policy. // Throws a security exception with the right error message. if (who != null) { final int userId = UserHandle.getUserId(callingUid); final DevicePolicyData policy = getUserData(userId); Loading @@ -2769,6 +2772,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { throw new SecurityException("Admin " + admin.info.getComponent() + " does not own the profile"); } if (reqPolicy == DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER) { throw new SecurityException("Admin " + admin.info.getComponent() + " is not the profile owner on organization-owned device"); } if (DA_DISALLOWED_POLICIES.contains(reqPolicy) && !isDeviceOwner && !isProfileOwner) { throw new SecurityException("Admin " + admin.info.getComponent() + " is not a device owner or profile owner, so may not use policy: " Loading Loading @@ -2875,12 +2882,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { ensureLocked(); final boolean ownsDevice = isDeviceOwner(admin.info.getComponent(), userId); final boolean ownsProfile = isProfileOwner(admin.info.getComponent(), userId); final boolean ownsProfileOnOrganizationOwnedDevice = isProfileOwnerOfOrganizationOwnedDevice(admin.info.getComponent(), userId); if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) { return ownsDevice; } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER) { return ownsDevice || ownsProfileOnOrganizationOwnedDevice; } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) { // DO always has the PO power. return ownsDevice || ownsProfile; return ownsDevice || ownsProfileOnOrganizationOwnedDevice || ownsProfile; } else { boolean allowedToUsePolicy = ownsDevice || ownsProfile || !DA_DISALLOWED_POLICIES.contains(reqPolicy) Loading Loading @@ -5580,6 +5591,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private void enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(ComponentName who) { synchronized (getLockObject()) { getActiveAdminForCallerLocked( who, DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER); } } private void enforceProfileOwnerOfOrganizationOwnedDevice(ActiveAdmin admin) { if (!isProfileOwnerOfOrganizationOwnedDevice(admin)) { throw new SecurityException(String.format("Provided admin %s is either not a profile " Loading Loading @@ -8077,21 +8095,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } final int adminUserId = admin.getUserHandle().getIdentifier(); if (!isProfileOwner(admin.info.getComponent(), adminUserId)) { Slog.w(LOG_TAG, String.format("%s is not profile owner of user %d", admin.info.getComponent(), adminUserId)); return false; return isProfileOwnerOfOrganizationOwnedDevice( admin.info.getComponent(), admin.getUserHandle().getIdentifier()); } if (!canProfileOwnerAccessDeviceIds(adminUserId)) { Slog.w(LOG_TAG, String.format("Profile owner of user %d does not own the device.", adminUserId)); return false; } return true; private boolean isProfileOwnerOfOrganizationOwnedDevice(ComponentName who, int userId) { return isProfileOwner(who, userId) && canProfileOwnerAccessDeviceIds(userId); } @Override Loading Loading @@ -12386,7 +12395,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public String getWifiMacAddress(ComponentName admin) { // Make sure caller has DO. enforceDeviceOwner(admin); enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(admin); final long ident = mInjector.binderClearCallingIdentity(); try {
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +15 −2 Original line number Diff line number Diff line Loading @@ -140,6 +140,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { permission.MANAGE_USERS, permission.INTERACT_ACROSS_USERS_FULL); public static final String NOT_DEVICE_OWNER_MSG = "does not own the device"; public static final String NOT_PROFILE_OWNER_MSG = "does not own the profile"; public static final String NOT_ORG_OWNED_PROFILE_OWNER_MSG = "not the profile owner on organization-owned device"; public static final String ONGOING_CALL_MSG = "ongoing call on the device"; // TODO replace all instances of this with explicit {@link #mServiceContext}. Loading Loading @@ -2116,12 +2118,14 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertTrue(dpm.isAdminActive(admin1)); // Test 2. Caller has DA, but not DO. assertExpectException(SecurityException.class, /* messageRegex= */ NOT_DEVICE_OWNER_MSG, assertExpectException(SecurityException.class, /* messageRegex= */ NOT_ORG_OWNED_PROFILE_OWNER_MSG, () -> dpm.getWifiMacAddress(admin1)); // Test 3. Caller has PO, but not DO. assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)); assertExpectException(SecurityException.class, /* messageRegex= */ NOT_DEVICE_OWNER_MSG, assertExpectException(SecurityException.class, /* messageRegex= */ NOT_ORG_OWNED_PROFILE_OWNER_MSG, () -> dpm.getWifiMacAddress(admin1)); // Remove PO. Loading @@ -2143,6 +2147,15 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1)); } public void testGetMacAddressByOrgOwnedPO() throws Exception { setupProfileOwner(); configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); final String[] macAddresses = new String[]{"11:22:33:44:55:66"}; when(getServices().wifiManager.getFactoryMacAddresses()).thenReturn(macAddresses); assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1)); } public void testReboot() throws Exception { mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); Loading