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

Commit d932f768 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Refactor DPMS tests to be able to test more different cases.

- DpmMockContext.addUser() allows to create more users.  This will set up
UserManager properly and create a data directory.

- Updated DevicePolicyManagerTest so it can now easily emulate calls from
different secondary users.

Change-Id: Ic9d3e8d0d1e7f41e184c82e6dc323c244535b8d8
parent b4a6d984
Loading
Loading
Loading
Loading
+6 −18
Original line number Diff line number Diff line
@@ -50,11 +50,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
        private final File mDeviceOwnerFile;
        private final File mProfileOwnerBase;

        public OwnersTestable(Context context, File dataDir) {
        public OwnersTestable(DpmMockContext context) {
            super(context);
            mLegacyFile = new File(dataDir, LEGACY_FILE);
            mDeviceOwnerFile = new File(dataDir, DEVICE_OWNER_FILE);
            mProfileOwnerBase = new File(dataDir, PROFILE_OWNER_FILE_BASE);
            mLegacyFile = new File(context.dataDir, LEGACY_FILE);
            mDeviceOwnerFile = new File(context.dataDir, DEVICE_OWNER_FILE);
            mProfileOwnerBase = new File(context.dataDir, PROFILE_OWNER_FILE_BASE);
        }

        @Override
@@ -90,27 +90,15 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi

        public final File dataDir;

        public final File systemUserDataDir;
        public final File secondUserDataDir;

        private MockInjector(DpmMockContext context, File dataDir) {
            super(context);
            this.context = context;
            this.dataDir = dataDir;

            systemUserDataDir = new File(dataDir, "user0");
            DpmTestUtils.clearDir(dataDir);

            secondUserDataDir = new File(dataDir, "user" + DpmMockContext.CALLER_USER_HANDLE);
            DpmTestUtils.clearDir(secondUserDataDir);

            when(context.environment.getUserSystemDirectory(
                    eq(DpmMockContext.CALLER_USER_HANDLE))).thenReturn(secondUserDataDir);
        }

        @Override
        Owners newOwners() {
            return new OwnersTestable(context, dataDir);
            return new OwnersTestable(context);
        }

        @Override
@@ -165,7 +153,7 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi

        @Override
        String getDevicePolicyFilePathForSystemUser() {
            return systemUserDataDir.getAbsolutePath();
            return context.systemUserDataDir.getAbsolutePath();
        }

        @Override
+66 −30
Original line number Diff line number Diff line
@@ -91,11 +91,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
        admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);

        setUpPackageManagerForAdmin(admin1);
        setUpPackageManagerForAdmin(admin2);
        setUpPackageManagerForAdmin(admin3);
        setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
        setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID);
        setUpPackageManagerForAdmin(admin3, DpmMockContext.CALLER_UID);

        setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
                DpmMockContext.CALLER_UID);

        setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
        setUpPackageInfo();
        setUpUserManager();
    }
@@ -105,7 +107,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
     * the actual ResolveInfo for the admin component, but we need to mock PM so it'll return
     * it for user {@link DpmMockContext#CALLER_USER_HANDLE}.
     */
    private void setUpPackageManagerForAdmin(ComponentName admin) {
    private void setUpPackageManagerForAdmin(ComponentName admin, int packageUid) {
        final Intent resolveIntent = new Intent();
        resolveIntent.setComponent(admin);
        final List<ResolveInfo> realResolveInfo =
@@ -115,32 +117,36 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        assertNotNull(realResolveInfo);
        assertEquals(1, realResolveInfo.size());

        // We need to change AI, so set a clone.
        realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));

        // We need to rewrite the UID in the activity info.
        realResolveInfo.get(0).activityInfo.applicationInfo.uid = DpmMockContext.CALLER_UID;
        realResolveInfo.get(0).activityInfo.applicationInfo.uid = packageUid;

        doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
                MockUtils.checkIntentComponent(admin),
                eq(PackageManager.GET_META_DATA
                        | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
                eq(DpmMockContext.CALLER_USER_HANDLE)
        );
                eq(UserHandle.getUserId(packageUid)));
    }

    /**
     * Set up a mock result for {@link IPackageManager#getApplicationInfo} for user
     * {@link DpmMockContext#CALLER_USER_HANDLE}.
     */
    private void setUpApplicationInfo(int enabledSetting) throws Exception {
        final ApplicationInfo ai = mRealTestContext.getPackageManager().getApplicationInfo(
    private void setUpApplicationInfo(int enabledSetting, int packageUid) throws Exception {
        final ApplicationInfo ai = DpmTestUtils.cloneParcelable(
                mRealTestContext.getPackageManager().getApplicationInfo(
                        admin1.getPackageName(),
                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
                        PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));

        ai.enabledSetting = enabledSetting;
        ai.uid = packageUid;

        doReturn(ai).when(mContext.ipackageManager).getApplicationInfo(
                eq(admin1.getPackageName()),
                eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
                eq(DpmMockContext.CALLER_USER_HANDLE));
                eq(UserHandle.getUserId(packageUid)));
    }

    /**
@@ -193,16 +199,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        }).when(mContext.userManager).getApplicationRestrictions(
                anyString(), any(UserHandle.class));

        // System user is always running.
        when(mContext.userManager.isUserRunning(MockUtils.checkUserHandle(UserHandle.USER_SYSTEM)))
                .thenReturn(true);

        // Set up (default) UserInfo for CALLER_USER_HANDLE.
        final UserInfo uh = new UserInfo(DpmMockContext.CALLER_USER_HANDLE,
                "user" + DpmMockContext.CALLER_USER_HANDLE, 0);

        when(mContext.userManager.getUserInfo(eq(DpmMockContext.CALLER_USER_HANDLE)))
                .thenReturn(uh);
        // Add the first secondary user.
        mContext.addUser(DpmMockContext.CALLER_USER_HANDLE, 0);
    }

    private void setAsProfileOwner(ComponentName admin) {
@@ -309,7 +307,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Next, add one more admin.
        // Before doing so, update the application info, now it's enabled.
        setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
        setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                DpmMockContext.CALLER_UID);

        dpm.setActiveAdmin(admin2, /* replace =*/ false);

@@ -354,6 +353,35 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
    }

    public void testSetActiveAdmin_multiUsers() throws Exception {

        final int ANOTHER_USER_ID = 100;
        final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 20456);

        mMockContext.addUser(ANOTHER_USER_ID, 0); // Add one more user.

        // Set up pacakge manager for the other user.
        setUpPackageManagerForAdmin(admin2, ANOTHER_ADMIN_UID);
        setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
                ANOTHER_ADMIN_UID);

        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);

        dpm.setActiveAdmin(admin1, /* replace =*/ false);

        mMockContext.binder.callingUid = ANOTHER_ADMIN_UID;
        dpm.setActiveAdmin(admin2, /* replace =*/ false);


        mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
        assertTrue(dpm.isAdminActive(admin1));
        assertFalse(dpm.isAdminActive(admin2));

        mMockContext.binder.callingUid = ANOTHER_ADMIN_UID;
        assertFalse(dpm.isAdminActive(admin1));
        assertTrue(dpm.isAdminActive(admin2));
    }

    /**
     * Test for:
     * {@link DevicePolicyManager#setActiveAdmin}
@@ -400,9 +428,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        // having MANAGE_DEVICE_ADMINS.
        mContext.callerPermissions.clear();

        // Change the caller, and call into DPMS directly with a different user-id.

        mContext.binder.callingUid = 1234567;
        try {
            dpm.removeActiveAdmin(admin1);
            dpms.removeActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE);
            fail("Didn't throw SecurityException");
        } catch (SecurityException expected) {
        }
@@ -412,7 +442,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
     * Test for:
     * {@link DevicePolicyManager#removeActiveAdmin}
     */
    public void testRemoveActiveAdmin_fromDifferentUserWithMINTERACT_ACROSS_USERS_FULL() {
    public void testRemoveActiveAdmin_fromDifferentUserWithINTERACT_ACROSS_USERS_FULL() {
        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);

        // Add admin1.
@@ -424,8 +454,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        // Different user, but should work, because caller has proper permissions.
        mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);

        // Change the caller, and call into DPMS directly with a different user-id.
        mContext.binder.callingUid = 1234567;
        dpm.removeActiveAdmin(admin1);

        dpms.removeActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE);

        assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));

@@ -498,9 +531,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
        mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);

        // Call from a process on the system user.
        // In this test, change the caller user to "system".
        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;

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

        // DO needs to be an DA.
        dpm.setActiveAdmin(admin1, /* replace =*/ false);

@@ -536,8 +574,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        // Call from a process on the system user.
        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;

        // DO needs to be an DA.
        dpm.setActiveAdmin(admin1, /* replace =*/ false);
        try {
            dpm.setDeviceOwner("a.b.c");
            fail("Didn't throw IllegalArgumentException");
+2 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.server.devicepolicy;

import android.app.admin.DevicePolicyManager;
import android.os.UserHandle;

/**
 * Overrides {@link #DevicePolicyManager} for dependency injection.
@@ -31,6 +32,6 @@ public class DevicePolicyManagerTestable extends DevicePolicyManager {

    @Override
    public int myUserId() {
        return DpmMockContext.CALLER_USER_HANDLE;
        return UserHandle.getUserId(dpms.context.binder.callingUid);
    }
}
+48 −3
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.media.IAudioService;
import android.os.Bundle;
import android.os.Handler;
@@ -43,8 +44,10 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

/**
 * Context used throughout DPMS tests.
@@ -58,12 +61,12 @@ public class DpmMockContext extends MockContext {
    /**
     * UID corresponding to {@link #CALLER_USER_HANDLE}.
     */
    public static final int CALLER_UID = UserHandle.PER_USER_RANGE * CALLER_USER_HANDLE + 123;
    public static final int CALLER_UID = UserHandle.getUid(CALLER_USER_HANDLE, 20123);

    /**
     * UID used when a caller is on the system user.
     */
    public static final int CALLER_SYSTEM_USER_UID = 123;
    public static final int CALLER_SYSTEM_USER_UID = 20321;

    /**
     * PID of the caller.
@@ -164,6 +167,9 @@ public class DpmMockContext extends MockContext {
     */
    public final Context spiedContext;

    public final File dataDir;
    public final File systemUserDataDir;

    public final MockBinder binder;
    public final EnvironmentForMock environment;
    public final SystemPropertiesForMock systemProperties;
@@ -184,8 +190,14 @@ public class DpmMockContext extends MockContext {

    public final List<String> callerPermissions = new ArrayList<>();

    public DpmMockContext(Context context) {
    private final ArrayList<UserInfo> mUserInfos = new ArrayList<>();

    public DpmMockContext(Context context, File dataDir) {
        realTestContext = context;

        this.dataDir = dataDir;
        DpmTestUtils.clearDir(dataDir);

        binder = new MockBinder();
        environment = mock(EnvironmentForMock.class);
        systemProperties= mock(SystemPropertiesForMock.class);
@@ -205,6 +217,39 @@ public class DpmMockContext extends MockContext {
        packageManager = spy(context.getPackageManager());

        spiedContext = mock(Context.class);

        // Add the system user
        systemUserDataDir = addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY);

        // System user is always running.
        when(userManager.isUserRunning(MockUtils.checkUserHandle(UserHandle.USER_SYSTEM)))
                .thenReturn(true);
    }

    public File addUser(int userId, int flags) {

        // Set up (default) UserInfo for CALLER_USER_HANDLE.
        final UserInfo uh = new UserInfo(userId, "user" + userId, flags);
        when(userManager.getUserInfo(eq(userId))).thenReturn(uh);

        mUserInfos.add(uh);
        when(userManager.getUsers()).thenReturn(mUserInfos);

        // Create a data directory.
        final File dir = new File(dataDir, "user" + userId);
        DpmTestUtils.clearDir(dir);

        when(environment.getUserSystemDirectory(eq(userId))).thenReturn(dir);
        return dir;
    }

    /**
     * Add multiple users at once.  They'll all have flag 0.
     */
    public void addUsers(int... userIds) {
        for (int userId : userIds) {
            addUser(userId, 0);
        }
    }

    @Override
+2 −3
Original line number Diff line number Diff line
@@ -34,10 +34,9 @@ public abstract class DpmTestBase extends AndroidTestCase {
        super.setUp();

        mRealTestContext = super.getContext();
        mMockContext = new DpmMockContext(super.getContext());

        dataDir = new File(mRealTestContext.getCacheDir(), "test-data");
        DpmTestUtils.clearDir(dataDir);
        mMockContext = new DpmMockContext(
                mRealTestContext, new File(mRealTestContext.getCacheDir(), "test-data"));
    }

    @Override
Loading