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

Commit 2a3c3da0 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Clean up on UserManagerService and DPMS

- Avoid the ART warning about 4.1 compatibility
- Avoid integer overflow in DPMS

Bug 27243525
Bug 27242859

Change-Id: I92af323287e348fbd0eff31e6cf9823be8e41024
parent 0bc3cc9c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -840,7 +840,7 @@ public class UserManagerService extends IUserManager.Stub {
    /**
     * See {@link UserManagerInternal#setDevicePolicyUserRestrictions(int, Bundle, Bundle)}
     */
    void setDevicePolicyUserRestrictions(int userId, @NonNull Bundle local,
    void setDevicePolicyUserRestrictionsInner(int userId, @NonNull Bundle local,
            @Nullable Bundle global) {
        Preconditions.checkNotNull(local);
        boolean globalChanged = false;
@@ -2854,7 +2854,7 @@ public class UserManagerService extends IUserManager.Stub {
        @Override
        public void setDevicePolicyUserRestrictions(int userId, @NonNull Bundle localRestrictions,
                @Nullable Bundle globalRestrictions) {
            UserManagerService.this.setDevicePolicyUserRestrictions(userId, localRestrictions,
            UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, localRestrictions,
                    globalRestrictions);
        }

+4 −5
Original line number Diff line number Diff line
@@ -3874,7 +3874,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        // challenge only and keep the screen on. However there is no easy way of doing that at the
        // moment so we set the screen off timeout regardless of whether it affects the parent user
        // or the profile challenge only.
        long timeMs = Integer.MAX_VALUE;
        long timeMs = Long.MAX_VALUE;
        List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
        for (UserInfo userInfo : profiles) {
            DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
@@ -3898,15 +3898,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

        final long ident = mInjector.binderClearCallingIdentity();
        try {
            if (policy.mLastMaximumTimeToLock != Integer.MAX_VALUE) {
            if (policy.mLastMaximumTimeToLock != Long.MAX_VALUE) {
                // Make sure KEEP_SCREEN_ON is disabled, since that
                // would allow bypassing of the maximum time to lock.
                mInjector.settingsGlobalPutInt(Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
            }

            // TODO It can overflow.  Cap it.
            mInjector.getPowerManagerInternal()
                    .setMaximumScreenOffTimeoutFromDeviceAdmin((int)policy.mLastMaximumTimeToLock);
            mInjector.getPowerManagerInternal().setMaximumScreenOffTimeoutFromDeviceAdmin(
                    (int) Math.min(policy.mLastMaximumTimeToLock, Integer.MAX_VALUE));
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
        }
+79 −4
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
@@ -60,6 +61,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -999,7 +1001,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {

    /**
     * This essentially tests
     * {@code DevicePolicyManagerService.findOwnerComponentIfNecessaryLocked()}. (which is private.)
     * {@code DevicePolicyManagerService.findOwnerComponentIfNecessaryLocked()}. (which is
     * private.)
     *
     * We didn't use to persist the DO component class name, but now we do, and the above method
     * finds the right component from a package name upon migration.
@@ -1833,4 +1836,76 @@ public class DevicePolicyManagerTest extends DpmTestBase {

        mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
    }

    public void testSetMaximumTimeToLock() {
        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);

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

        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin1, 0);
        verifyScreenTimeoutCall(null, false);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin1, 1);
        verifyScreenTimeoutCall(1, true);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin2, 10);
        verifyScreenTimeoutCall(null, false);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin1, 5);
        verifyScreenTimeoutCall(5, true);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin2, 4);
        verifyScreenTimeoutCall(4, true);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin1, 0);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin2, Integer.MAX_VALUE);
        verifyScreenTimeoutCall(Integer.MAX_VALUE, true);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin2, Integer.MAX_VALUE + 1);
        verifyScreenTimeoutCall(Integer.MAX_VALUE, true);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        dpm.setMaximumTimeToLock(admin2, 10);
        verifyScreenTimeoutCall(10, true);
        reset(mMockContext.powerManagerInternal);
        reset(mMockContext.settings);

        // There's no restriction; shold be set to MAX.
        dpm.setMaximumTimeToLock(admin2, 0);
        verifyScreenTimeoutCall(Integer.MAX_VALUE, false);
    }

    private void verifyScreenTimeoutCall(Integer expectedTimeout,
            boolean shouldStayOnWhilePluggedInBeCleared) {
        if (expectedTimeout == null) {
            verify(mMockContext.powerManagerInternal, times(0))
                    .setMaximumScreenOffTimeoutFromDeviceAdmin(anyInt());
        } else {
            verify(mMockContext.powerManagerInternal, times(1))
                    .setMaximumScreenOffTimeoutFromDeviceAdmin(eq(expectedTimeout));
        }
        // TODO Verify calls to settingsGlobalPutInt.  Tried but somehow mockito threw
        // UnfinishedVerificationException.
    }
}
+47 −0
Original line number Diff line number Diff line
@@ -44,11 +44,14 @@ import android.test.mock.MockContext;
import android.view.IWindowManager;

import org.junit.Assert;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -294,6 +297,50 @@ public class DpmMockContext extends MockContext {

        mUserInfos.add(uh);
        when(userManager.getUsers()).thenReturn(mUserInfos);
        when(userManager.getUserInfo(anyInt())).thenAnswer(
                new Answer<UserInfo>() {
                    @Override
                    public UserInfo answer(InvocationOnMock invocation) throws Throwable {
                        final int userId = (int) invocation.getArguments()[0];
                        for (UserInfo ui : mUserInfos) {
                            if (ui.id == userId) {
                                return ui;
                            }
                        }
                        return null;
                    }
                }
        );
        when(userManager.getProfiles(anyInt())).thenAnswer(
                new Answer<List<UserInfo>>() {
                    @Override
                    public List<UserInfo> answer(InvocationOnMock invocation) throws Throwable {
                        final int userId = (int) invocation.getArguments()[0];
                        final ArrayList<UserInfo> ret = new ArrayList<UserInfo>();
                        UserInfo parent = null;
                        for (UserInfo ui : mUserInfos) {
                            if (ui.id == userId) {
                                parent = ui;
                                break;
                            }
                        }
                        if (parent == null) {
                            return ret;
                        }
                        ret.add(parent);
                        for (UserInfo ui : mUserInfos) {
                            if (ui.id == userId) {
                                continue;
                            }
                            if (ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
                                    && ui.profileGroupId == parent.profileGroupId) {
                                ret.add(ui);
                            }
                        }
                        return ret;
                    }
                }
        );

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