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 Original line 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);
                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
     * Admin apps targeting Android S+ may not use
     * {@link android.app.admin.DevicePolicyManager#setPasswordQuality} to set password quality
     * {@link android.app.admin.DevicePolicyManager#setPasswordQuality} to set password quality
@@ -1959,6 +1969,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return UserManager.isHeadlessSystemUserMode();
            return UserManager.isHeadlessSystemUserMode();
        }
        }
        List<String> roleManagerGetRoleHoldersAsUser(String role, UserHandle userHandle) {
            return getRoleManager().getRoleHoldersAsUser(role, userHandle);
        }
        @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
        @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
        PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode,
        PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode,
                @NonNull Intent intent, int flags, Bundle options, UserHandle user) {
                @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(
    private List<String> removeInvalidPkgsForMeteredDataRestriction(
            int userId, List<String> pkgNames) {
            int userId, List<String> pkgNames) {
        final Set<String> exemptRolePkgs = getMeteredDataRestrictionExemptPackages(userId);
        synchronized (getLockObject()) {
        synchronized (getLockObject()) {
            final Set<String> activeAdmins = getActiveAdminPackagesLocked(userId);
            final Set<String> activeAdmins = getActiveAdminPackagesLocked(userId);
            final List<String> excludedPkgs = new ArrayList<>();
            final List<String> excludedPkgs = new ArrayList<>();
            for (int i = pkgNames.size() - 1; i >= 0; --i) {
            for (int i = pkgNames.size() - 1; i >= 0; --i) {
                final String pkgName = pkgNames.get(i);
                final String pkgName = pkgNames.get(i);
                // If the package is an active admin, don't restrict it.
                // If the package is an active admin or exempt role, don't restrict it.
                if (activeAdmins.contains(pkgName)) {
                if (activeAdmins.contains(pkgName) || exemptRolePkgs.contains(pkgName)) {
                    excludedPkgs.add(pkgName);
                    excludedPkgs.add(pkgName);
                    continue;
                    continue;
                }
                }
@@ -21749,8 +21776,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     */
     */
    @Nullable
    @Nullable
    private String getRoleHolderPackageNameOnUser(String role, int userId) {
    private String getRoleHolderPackageNameOnUser(String role, int userId) {
        RoleManager roleManager = mContext.getSystemService(RoleManager.class);
        // Clear calling identity as the RoleManager APIs require privileged permissions.
        // Clear calling identity as the RoleManager APIs require privileged permissions.
        return mInjector.binderWithCleanCallingIdentity(() -> {
        return mInjector.binderWithCleanCallingIdentity(() -> {
            List<UserInfo> users;
            List<UserInfo> users;
@@ -21762,7 +21787,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            }
            for (UserInfo user : users) {
            for (UserInfo user : users) {
                List<String> roleHolders =
                List<String> roleHolders =
                        roleManager.getRoleHoldersAsUser(role, user.getUserHandle());
                        mInjector.roleManagerGetRoleHoldersAsUser(role, user.getUserHandle());
                if (!roleHolders.isEmpty()) {
                if (!roleHolders.isEmpty()) {
                    return roleHolders.get(0);
                    return roleHolders.get(0);
                }
                }
+6 −0
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ import com.android.server.wm.ActivityTaskManagerInternal;


import java.io.File;
import java.io.File;
import java.io.IOException;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map;


/**
/**
@@ -324,6 +325,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
            return services.userManagerForMock.isHeadlessSystemUserMode();
            return services.userManagerForMock.isHeadlessSystemUserMode();
        }
        }


        @Override
        List<String> roleManagerGetRoleHoldersAsUser(String role, UserHandle userHandle) {
            return services.roleManagerForMock.getRoleHoldersAsUser(role, userHandle);
        }

        @Override
        @Override
        PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode,
        PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode,
                Intent intent, int flags, Bundle options, UserHandle user) {
                Intent intent, int flags, Bundle options, UserHandle user) {
+47 −0
Original line number Original line Diff line number Diff line
@@ -109,6 +109,7 @@ import android.app.admin.PasswordMetrics;
import android.app.admin.PreferentialNetworkServiceConfig;
import android.app.admin.PreferentialNetworkServiceConfig;
import android.app.admin.SystemUpdatePolicy;
import android.app.admin.SystemUpdatePolicy;
import android.app.admin.WifiSsidPolicy;
import android.app.admin.WifiSsidPolicy;
import android.app.role.RoleManager;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Intent;
import android.content.Intent;
@@ -2888,6 +2889,52 @@ public class DevicePolicyManagerTest extends DpmTestBase {
                eq(CALLER_USER_HANDLE));
                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
    @Test
    public void testSetGetMeteredDataDisabledPackages_deviceAdmin() {
    public void testSetGetMeteredDataDisabledPackages_deviceAdmin() {
        mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
        mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+8 −0
Original line number Original line Diff line number Diff line
@@ -142,6 +142,7 @@ public class MockSystemServices {
    public final DevicePolicyManager devicePolicyManager;
    public final DevicePolicyManager devicePolicyManager;
    public final LocationManager locationManager;
    public final LocationManager locationManager;
    public final RoleManager roleManager;
    public final RoleManager roleManager;
    public final RoleManagerForMock roleManagerForMock;
    public final SubscriptionManager subscriptionManager;
    public final SubscriptionManager subscriptionManager;
    /** Note this is a partial mock, not a real mock. */
    /** Note this is a partial mock, not a real mock. */
    public final PackageManager packageManager;
    public final PackageManager packageManager;
@@ -200,6 +201,7 @@ public class MockSystemServices {
        devicePolicyManager = mock(DevicePolicyManager.class);
        devicePolicyManager = mock(DevicePolicyManager.class);
        locationManager = mock(LocationManager.class);
        locationManager = mock(LocationManager.class);
        roleManager = realContext.getSystemService(RoleManager.class);
        roleManager = realContext.getSystemService(RoleManager.class);
        roleManagerForMock = mock(RoleManagerForMock.class);
        subscriptionManager = mock(SubscriptionManager.class);
        subscriptionManager = mock(SubscriptionManager.class);


        // Package manager is huge, so we use a partial mock instead.
        // 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 static class SettingsForMock {
        public int settingsSecureGetIntForUser(String name, int def, int userHandle) {
        public int settingsSecureGetIntForUser(String name, int def, int userHandle) {
            return 0;
            return 0;