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

Commit 43769ddb authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add DISALLOW_ADD_MANAGED_PROFILE to existing device owners"

parents 37d37f0f 548a04b8
Loading
Loading
Loading
Loading
+82 −52
Original line number Diff line number Diff line
@@ -188,6 +188,7 @@ import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -632,6 +633,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        private static final String TAG_PACKAGE_LIST_ITEM  = "item";
        private static final String TAG_KEEP_UNINSTALLED_PACKAGES  = "keep-uninstalled-packages";
        private static final String TAG_USER_RESTRICTIONS = "user-restrictions";
        private static final String TAG_DEFAULT_ENABLED_USER_RESTRICTIONS =
                "default-enabled-user-restrictions";
        private static final String TAG_RESTRICTION = "restriction";
        private static final String TAG_SHORT_SUPPORT_MESSAGE = "short-support-message";
        private static final String TAG_LONG_SUPPORT_MESSAGE = "long-support-message";
        private static final String TAG_PARENT_ADMIN = "parent-admin";
@@ -704,7 +708,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
        }

        Set<String> accountTypesWithManagementDisabled = new ArraySet<>();
        final Set<String> accountTypesWithManagementDisabled = new ArraySet<>();

        // The list of permitted accessibility services package namesas set by a profile
        // or device owner. Null means all accessibility services are allowed, empty means
@@ -730,6 +734,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

        Bundle userRestrictions;

        // User restrictions that have already been enabled by default for this admin (either when
        // setting the device or profile owner, or during a system update if one of those "enabled
        // by default" restrictions is newly added).
        final Set<String> defaultEnabledRestrictionsAlreadySet = new ArraySet<>();

        // Support text provided by the admin to display to the user.
        CharSequence shortSupportMessage = null;
        CharSequence longSupportMessage = null;
@@ -925,11 +934,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            if (!accountTypesWithManagementDisabled.isEmpty()) {
                out.startTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT);
                for (String ac : accountTypesWithManagementDisabled) {
                    out.startTag(null, TAG_ACCOUNT_TYPE);
                    out.attribute(null, ATTR_VALUE, ac);
                    out.endTag(null, TAG_ACCOUNT_TYPE);
                }
                writeAttributeValuesToXml(
                        out, TAG_ACCOUNT_TYPE, accountTypesWithManagementDisabled);
                out.endTag(null,  TAG_DISABLE_ACCOUNT_MANAGEMENT);
            }
            if (!trustAgentInfos.isEmpty()) {
@@ -954,13 +960,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            if (crossProfileWidgetProviders != null && !crossProfileWidgetProviders.isEmpty()) {
                out.startTag(null, TAG_CROSS_PROFILE_WIDGET_PROVIDERS);
                final int providerCount = crossProfileWidgetProviders.size();
                for (int i = 0; i < providerCount; i++) {
                    String provider = crossProfileWidgetProviders.get(i);
                    out.startTag(null, TAG_PROVIDER);
                    out.attribute(null, ATTR_VALUE, provider);
                    out.endTag(null, TAG_PROVIDER);
                }
                writeAttributeValuesToXml(out, TAG_PROVIDER, crossProfileWidgetProviders);
                out.endTag(null, TAG_CROSS_PROFILE_WIDGET_PROVIDERS);
            }
            writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
@@ -971,6 +971,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                UserRestrictionsUtils.writeRestrictions(
                        out, userRestrictions, TAG_USER_RESTRICTIONS);
            }
            if (!defaultEnabledRestrictionsAlreadySet.isEmpty()) {
                out.startTag(null, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS);
                writeAttributeValuesToXml(
                        out, TAG_RESTRICTION, defaultEnabledRestrictionsAlreadySet);
                out.endTag(null, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS);
            }
            if (!TextUtils.isEmpty(shortSupportMessage)) {
                out.startTag(null, TAG_SHORT_SUPPORT_MESSAGE);
                out.text(shortSupportMessage.toString());
@@ -1006,14 +1012,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }

            out.startTag(null, outerTag);
            for (String packageName : packageList) {
                out.startTag(null, TAG_PACKAGE_LIST_ITEM);
                out.attribute(null, ATTR_VALUE, packageName);
                out.endTag(null, TAG_PACKAGE_LIST_ITEM);
            }
            writeAttributeValuesToXml(out, TAG_PACKAGE_LIST_ITEM, packageList);
            out.endTag(null, outerTag);
        }

        void writeAttributeValuesToXml(XmlSerializer out, String tag,
                @NonNull Collection<String> values) throws IOException {
            for (String value : values) {
                out.startTag(null, tag);
                out.attribute(null, ATTR_VALUE, value);
                out.endTag(null, tag);
            }
        }

        void readFromXml(XmlPullParser parser)
                throws XmlPullParserException, IOException {
            int outerDepth = parser.getDepth();
@@ -1115,11 +1126,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    disabledKeyguardFeatures = Integer.parseInt(
                            parser.getAttributeValue(null, ATTR_VALUE));
                } else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
                    accountTypesWithManagementDisabled = readDisableAccountInfo(parser, tag);
                    readAttributeValues(
                            parser, TAG_ACCOUNT_TYPE, accountTypesWithManagementDisabled);
                } else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
                    trustAgentInfos = getAllTrustAgentInfos(parser, tag);
                } else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
                    crossProfileWidgetProviders = getCrossProfileWidgetProviders(parser, tag);
                    crossProfileWidgetProviders = new ArrayList<>();
                    readAttributeValues(parser, TAG_PROVIDER, crossProfileWidgetProviders);
                } else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
                    permittedAccessiblityServices = readPackageList(parser, tag);
                } else if (TAG_PERMITTED_IMES.equals(tag)) {
@@ -1128,6 +1141,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    keepUninstalledPackages = readPackageList(parser, tag);
                } else if (TAG_USER_RESTRICTIONS.equals(tag)) {
                    UserRestrictionsUtils.readRestrictions(parser, ensureUserRestrictions());
                } else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) {
                    readAttributeValues(
                            parser, TAG_RESTRICTION, defaultEnabledRestrictionsAlreadySet);
                } else if (TAG_SHORT_SUPPORT_MESSAGE.equals(tag)) {
                    type = parser.next();
                    if (type == XmlPullParser.TEXT) {
@@ -1189,24 +1205,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return result;
        }

        private Set<String> readDisableAccountInfo(XmlPullParser parser, String tag)
        private void readAttributeValues(
                XmlPullParser parser, String tag, Collection<String> result)
                throws XmlPullParserException, IOException {
            result.clear();
            int outerDepthDAM = parser.getDepth();
            int typeDAM;
            Set<String> result = new ArraySet<>();
            while ((typeDAM=parser.next()) != END_DOCUMENT
                    && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
                if (typeDAM == END_TAG || typeDAM == TEXT) {
                    continue;
                }
                String tagDAM = parser.getName();
                if (TAG_ACCOUNT_TYPE.equals(tagDAM)) {
                if (tag.equals(tagDAM)) {
                    result.add(parser.getAttributeValue(null, ATTR_VALUE));
                } else {
                    Slog.w(LOG_TAG, "Unknown tag under " + tag +  ": " + tagDAM);
                    Slog.e(LOG_TAG, "Expected tag " + tag +  " but found " + tagDAM);
                }
            }
            return result;
        }

        private ArrayMap<String, TrustAgentInfo> getAllTrustAgentInfos(
@@ -1251,30 +1267,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return result;
        }

        private List<String> getCrossProfileWidgetProviders(XmlPullParser parser, String tag)
                throws XmlPullParserException, IOException  {
            int outerDepthDAM = parser.getDepth();
            int typeDAM;
            ArrayList<String> result = null;
            while ((typeDAM=parser.next()) != END_DOCUMENT
                    && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
                if (typeDAM == END_TAG || typeDAM == TEXT) {
                    continue;
                }
                String tagDAM = parser.getName();
                if (TAG_PROVIDER.equals(tagDAM)) {
                    final String provider = parser.getAttributeValue(null, ATTR_VALUE);
                    if (result == null) {
                        result = new ArrayList<>();
                    }
                    result.add(provider);
                } else {
                    Slog.w(LOG_TAG, "Unknown tag under " + tag +  ": " + tagDAM);
                }
            }
            return result;
        }

        boolean hasUserRestrictions() {
            return userRestrictions != null && userRestrictions.size() > 0;
        }
@@ -1377,6 +1369,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            pw.print(prefix); pw.println("userRestrictions:");
            UserRestrictionsUtils.dumpRestrictions(pw, prefix + "  ", userRestrictions);
            pw.print(prefix); pw.print("defaultEnabledRestrictionsAlreadySet=");
                    pw.println(defaultEnabledRestrictionsAlreadySet);
            pw.print(prefix); pw.print("isParent=");
                    pw.println(isParent);
            if (parentAdmin != null) {
@@ -1802,6 +1796,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            setDeviceOwnerSystemPropertyLocked();
            findOwnerComponentIfNecessaryLocked();
            migrateUserRestrictionsIfNecessaryLocked();
            setDefaultEnabledUserRestrictionsIfNecessaryLocked();

            // TODO PO may not have a class name either due to b/17652534.  Address that too.

@@ -1809,6 +1804,36 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    private void setDefaultEnabledUserRestrictionsIfNecessaryLocked() {
        final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
        if (deviceOwner != null
                && !UserRestrictionsUtils.getDefaultEnabledForDeviceOwner().equals(
                        deviceOwner.defaultEnabledRestrictionsAlreadySet)) {
            Slog.i(LOG_TAG,"New user restrictions need to be set by default for the device owner");

            if (VERBOSE_LOG) {
                Slog.d(LOG_TAG,"Default enabled restrictions for DO: "
                        + UserRestrictionsUtils.getDefaultEnabledForDeviceOwner()
                        + ". Restrictions already enabled: "
                        + deviceOwner.defaultEnabledRestrictionsAlreadySet);
            }

            Set<String> restrictionsToSet = new ArraySet<>(
                    UserRestrictionsUtils.getDefaultEnabledForDeviceOwner());
            restrictionsToSet.removeAll(deviceOwner.defaultEnabledRestrictionsAlreadySet);
            if (!restrictionsToSet.isEmpty()) {
                for (String restriction : restrictionsToSet) {
                    deviceOwner.ensureUserRestrictions().putBoolean(restriction, true);
                }
                deviceOwner.defaultEnabledRestrictionsAlreadySet.addAll(restrictionsToSet);
                Slog.i(LOG_TAG,
                        "Enabled the following restrictions by default: " + restrictionsToSet);

                saveUserRestrictionsLocked(mOwners.getDeviceOwnerUserId());
            }
        }
    }

    private void setDeviceOwnerSystemPropertyLocked() {
        // Device owner may still be provisioned, do not set the read-only system property yet.
        if (mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
@@ -3455,7 +3480,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        synchronized (this) {
            ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
            if (activeAdmin.crossProfileWidgetProviders == null) {
            if (activeAdmin.crossProfileWidgetProviders == null
                    || activeAdmin.crossProfileWidgetProviders.isEmpty()) {
                return false;
            }
            List<String> providers = activeAdmin.crossProfileWidgetProviders;
@@ -5983,13 +6009,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            updateDeviceOwnerLocked();
            setDeviceOwnerSystemPropertyLocked();

            // STOPSHIP(b/31952368) Also set this restriction for existing DOs on OTA to Android OC.
            final Set<String> restrictions =
                    UserRestrictionsUtils.getDefaultEnabledForDeviceOwner();
            if (!restrictions.isEmpty()) {
                for (String restriction : restrictions) {
                    activeAdmin.ensureUserRestrictions().putBoolean(restriction, true);
                }
                activeAdmin.defaultEnabledRestrictionsAlreadySet.addAll(restrictions);
                Slog.i(LOG_TAG, "Enabled the following restrictions by default: " + restrictions);

                saveUserRestrictionsLocked(userId);
            }

@@ -6090,7 +6118,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    // Returns the active device owner or null if there is no device owner.
    /** Returns the active device owner or {@code null} if there is no device owner. */
    @VisibleForTesting
    ActiveAdmin getDeviceOwnerAdminLocked() {
        ComponentName component = mOwners.getDeviceOwnerComponent();
@@ -6152,6 +6180,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        if (admin != null) {
            admin.disableCamera = false;
            admin.userRestrictions = null;
            admin.defaultEnabledRestrictionsAlreadySet.clear();
            admin.forceEphemeralUsers = false;
            mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
            final DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
@@ -6235,6 +6264,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        if (admin != null) {
            admin.disableCamera = false;
            admin.userRestrictions = null;
            admin.defaultEnabledRestrictionsAlreadySet.clear();
        }
        clearUserPoliciesLocked(userId);
        mOwners.removeProfileOwner(userId);
+115 −19
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.reset;
@@ -1205,21 +1206,18 @@ public class DevicePolicyManagerTest extends DpmTestBase {
                DpmTestUtils.newRestrictions(defaultRestrictions),
                dpm.getUserRestrictions(admin1)
        );
        verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
                eq(UserHandle.USER_SYSTEM),
                MockUtils.checkUserRestrictions(),
                MockUtils.checkUserRestrictions(defaultRestrictions)
        );
        reset(mContext.userManagerInternal);

        for (String restriction : defaultRestrictions) {
            dpm.clearUserRestriction(admin1, restriction);
        }

        DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(),
                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
        );
        DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(),
                dpm.getUserRestrictions(admin1)
        );

        reset(mContext.userManagerInternal);
        assertNoDeviceOwnerRestrictions();

        dpm.addUserRestriction(admin1, UserManager.DISALLOW_ADD_USER);
        verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
@@ -1273,14 +1271,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        );
        reset(mContext.userManagerInternal);

        DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(),
                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
        );
        DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(),
                dpm.getUserRestrictions(admin1)
        );
        assertNoDeviceOwnerRestrictions();

        // DISALLOW_ADJUST_VOLUME and DISALLOW_UNMUTE_MICROPHONE are PO restrictions, but when
        // DO sets them, the scope is global.
@@ -1455,6 +1446,111 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        // TODO Make sure restrictions are written to the file.
    }


    public void testDefaultEnabledUserRestrictions() throws Exception {
        mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
        mContext.callerPermissions.add(permission.MANAGE_USERS);
        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
        mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);

        // First, set DO.

        // Call from a process on the system user.
        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;

        // Make sure admin1 is installed on system user.
        setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);

        dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
        assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
                UserHandle.USER_SYSTEM));

        // Check that the user restrictions that are enabled by default are set. Then unset them.
        String[] defaultRestrictions = UserRestrictionsUtils
                .getDefaultEnabledForDeviceOwner().toArray(new String[0]);
        assertTrue(defaultRestrictions.length > 0);
        DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(defaultRestrictions),
                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
        );
        DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(defaultRestrictions),
                dpm.getUserRestrictions(admin1)
        );
        verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
                eq(UserHandle.USER_SYSTEM),
                MockUtils.checkUserRestrictions(),
                MockUtils.checkUserRestrictions(defaultRestrictions)
        );
        reset(mContext.userManagerInternal);

        for (String restriction : defaultRestrictions) {
            dpm.clearUserRestriction(admin1, restriction);
        }

        assertNoDeviceOwnerRestrictions();

        // Initialize DPMS again and check that the user restriction wasn't enabled again.
        reset(mContext.userManagerInternal);
        initializeDpms();
        assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
        assertNotNull(dpms.getDeviceOwnerAdminLocked());

        assertNoDeviceOwnerRestrictions();

        // Add a new restriction to the default set, initialize DPMS, and check that the restriction
        // is set as it wasn't enabled during setDeviceOwner.
        final String newDefaultEnabledRestriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
        assertFalse(UserRestrictionsUtils
                .getDefaultEnabledForDeviceOwner().contains(newDefaultEnabledRestriction));
        UserRestrictionsUtils
                .getDefaultEnabledForDeviceOwner().add(newDefaultEnabledRestriction);
        try {
            reset(mContext.userManagerInternal);
            initializeDpms();
            assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
            assertNotNull(dpms.getDeviceOwnerAdminLocked());

            DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(newDefaultEnabledRestriction),
                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
            );
            DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(newDefaultEnabledRestriction),
                dpm.getUserRestrictions(admin1)
            );
            verify(mContext.userManagerInternal, atLeast(1)).setDevicePolicyUserRestrictions(
                eq(UserHandle.USER_SYSTEM),
                MockUtils.checkUserRestrictions(),
                MockUtils.checkUserRestrictions(newDefaultEnabledRestriction)
            );
            reset(mContext.userManagerInternal);

            // Remove the restriction.
            dpm.clearUserRestriction(admin1, newDefaultEnabledRestriction);

            // Initialize DPMS again. The restriction shouldn't be enabled for a second time.
            initializeDpms();
            assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
            assertNotNull(dpms.getDeviceOwnerAdminLocked());
            assertNoDeviceOwnerRestrictions();
        } finally {
            UserRestrictionsUtils
                .getDefaultEnabledForDeviceOwner().remove(newDefaultEnabledRestriction);
        }
    }

    private void assertNoDeviceOwnerRestrictions() {
        DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(),
                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
        );
        DpmTestUtils.assertRestrictions(
                DpmTestUtils.newRestrictions(),
                dpm.getUserRestrictions(admin1)
        );
    }

    public void testGetMacAddress() throws Exception {
        mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);