diff options
4 files changed, 132 insertions, 11 deletions
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 117c6634d939..788c44a75249 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -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); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 6ec0ba11517d..9cfa18345df5 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -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); } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 6d168b0abb5a..212b37cebead 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -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; @@ -208,7 +210,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { /** * Test for: * {@link DevicePolicyManager#setActiveAdmin} - * with replace=false and replace=true + * with replace=false and replace=true * {@link DevicePolicyManager#isAdminActive} * {@link DevicePolicyManager#isAdminActiveAsUser} * {@link DevicePolicyManager#getActiveAdmins} @@ -336,7 +338,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { /** * Test for: * {@link DevicePolicyManager#setActiveAdmin} - * with replace=false + * with replace=false */ public void testSetActiveAdmin_twiceWithoutReplace() throws Exception { // 1. Make sure the caller has proper permissions. @@ -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. @@ -1196,7 +1199,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(), MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER) - ); + ); reset(mContext.userManagerInternal); dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS); @@ -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. + } } + diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java index 7a000985a5ca..ef8e420e53f0 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java @@ -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); |