Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +30 −5 Original line number Diff line number Diff line Loading @@ -871,6 +871,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { EXEMPT_FROM_POWER_RESTRICTIONS, OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS); } private static final Set<String> METERED_DATA_RESTRICTION_EXEMPT_ROLES = new ArraySet<>(); static { // TODO(b/362545319): reference role name from role manager once it's exposed. final String roleDeviceLockController = "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; METERED_DATA_RESTRICTION_EXEMPT_ROLES.add(roleDeviceLockController); METERED_DATA_RESTRICTION_EXEMPT_ROLES.add(RoleManager.ROLE_FINANCED_DEVICE_KIOSK); } /** * Admin apps targeting Android S+ may not use * {@link android.app.admin.DevicePolicyManager#setPasswordQuality} to set password quality Loading Loading @@ -1959,6 +1969,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return UserManager.isHeadlessSystemUserMode(); } List<String> roleManagerGetRoleHoldersAsUser(String role, UserHandle userHandle) { return getRoleManager().getRoleHoldersAsUser(role, userHandle); } @SuppressWarnings("AndroidFrameworkPendingIntentMutability") PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode, @NonNull Intent intent, int flags, Bundle options, UserHandle user) { Loading Loading @@ -17900,15 +17914,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }); } private Set<String> getMeteredDataRestrictionExemptPackages(int userId) { final Set<String> exemptPkgs = new ArraySet<>(); for (String role: METERED_DATA_RESTRICTION_EXEMPT_ROLES) { String pkg = getRoleHolderPackageNameOnUser(role, userId); if (pkg != null) { exemptPkgs.add(pkg); } } return exemptPkgs; } private List<String> removeInvalidPkgsForMeteredDataRestriction( int userId, List<String> pkgNames) { final Set<String> exemptRolePkgs = getMeteredDataRestrictionExemptPackages(userId); synchronized (getLockObject()) { final Set<String> activeAdmins = getActiveAdminPackagesLocked(userId); final List<String> excludedPkgs = new ArrayList<>(); for (int i = pkgNames.size() - 1; i >= 0; --i) { final String pkgName = pkgNames.get(i); // If the package is an active admin, don't restrict it. if (activeAdmins.contains(pkgName)) { // If the package is an active admin or exempt role, don't restrict it. if (activeAdmins.contains(pkgName) || exemptRolePkgs.contains(pkgName)) { excludedPkgs.add(pkgName); continue; } Loading Loading @@ -21749,8 +21776,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { */ @Nullable private String getRoleHolderPackageNameOnUser(String role, int userId) { RoleManager roleManager = mContext.getSystemService(RoleManager.class); // Clear calling identity as the RoleManager APIs require privileged permissions. return mInjector.binderWithCleanCallingIdentity(() -> { List<UserInfo> users; Loading @@ -21762,7 +21787,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } for (UserInfo user : users) { List<String> roleHolders = roleManager.getRoleHoldersAsUser(role, user.getUserHandle()); mInjector.roleManagerGetRoleHoldersAsUser(role, user.getUserHandle()); if (!roleHolders.isEmpty()) { return roleHolders.get(0); } services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +6 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.server.wm.ActivityTaskManagerInternal; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; /** Loading Loading @@ -324,6 +325,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi return services.userManagerForMock.isHeadlessSystemUserMode(); } @Override List<String> roleManagerGetRoleHoldersAsUser(String role, UserHandle userHandle) { return services.roleManagerForMock.getRoleHoldersAsUser(role, userHandle); } @Override PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode, Intent intent, int flags, Bundle options, UserHandle user) { Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +47 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ import android.app.admin.PasswordMetrics; import android.app.admin.PreferentialNetworkServiceConfig; import android.app.admin.SystemUpdatePolicy; import android.app.admin.WifiSsidPolicy; import android.app.role.RoleManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Intent; Loading Loading @@ -2888,6 +2889,52 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(CALLER_USER_HANDLE)); } @Test public void testSetMeteredDataDisabledPackagesExemptRoles() throws Exception { // TODO(b/362545319): reference role name from role manager once it's exposed. final String controllerRole = "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; setAsProfileOwner(admin1); assertThat(dpm.getMeteredDataDisabledPackages(admin1)).isEmpty(); // Setup final ArrayList<String> pkgsToRestrict = new ArrayList<>(); final ArrayList<String> pkgsExpectedAsNotRestricted = new ArrayList<>(); final String packageWithControllerRole = "com.example.controller"; final String packageWithKioskRole = "com.example.kiosk"; final String packageWithNotExemptRole = "com.example.notexempt"; pkgsToRestrict.add(packageWithControllerRole); pkgsToRestrict.add(packageWithKioskRole); pkgsToRestrict.add(packageWithNotExemptRole); pkgsExpectedAsNotRestricted.add(packageWithControllerRole); pkgsExpectedAsNotRestricted.add(packageWithKioskRole); setupPackageInPackageManager(packageWithControllerRole, CALLER_USER_HANDLE, 123, 0); setupPackageInPackageManager(packageWithKioskRole, CALLER_USER_HANDLE, 456, 0); setupPackageInPackageManager(packageWithNotExemptRole, CALLER_USER_HANDLE, 789, 0); when(getServices().roleManagerForMock.getRoleHoldersAsUser(controllerRole, UserHandle.of(CALLER_USER_HANDLE))) .thenReturn(new ArrayList<>(Arrays.asList(packageWithControllerRole))); when(getServices().roleManagerForMock.getRoleHoldersAsUser( RoleManager.ROLE_FINANCED_DEVICE_KIOSK, UserHandle.of(CALLER_USER_HANDLE))) .thenReturn(new ArrayList<>(Arrays.asList(packageWithKioskRole))); List<String> excludedPkgs = dpm.setMeteredDataDisabledPackages(admin1, pkgsToRestrict); // Verify assertThat(excludedPkgs).containsExactlyElementsIn(pkgsExpectedAsNotRestricted); assertThat(dpm.getMeteredDataDisabledPackages(admin1)) .isEqualTo(Arrays.asList(packageWithNotExemptRole)); verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages( MockUtils.checkApps(packageWithNotExemptRole), eq(CALLER_USER_HANDLE)); } @Test public void testSetGetMeteredDataDisabledPackages_deviceAdmin() { mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); Loading services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java +8 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,7 @@ public class MockSystemServices { public final DevicePolicyManager devicePolicyManager; public final LocationManager locationManager; public final RoleManager roleManager; public final RoleManagerForMock roleManagerForMock; public final SubscriptionManager subscriptionManager; /** Note this is a partial mock, not a real mock. */ public final PackageManager packageManager; Loading Loading @@ -200,6 +201,7 @@ public class MockSystemServices { devicePolicyManager = mock(DevicePolicyManager.class); locationManager = mock(LocationManager.class); roleManager = realContext.getSystemService(RoleManager.class); roleManagerForMock = mock(RoleManagerForMock.class); subscriptionManager = mock(SubscriptionManager.class); // Package manager is huge, so we use a partial mock instead. Loading Loading @@ -495,6 +497,12 @@ public class MockSystemServices { } } public static class RoleManagerForMock { public List<String> getRoleHoldersAsUser(String role, UserHandle userHandle) { return new ArrayList<>(); } } public static class SettingsForMock { public int settingsSecureGetIntForUser(String name, int def, int userHandle) { return 0; Loading Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +30 −5 Original line number Diff line number Diff line Loading @@ -871,6 +871,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { EXEMPT_FROM_POWER_RESTRICTIONS, OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS); } private static final Set<String> METERED_DATA_RESTRICTION_EXEMPT_ROLES = new ArraySet<>(); static { // TODO(b/362545319): reference role name from role manager once it's exposed. final String roleDeviceLockController = "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; METERED_DATA_RESTRICTION_EXEMPT_ROLES.add(roleDeviceLockController); METERED_DATA_RESTRICTION_EXEMPT_ROLES.add(RoleManager.ROLE_FINANCED_DEVICE_KIOSK); } /** * Admin apps targeting Android S+ may not use * {@link android.app.admin.DevicePolicyManager#setPasswordQuality} to set password quality Loading Loading @@ -1959,6 +1969,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return UserManager.isHeadlessSystemUserMode(); } List<String> roleManagerGetRoleHoldersAsUser(String role, UserHandle userHandle) { return getRoleManager().getRoleHoldersAsUser(role, userHandle); } @SuppressWarnings("AndroidFrameworkPendingIntentMutability") PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode, @NonNull Intent intent, int flags, Bundle options, UserHandle user) { Loading Loading @@ -17900,15 +17914,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }); } private Set<String> getMeteredDataRestrictionExemptPackages(int userId) { final Set<String> exemptPkgs = new ArraySet<>(); for (String role: METERED_DATA_RESTRICTION_EXEMPT_ROLES) { String pkg = getRoleHolderPackageNameOnUser(role, userId); if (pkg != null) { exemptPkgs.add(pkg); } } return exemptPkgs; } private List<String> removeInvalidPkgsForMeteredDataRestriction( int userId, List<String> pkgNames) { final Set<String> exemptRolePkgs = getMeteredDataRestrictionExemptPackages(userId); synchronized (getLockObject()) { final Set<String> activeAdmins = getActiveAdminPackagesLocked(userId); final List<String> excludedPkgs = new ArrayList<>(); for (int i = pkgNames.size() - 1; i >= 0; --i) { final String pkgName = pkgNames.get(i); // If the package is an active admin, don't restrict it. if (activeAdmins.contains(pkgName)) { // If the package is an active admin or exempt role, don't restrict it. if (activeAdmins.contains(pkgName) || exemptRolePkgs.contains(pkgName)) { excludedPkgs.add(pkgName); continue; } Loading Loading @@ -21749,8 +21776,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { */ @Nullable private String getRoleHolderPackageNameOnUser(String role, int userId) { RoleManager roleManager = mContext.getSystemService(RoleManager.class); // Clear calling identity as the RoleManager APIs require privileged permissions. return mInjector.binderWithCleanCallingIdentity(() -> { List<UserInfo> users; Loading @@ -21762,7 +21787,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } for (UserInfo user : users) { List<String> roleHolders = roleManager.getRoleHoldersAsUser(role, user.getUserHandle()); mInjector.roleManagerGetRoleHoldersAsUser(role, user.getUserHandle()); if (!roleHolders.isEmpty()) { return roleHolders.get(0); }
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +6 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.server.wm.ActivityTaskManagerInternal; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; /** Loading Loading @@ -324,6 +325,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi return services.userManagerForMock.isHeadlessSystemUserMode(); } @Override List<String> roleManagerGetRoleHoldersAsUser(String role, UserHandle userHandle) { return services.roleManagerForMock.getRoleHoldersAsUser(role, userHandle); } @Override PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode, Intent intent, int flags, Bundle options, UserHandle user) { Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +47 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ import android.app.admin.PasswordMetrics; import android.app.admin.PreferentialNetworkServiceConfig; import android.app.admin.SystemUpdatePolicy; import android.app.admin.WifiSsidPolicy; import android.app.role.RoleManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Intent; Loading Loading @@ -2888,6 +2889,52 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(CALLER_USER_HANDLE)); } @Test public void testSetMeteredDataDisabledPackagesExemptRoles() throws Exception { // TODO(b/362545319): reference role name from role manager once it's exposed. final String controllerRole = "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; setAsProfileOwner(admin1); assertThat(dpm.getMeteredDataDisabledPackages(admin1)).isEmpty(); // Setup final ArrayList<String> pkgsToRestrict = new ArrayList<>(); final ArrayList<String> pkgsExpectedAsNotRestricted = new ArrayList<>(); final String packageWithControllerRole = "com.example.controller"; final String packageWithKioskRole = "com.example.kiosk"; final String packageWithNotExemptRole = "com.example.notexempt"; pkgsToRestrict.add(packageWithControllerRole); pkgsToRestrict.add(packageWithKioskRole); pkgsToRestrict.add(packageWithNotExemptRole); pkgsExpectedAsNotRestricted.add(packageWithControllerRole); pkgsExpectedAsNotRestricted.add(packageWithKioskRole); setupPackageInPackageManager(packageWithControllerRole, CALLER_USER_HANDLE, 123, 0); setupPackageInPackageManager(packageWithKioskRole, CALLER_USER_HANDLE, 456, 0); setupPackageInPackageManager(packageWithNotExemptRole, CALLER_USER_HANDLE, 789, 0); when(getServices().roleManagerForMock.getRoleHoldersAsUser(controllerRole, UserHandle.of(CALLER_USER_HANDLE))) .thenReturn(new ArrayList<>(Arrays.asList(packageWithControllerRole))); when(getServices().roleManagerForMock.getRoleHoldersAsUser( RoleManager.ROLE_FINANCED_DEVICE_KIOSK, UserHandle.of(CALLER_USER_HANDLE))) .thenReturn(new ArrayList<>(Arrays.asList(packageWithKioskRole))); List<String> excludedPkgs = dpm.setMeteredDataDisabledPackages(admin1, pkgsToRestrict); // Verify assertThat(excludedPkgs).containsExactlyElementsIn(pkgsExpectedAsNotRestricted); assertThat(dpm.getMeteredDataDisabledPackages(admin1)) .isEqualTo(Arrays.asList(packageWithNotExemptRole)); verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages( MockUtils.checkApps(packageWithNotExemptRole), eq(CALLER_USER_HANDLE)); } @Test public void testSetGetMeteredDataDisabledPackages_deviceAdmin() { mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); Loading
services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java +8 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,7 @@ public class MockSystemServices { public final DevicePolicyManager devicePolicyManager; public final LocationManager locationManager; public final RoleManager roleManager; public final RoleManagerForMock roleManagerForMock; public final SubscriptionManager subscriptionManager; /** Note this is a partial mock, not a real mock. */ public final PackageManager packageManager; Loading Loading @@ -200,6 +201,7 @@ public class MockSystemServices { devicePolicyManager = mock(DevicePolicyManager.class); locationManager = mock(LocationManager.class); roleManager = realContext.getSystemService(RoleManager.class); roleManagerForMock = mock(RoleManagerForMock.class); subscriptionManager = mock(SubscriptionManager.class); // Package manager is huge, so we use a partial mock instead. Loading Loading @@ -495,6 +497,12 @@ public class MockSystemServices { } } public static class RoleManagerForMock { public List<String> getRoleHoldersAsUser(String role, UserHandle userHandle) { return new ArrayList<>(); } } public static class SettingsForMock { public int settingsSecureGetIntForUser(String name, int def, int userHandle) { return 0; Loading