diff options
| author | 2019-01-23 10:55:33 +0000 | |
|---|---|---|
| committer | 2019-01-23 10:55:33 +0000 | |
| commit | eea1710cda18b5dfb76755f9708cc5e2d2bf1f4d (patch) | |
| tree | dcef45830578e522a21e4f6d1bc1d09076bb3d37 /services | |
| parent | d133e9f40c24fc83661164390a8d1eaafe5d37ed (diff) | |
| parent | 66c492a87efedfa4dfd25b3561ad9c9daafc4ee3 (diff) | |
Merge "Add a feature flag for secure lock screen."
Diffstat (limited to 'services')
8 files changed, 200 insertions, 20 deletions
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 8734ceb614a9..a9ae74f67de7 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -947,6 +947,10 @@ public class LockSettingsService extends ILockSettings.Stub { public void setSeparateProfileChallengeEnabled(int userId, boolean enabled, String managedUserPassword) { checkWritePermission(userId); + if (!mLockPatternUtils.hasSecureLockScreen()) { + throw new UnsupportedOperationException( + "This operation requires secure lock screen feature."); + } synchronized (mSeparateChallengeLock) { setSeparateProfileChallengeEnabledLocked(userId, enabled, managedUserPassword); } @@ -1305,6 +1309,10 @@ public class LockSettingsService extends ILockSettings.Stub { public void setLockCredential(String credential, int type, String savedCredential, int requestedQuality, int userId) throws RemoteException { + if (!mLockPatternUtils.hasSecureLockScreen()) { + throw new UnsupportedOperationException( + "This operation requires secure lock screen feature"); + } checkWritePermission(userId); synchronized (mSeparateChallengeLock) { setLockCredentialInternal(credential, type, savedCredential, requestedQuality, userId); @@ -2906,6 +2914,10 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle, byte[] token, int requestedQuality, int userId) { + if (!mLockPatternUtils.hasSecureLockScreen()) { + throw new UnsupportedOperationException( + "This operation requires secure lock screen feature."); + } try { return LockSettingsService.this.setLockCredentialWithToken(credential, type, tokenHandle, token, requestedQuality, userId); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index 07f23ce2231a..6163077e1acf 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java @@ -18,6 +18,7 @@ package com.android.server.locksettings; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; + import static com.android.internal.widget.LockPatternUtils.stringToPattern; import android.app.ActivityManager; @@ -58,6 +59,18 @@ class LockSettingsShellCommand extends ShellCommand { mCurrentUserId = ActivityManager.getService().getCurrentUser().id; parseArgs(); + if (!mLockPatternUtils.hasSecureLockScreen()) { + switch (cmd) { + case COMMAND_HELP: + case COMMAND_GET_DISABLED: + case COMMAND_SET_DISABLED: + break; + default: + getErrPrintWriter().println( + "The device does not support lock screen - ignoring the command."); + return -1; + } + } if (!checkCredential()) { return -1; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 0977323754f9..fb7e47d70d64 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4223,7 +4223,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setPasswordHistoryLength(ComponentName who, int length, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } Preconditions.checkNotNull(who, "ComponentName is null"); @@ -4246,13 +4246,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getPasswordHistoryLength(ComponentName who, int userHandle, boolean parent) { + if (!mLockPatternUtils.hasSecureLockScreen()) { + return 0; + } return getStrictestPasswordRequirement(who, userHandle, parent, admin -> admin.passwordHistoryLength, PASSWORD_QUALITY_UNSPECIFIED); } @Override public void setPasswordExpirationTimeout(ComponentName who, long timeout, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } Preconditions.checkNotNull(who, "ComponentName is null"); @@ -4288,7 +4291,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { */ @Override public long getPasswordExpirationTimeout(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return 0L; } enforceFullCrossUsersPermission(userHandle); @@ -4423,7 +4426,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public long getPasswordExpiration(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return 0L; } enforceFullCrossUsersPermission(userHandle); @@ -4770,6 +4773,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getCurrentFailedPasswordAttempts(int userHandle, boolean parent) { + if (!mLockPatternUtils.hasSecureLockScreen()) { + return 0; + } enforceFullCrossUsersPermission(userHandle); synchronized (getLockObject()) { if (!isCallerWithSystemUid()) { @@ -4789,7 +4795,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setMaximumFailedPasswordsForWipe(ComponentName who, int num, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } Preconditions.checkNotNull(who, "ComponentName is null"); @@ -4815,7 +4821,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getMaximumFailedPasswordsForWipe(ComponentName who, int userHandle, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return 0; } enforceFullCrossUsersPermission(userHandle); @@ -4829,7 +4835,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return UserHandle.USER_NULL; } enforceFullCrossUsersPermission(userHandle); @@ -4910,6 +4916,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException { + if (!mLockPatternUtils.hasSecureLockScreen()) { + Slog.w(LOG_TAG, "Cannot reset password when the device has no lock screen"); + return false; + } + final int callingUid = mInjector.binderGetCallingUid(); final int userHandle = mInjector.userHandleGetCallingUserId(); @@ -5252,7 +5263,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setRequiredStrongAuthTimeout(ComponentName who, long timeoutMs, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } Preconditions.checkNotNull(who, "ComponentName is null"); @@ -5285,7 +5296,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { */ @Override public long getRequiredStrongAuthTimeout(ComponentName who, int userId, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS; } enforceFullCrossUsersPermission(userId); @@ -6494,7 +6505,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { */ @Override public void setActivePasswordState(PasswordMetrics metrics, int userHandle) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } enforceFullCrossUsersPermission(userHandle); @@ -6514,7 +6525,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void reportPasswordChanged(@UserIdInt int userId) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } enforceFullCrossUsersPermission(userId); @@ -8800,7 +8811,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent, PersistableBundle args, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } Preconditions.checkNotNull(admin, "admin is null"); @@ -8817,7 +8828,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin, ComponentName agent, int userHandle, boolean parent) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return null; } Preconditions.checkNotNull(agent, "agent null"); @@ -13215,7 +13226,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean setResetPasswordToken(ComponentName admin, byte[] token) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return false; } if (token == null || token.length < 32) { @@ -13243,7 +13254,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean clearResetPasswordToken(ComponentName admin) { - if (!mHasFeature) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return false; } synchronized (getLockObject()) { @@ -13269,6 +13280,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isResetPasswordTokenActive(ComponentName admin) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { + return false; + } synchronized (getLockObject()) { final int userHandle = mInjector.userHandleGetCallingUserId(); getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); @@ -13290,6 +13304,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean resetPasswordWithToken(ComponentName admin, String passwordOrNull, byte[] token, int flags) { + if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { + return false; + } Preconditions.checkNotNull(token); synchronized (getLockObject()) { final int userHandle = mInjector.userHandleGetCallingUserId(); 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 38e8ac2d8f4c..0813e6fa0252 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -206,6 +206,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { mAdmin1Context.binder.callingUid = DpmMockContext.CALLER_UID; setUpUserManager(); + + when(getServices().lockPatternUtils.hasSecureLockScreen()).thenReturn(true); } private TransferOwnershipMetadataManager getMockTransferMetadataManager() { @@ -836,6 +838,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { MockUtils.checkIntent(intent), MockUtils.checkUserHandle(MANAGED_PROFILE_USER_ID)); } + /** * Test for: {@link DevicePolicyManager#setDeviceOwner} DO on system user installs successfully. */ @@ -2618,6 +2621,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { when(getServices().lockPatternUtils .isSeparateProfileChallengeEnabled(eq(PROFILE_USER))).thenReturn(false); dpmi.reportSeparateProfileChallengeChanged(PROFILE_USER); + when(getServices().lockPatternUtils.hasSecureLockScreen()).thenReturn(true); verifyScreenTimeoutCall(Long.MAX_VALUE, PROFILE_USER); verifyScreenTimeoutCall(10L , UserHandle.USER_SYSTEM); @@ -4233,6 +4237,41 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertTrue(dpm.isActivePasswordSufficient()); } + public void testIsActivePasswordSufficient_noLockScreen() throws Exception { + // If there is no lock screen, the password is considered empty no matter what, because + // it provides no security. + when(getServices().lockPatternUtils.hasSecureLockScreen()).thenReturn(false); + + mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + mContext.packageName = admin1.getPackageName(); + setupDeviceOwner(); + + // If no password requirements are set, isActivePasswordSufficient should succeed. + assertTrue(dpm.isActivePasswordSufficient()); + + // Now set some password quality requirements. + dpm.setPasswordQuality(admin1, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); + + reset(mContext.spiedContext); + final int userHandle = UserHandle.getUserId(mContext.binder.callingUid); + PasswordMetrics passwordMetricsNoSymbols = new PasswordMetrics( + DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, 9, + 8, 2, + 6, 1, + 0, 1); + // This should be ignored, as there is no lock screen. + dpm.setActivePasswordState(passwordMetricsNoSymbols, userHandle); + dpm.reportPasswordChanged(userHandle); + + // No broadcast should be sent. + verify(mContext.spiedContext, times(0)).sendBroadcastAsUser( + MockUtils.checkIntentAction(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED), + MockUtils.checkUserHandle(userHandle)); + + // The active (nonexistent) password doesn't comply with the requirements. + assertFalse(dpm.isActivePasswordSufficient()); + } + private void setActivePasswordState(PasswordMetrics passwordMetrics) throws Exception { final int userHandle = UserHandle.getUserId(mContext.binder.callingUid); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index 2dc3510a82e5..cf89cb8f7a15 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -37,8 +37,8 @@ import android.os.FileUtils; import android.os.IProgressListener; import android.os.RemoteException; import android.os.UserManager; -import android.os.storage.StorageManager; import android.os.storage.IStorageManager; +import android.os.storage.StorageManager; import android.security.KeyStore; import android.test.AndroidTestCase; @@ -46,6 +46,7 @@ import com.android.internal.widget.ILockSettings; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockSettingsInternal; import com.android.server.LocalServices; +import com.android.server.wm.WindowManagerInternal; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -85,6 +86,8 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { KeyStore mKeyStore; MockSyntheticPasswordManager mSpManager; IAuthSecret mAuthSecretService; + WindowManagerInternal mMockWindowManager; + protected boolean mHasSecureLockScreen; @Override protected void setUp() throws Exception { @@ -97,10 +100,13 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { mActivityManager = mock(IActivityManager.class); mDevicePolicyManager = mock(DevicePolicyManager.class); mDevicePolicyManagerInternal = mock(DevicePolicyManagerInternal.class); + mMockWindowManager = mock(WindowManagerInternal.class); LocalServices.removeServiceForTest(LockSettingsInternal.class); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); + LocalServices.removeServiceForTest(WindowManagerInternal.class); LocalServices.addService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); + LocalServices.addService(WindowManagerInternal.class, mMockWindowManager); mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager, mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class), @@ -114,11 +120,17 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { storageDir.mkdirs(); } + mHasSecureLockScreen = true; mLockPatternUtils = new LockPatternUtils(mContext) { @Override public ILockSettings getLockSettings() { return mService; } + + @Override + public boolean hasSecureLockScreen() { + return mHasSecureLockScreen; + } }; mSpManager = new MockSyntheticPasswordManager(mContext, mStorage, mGateKeeperService, mUserManager); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java index e12f6d3be71e..5124803ee298 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java @@ -26,13 +26,12 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; import android.os.RemoteException; -import android.os.UserHandle; import android.service.gatekeeper.GateKeeperResponse; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; -import com.android.server.locksettings.LockSettingsStorage.CredentialHash; import com.android.server.locksettings.FakeGateKeeperService.VerifyHandle; +import com.android.server.locksettings.LockSettingsStorage.CredentialHash; /** * runtest frameworks-services -c com.android.server.locksettings.LockSettingsServiceTests @@ -54,11 +53,21 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { PASSWORD_QUALITY_ALPHABETIC); } + public void testCreatePasswordFailsWithoutLockScreen() throws RemoteException { + testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, "password", + CREDENTIAL_TYPE_PASSWORD, PASSWORD_QUALITY_ALPHABETIC); + } + public void testCreatePatternPrimaryUser() throws RemoteException { testCreateCredential(PRIMARY_USER_ID, "123456789", CREDENTIAL_TYPE_PATTERN, PASSWORD_QUALITY_SOMETHING); } + public void testCreatePatternFailsWithoutLockScreen() throws RemoteException { + testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, "123456789", + CREDENTIAL_TYPE_PATTERN, PASSWORD_QUALITY_SOMETHING); + } + public void testChangePasswordPrimaryUser() throws RemoteException { testChangeCredentials(PRIMARY_USER_ID, "78963214", CREDENTIAL_TYPE_PATTERN, "asdfghjk", CREDENTIAL_TYPE_PASSWORD, PASSWORD_QUALITY_ALPHABETIC); @@ -198,6 +207,21 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { assertVerifyCredentials(userId, credential, type, -1); } + private void testCreateCredentialFailsWithoutLockScreen( + int userId, String credential, int type, int quality) throws RemoteException { + mHasSecureLockScreen = false; + + try { + mService.setLockCredential(credential, type, null, quality, userId); + fail("An exception should have been thrown."); + } catch (UnsupportedOperationException e) { + // Success - the exception was expected. + } + + assertFalse(mService.havePassword(userId)); + assertFalse(mService.havePattern(userId)); + } + private void testChangeCredentials(int userId, String newCredential, int newType, String oldCredential, int oldType, int quality) throws RemoteException { final long sid = 1234; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java index a28a5a10e832..929c3b525db9 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java @@ -27,6 +27,7 @@ import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.app.ActivityManager; @@ -77,6 +78,7 @@ public class LockSettingsShellCommandTest { final Context context = InstrumentationRegistry.getTargetContext(); mUserId = ActivityManager.getCurrentUser(); mCommand = new LockSettingsShellCommand(mLockPatternUtils); + when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(true); } @Test @@ -103,6 +105,16 @@ public class LockSettingsShellCommandTest { } @Test + public void testChangePin_noLockScreen() throws Exception { + when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(false); + assertEquals(-1, mCommand.exec(new Binder(), in, out, err, + new String[] { "set-pin", "--old", "1234", "4321" }, + mShellCallback, mResultReceiver)); + verify(mLockPatternUtils).hasSecureLockScreen(); + verifyNoMoreInteractions(mLockPatternUtils); + } + + @Test public void testChangePassword() throws Exception { when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false); when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true); @@ -115,6 +127,16 @@ public class LockSettingsShellCommandTest { } @Test + public void testChangePassword_noLockScreen() throws Exception { + when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(false); + assertEquals(-1, mCommand.exec(new Binder(), in, out, err, + new String[] { "set-password", "--old", "1234", "4321" }, + mShellCallback, mResultReceiver)); + verify(mLockPatternUtils).hasSecureLockScreen(); + verifyNoMoreInteractions(mLockPatternUtils); + } + + @Test public void testChangePattern() throws Exception { when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true); when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false); @@ -126,6 +148,16 @@ public class LockSettingsShellCommandTest { } @Test + public void testChangePattern_noLockScreen() throws Exception { + when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(false); + assertEquals(-1, mCommand.exec(new Binder(), in, out, err, + new String[] { "set-pattern", "--old", "1234", "4321" }, + mShellCallback, mResultReceiver)); + verify(mLockPatternUtils).hasSecureLockScreen(); + verifyNoMoreInteractions(mLockPatternUtils); + } + + @Test public void testClear() throws Exception { when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true); when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index 94e02bc4d35f..0595a5b2e9a0 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -40,10 +40,10 @@ import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationRe import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken; import com.android.server.locksettings.SyntheticPasswordManager.PasswordData; -import java.util.ArrayList; - import org.mockito.ArgumentCaptor; +import java.util.ArrayList; + /** * runtest frameworks-services -c com.android.server.locksettings.SyntheticPasswordTests @@ -448,6 +448,37 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); } + public void testSetLockCredentialWithTokenFailsWithoutLockScreen() throws Exception { + final String password = "password"; + final String pattern = "123654"; + final String token = "some-high-entropy-secure-token"; + + mHasSecureLockScreen = false; + enableSyntheticPassword(); + long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID); + assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); + + try { + mLocalService.setLockCredentialWithToken(password, + LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token.getBytes(), + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + fail("An exception should have been thrown."); + } catch (UnsupportedOperationException e) { + // Success - the exception was expected. + } + assertFalse(mService.havePassword(PRIMARY_USER_ID)); + + try { + mLocalService.setLockCredentialWithToken(pattern, + LockPatternUtils.CREDENTIAL_TYPE_PATTERN, handle, token.getBytes(), + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + fail("An exception should have been thrown."); + } catch (UnsupportedOperationException e) { + // Success - the exception was expected. + } + assertFalse(mService.havePattern(PRIMARY_USER_ID)); + } + public void testgetHashFactorPrimaryUser() throws RemoteException { final String password = "password"; mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, |