Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7989a38 authored by Rajeev Kumar's avatar Rajeev Kumar Committed by Android (Google) Code Review
Browse files

Merge "Exempt device lock controller and kiosk roles from metered restrictions." into main

parents 7602ab84 63ec472b
Loading
Loading
Loading
Loading
+30 −5
Original line number Diff line number Diff line
@@ -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
@@ -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) {
@@ -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;
                }
@@ -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;
@@ -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);
                }
+6 −0
Original line number Diff line number Diff line
@@ -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;

/**
@@ -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) {
+47 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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.
@@ -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;