• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.server.locksettings;
18 
19 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
20 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
21 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
22 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
23 
24 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
25 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
26 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
27 
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.ArgumentMatchers.anyInt;
30 import static org.mockito.ArgumentMatchers.eq;
31 import static org.mockito.Mockito.never;
32 import static org.mockito.Mockito.reset;
33 import static org.mockito.Mockito.verify;
34 
35 import android.os.RemoteException;
36 import android.platform.test.annotations.Presubmit;
37 import android.service.gatekeeper.GateKeeperResponse;
38 
39 import androidx.test.filters.SmallTest;
40 
41 import com.android.internal.widget.LockPatternUtils;
42 import com.android.internal.widget.VerifyCredentialResponse;
43 import com.android.server.locksettings.FakeGateKeeperService.VerifyHandle;
44 import com.android.server.locksettings.LockSettingsStorage.CredentialHash;
45 
46 /**
47  * runtest frameworks-services -c com.android.server.locksettings.LockSettingsServiceTests
48  */
49 @SmallTest
50 @Presubmit
51 public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
52 
53     @Override
setUp()54     protected void setUp() throws Exception {
55         super.setUp();
56     }
57 
58     @Override
tearDown()59     protected void tearDown() throws Exception {
60         super.tearDown();
61     }
62 
testCreatePasswordPrimaryUser()63     public void testCreatePasswordPrimaryUser() throws RemoteException {
64         testCreateCredential(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD,
65                 PASSWORD_QUALITY_ALPHABETIC);
66     }
67 
testCreatePasswordFailsWithoutLockScreen()68     public void testCreatePasswordFailsWithoutLockScreen() throws RemoteException {
69         testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, "password",
70                 CREDENTIAL_TYPE_PASSWORD, PASSWORD_QUALITY_ALPHABETIC);
71     }
72 
testCreatePatternPrimaryUser()73     public void testCreatePatternPrimaryUser() throws RemoteException {
74         testCreateCredential(PRIMARY_USER_ID, "123456789", CREDENTIAL_TYPE_PATTERN,
75                 PASSWORD_QUALITY_SOMETHING);
76     }
77 
testCreatePatternFailsWithoutLockScreen()78     public void testCreatePatternFailsWithoutLockScreen() throws RemoteException {
79         testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, "123456789",
80                 CREDENTIAL_TYPE_PATTERN, PASSWORD_QUALITY_SOMETHING);
81     }
82 
testChangePasswordPrimaryUser()83     public void testChangePasswordPrimaryUser() throws RemoteException {
84         testChangeCredentials(PRIMARY_USER_ID, "78963214", CREDENTIAL_TYPE_PATTERN,
85                 "asdfghjk", CREDENTIAL_TYPE_PASSWORD, PASSWORD_QUALITY_ALPHABETIC);
86     }
87 
testChangePatternPrimaryUser()88     public void testChangePatternPrimaryUser() throws RemoteException {
89         testChangeCredentials(PRIMARY_USER_ID, "!£$%^&*(())", CREDENTIAL_TYPE_PASSWORD,
90                 "1596321", CREDENTIAL_TYPE_PATTERN, PASSWORD_QUALITY_SOMETHING);
91     }
92 
testChangePasswordFailPrimaryUser()93     public void testChangePasswordFailPrimaryUser() throws RemoteException {
94         final long sid = 1234;
95         final String FAILED_MESSAGE = "Failed to enroll password";
96         initializeStorageWithCredential(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid);
97 
98         try {
99             mService.setLockCredential("newpwd".getBytes(), CREDENTIAL_TYPE_PASSWORD,
100                     "badpwd".getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
101             fail("Did not fail when enrolling using incorrect credential");
102         } catch (IllegalStateException expected) {
103             assertTrue(expected.getMessage().equals(FAILED_MESSAGE));
104         }
105         assertVerifyCredentials(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid);
106     }
107 
testClearPasswordPrimaryUser()108     public void testClearPasswordPrimaryUser() throws RemoteException {
109         final String PASSWORD = "password";
110         initializeStorageWithCredential(PRIMARY_USER_ID, PASSWORD, CREDENTIAL_TYPE_PASSWORD, 1234);
111         mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, PASSWORD.getBytes(),
112                 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
113         assertFalse(mService.havePassword(PRIMARY_USER_ID));
114         assertFalse(mService.havePattern(PRIMARY_USER_ID));
115         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
116     }
117 
testManagedProfileUnifiedChallenge()118     public void testManagedProfileUnifiedChallenge() throws RemoteException {
119         final String firstUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-1";
120         final String secondUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-2";
121         mService.setLockCredential(firstUnifiedPassword.getBytes(),
122                 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
123                 null, PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false);
124         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
125         final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
126         final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
127         final long turnedOffProfileSid =
128                 mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID);
129         assertTrue(primarySid != 0);
130         assertTrue(profileSid != 0);
131         assertTrue(profileSid != primarySid);
132         assertTrue(turnedOffProfileSid != 0);
133         assertTrue(turnedOffProfileSid != primarySid);
134         assertTrue(turnedOffProfileSid != profileSid);
135 
136         // clear auth token and wait for verify challenge from primary user to re-generate it.
137         mGateKeeperService.clearAuthToken(MANAGED_PROFILE_USER_ID);
138         mGateKeeperService.clearAuthToken(TURNED_OFF_PROFILE_USER_ID);
139         // verify credential
140         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
141                 firstUnifiedPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
142                 PRIMARY_USER_ID).getResponseCode());
143 
144         // Verify that we have a new auth token for the profile
145         assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
146         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
147 
148         // Verify that profile which aren't running (e.g. turn off work) don't get unlocked
149         assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID));
150 
151         /* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new
152          * credential as part of verifyCredential() before the new credential is committed in
153          * StorageManager. So we relax the check in our mock StorageManager to allow that.
154          */
155         mStorageManager.setIgnoreBadUnlock(true);
156         // Change primary password and verify that profile SID remains
157         mService.setLockCredential(secondUnifiedPassword.getBytes(),
158                 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, firstUnifiedPassword.getBytes(),
159                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
160         mStorageManager.setIgnoreBadUnlock(false);
161         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
162         assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID));
163 
164         // Clear unified challenge
165         mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
166                 secondUnifiedPassword.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID,
167                 false);
168         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
169         assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
170         assertEquals(0, mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID));
171     }
172 
testManagedProfileSeparateChallenge()173     public void testManagedProfileSeparateChallenge() throws RemoteException {
174         final String primaryPassword = "testManagedProfileSeparateChallenge-primary";
175         final String profilePassword = "testManagedProfileSeparateChallenge-profile";
176         mService.setLockCredential(primaryPassword.getBytes(),
177                 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
178                 PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false);
179         /* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new
180          * credential as part of verifyCredential() before the new credential is committed in
181          * StorageManager. So we relax the check in our mock StorageManager to allow that.
182          */
183         mStorageManager.setIgnoreBadUnlock(true);
184         mService.setLockCredential(profilePassword.getBytes(),
185                 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
186                 PASSWORD_QUALITY_COMPLEX, MANAGED_PROFILE_USER_ID, false);
187         mStorageManager.setIgnoreBadUnlock(false);
188 
189         final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
190         final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
191         assertTrue(primarySid != 0);
192         assertTrue(profileSid != 0);
193         assertTrue(profileSid != primarySid);
194 
195         // clear auth token and make sure verify challenge from primary user does not regenerate it.
196         mGateKeeperService.clearAuthToken(MANAGED_PROFILE_USER_ID);
197         // verify primary credential
198         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
199                 primaryPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
200                 PRIMARY_USER_ID).getResponseCode());
201         assertNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
202 
203         // verify profile credential
204         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
205                 profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
206                 MANAGED_PROFILE_USER_ID).getResponseCode());
207         assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
208         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
209 
210         // Change primary credential and make sure we don't affect profile
211         mStorageManager.setIgnoreBadUnlock(true);
212         mService.setLockCredential("pwd".getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
213                 primaryPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
214         mStorageManager.setIgnoreBadUnlock(false);
215         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
216                 profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
217                 MANAGED_PROFILE_USER_ID).getResponseCode());
218         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
219     }
220 
testSetLockCredential_forPrimaryUser_sendsCredentials()221     public void testSetLockCredential_forPrimaryUser_sendsCredentials() throws Exception {
222         final byte[] password = "password".getBytes();
223 
224         mService.setLockCredential(
225                 password,
226                 CREDENTIAL_TYPE_PASSWORD,
227                 null,
228                 PASSWORD_QUALITY_ALPHABETIC,
229                 PRIMARY_USER_ID,
230                 false);
231 
232         verify(mRecoverableKeyStoreManager)
233                 .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, password, PRIMARY_USER_ID);
234     }
235 
testSetLockCredential_forProfileWithSeparateChallenge_sendsCredentials()236     public void testSetLockCredential_forProfileWithSeparateChallenge_sendsCredentials()
237             throws Exception {
238         final byte[] pattern = "12345".getBytes();
239 
240         mService.setLockCredential(
241                 pattern,
242                 CREDENTIAL_TYPE_PATTERN,
243                 null,
244                 PASSWORD_QUALITY_SOMETHING,
245                 MANAGED_PROFILE_USER_ID,
246                 false);
247 
248         verify(mRecoverableKeyStoreManager)
249                 .lockScreenSecretChanged(CREDENTIAL_TYPE_PATTERN, pattern, MANAGED_PROFILE_USER_ID);
250     }
251 
testSetLockCredential_forProfileWithSeparateChallenge_updatesCredentials()252     public void testSetLockCredential_forProfileWithSeparateChallenge_updatesCredentials()
253             throws Exception {
254         final String oldCredential = "12345";
255         final byte[] newCredential = "newPassword".getBytes();
256         initializeStorageWithCredential(
257                 MANAGED_PROFILE_USER_ID,
258                 oldCredential,
259                 CREDENTIAL_TYPE_PATTERN,
260                 PASSWORD_QUALITY_SOMETHING);
261 
262         mService.setLockCredential(
263                 newCredential,
264                 CREDENTIAL_TYPE_PASSWORD,
265                 oldCredential.getBytes(),
266                 PASSWORD_QUALITY_ALPHABETIC,
267                 MANAGED_PROFILE_USER_ID,
268                 false);
269 
270         verify(mRecoverableKeyStoreManager)
271                 .lockScreenSecretChanged(
272                         CREDENTIAL_TYPE_PASSWORD, newCredential, MANAGED_PROFILE_USER_ID);
273     }
274 
testSetLockCredential_forProfileWithUnifiedChallenge_doesNotSendRandomCredential()275     public void testSetLockCredential_forProfileWithUnifiedChallenge_doesNotSendRandomCredential()
276             throws Exception {
277         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
278 
279         mService.setLockCredential(
280                 "12345".getBytes(),
281                 CREDENTIAL_TYPE_PATTERN,
282                 null,
283                 PASSWORD_QUALITY_SOMETHING,
284                 PRIMARY_USER_ID,
285                 false);
286 
287         verify(mRecoverableKeyStoreManager, never())
288                 .lockScreenSecretChanged(
289                         eq(CREDENTIAL_TYPE_PASSWORD), any(), eq(MANAGED_PROFILE_USER_ID));
290     }
291 
292     public void
testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_updatesBothCredentials()293             testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_updatesBothCredentials()
294                     throws Exception {
295         final String oldCredential = "oldPassword";
296         final byte[] newCredential = "newPassword".getBytes();
297         initializeStorageWithCredential(
298                 PRIMARY_USER_ID, oldCredential, CREDENTIAL_TYPE_PASSWORD, 1234);
299         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
300 
301         mService.setLockCredential(
302                 newCredential,
303                 CREDENTIAL_TYPE_PASSWORD,
304                 oldCredential.getBytes(),
305                 PASSWORD_QUALITY_ALPHABETIC,
306                 PRIMARY_USER_ID,
307                 false);
308 
309         verify(mRecoverableKeyStoreManager)
310                 .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, newCredential, PRIMARY_USER_ID);
311         verify(mRecoverableKeyStoreManager)
312                 .lockScreenSecretChanged(
313                         CREDENTIAL_TYPE_PASSWORD, newCredential, MANAGED_PROFILE_USER_ID);
314     }
315 
316     public void
testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_removesBothCredentials()317             testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_removesBothCredentials()
318                     throws Exception {
319         final String oldCredential = "oldPassword";
320         initializeStorageWithCredential(
321                 PRIMARY_USER_ID, oldCredential, CREDENTIAL_TYPE_PASSWORD, 1234);
322         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
323 
324         mService.setLockCredential(
325                 null,
326                 CREDENTIAL_TYPE_NONE,
327                 oldCredential.getBytes(),
328                 PASSWORD_QUALITY_UNSPECIFIED,
329                 PRIMARY_USER_ID,
330                 false);
331 
332         verify(mRecoverableKeyStoreManager)
333                 .lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, PRIMARY_USER_ID);
334         verify(mRecoverableKeyStoreManager)
335                 .lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, MANAGED_PROFILE_USER_ID);
336     }
337 
testSetLockCredential_forUnifiedToSeparateChallengeProfile_sendsNewCredentials()338     public void testSetLockCredential_forUnifiedToSeparateChallengeProfile_sendsNewCredentials()
339             throws Exception {
340         final String parentPassword = "parentPassword";
341         final byte[] profilePassword = "profilePassword".getBytes();
342         initializeStorageWithCredential(
343                 PRIMARY_USER_ID, parentPassword, CREDENTIAL_TYPE_PASSWORD, 1234);
344         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
345 
346         mService.setLockCredential(
347                 profilePassword,
348                 CREDENTIAL_TYPE_PASSWORD,
349                 null,
350                 PASSWORD_QUALITY_ALPHABETIC,
351                 MANAGED_PROFILE_USER_ID,
352                 false);
353 
354         verify(mRecoverableKeyStoreManager)
355                 .lockScreenSecretChanged(
356                         CREDENTIAL_TYPE_PASSWORD, profilePassword, MANAGED_PROFILE_USER_ID);
357     }
358 
359     public void
testSetLockCredential_forSeparateToUnifiedChallengeProfile_doesNotSendRandomCredential()360             testSetLockCredential_forSeparateToUnifiedChallengeProfile_doesNotSendRandomCredential()
361                     throws Exception {
362         final String parentPassword = "parentPassword";
363         final String profilePassword = "12345";
364         initializeStorageWithCredential(
365                 PRIMARY_USER_ID, parentPassword, CREDENTIAL_TYPE_PASSWORD, 1234);
366         // Create and verify separate profile credentials.
367         testCreateCredential(
368                 MANAGED_PROFILE_USER_ID,
369                 profilePassword,
370                 CREDENTIAL_TYPE_PATTERN,
371                 PASSWORD_QUALITY_SOMETHING);
372 
373         mService.setSeparateProfileChallengeEnabled(
374                 MANAGED_PROFILE_USER_ID, false, profilePassword.getBytes());
375 
376         // Called once for setting the initial separate profile credentials and not again during
377         // unification.
378         verify(mRecoverableKeyStoreManager)
379                 .lockScreenSecretChanged(anyInt(), any(), eq(MANAGED_PROFILE_USER_ID));
380     }
381 
testVerifyCredential_forPrimaryUser_sendsCredentials()382     public void testVerifyCredential_forPrimaryUser_sendsCredentials() throws Exception {
383         final String password = "password";
384         initializeStorageWithCredential(PRIMARY_USER_ID, password, CREDENTIAL_TYPE_PASSWORD, 1234);
385         reset(mRecoverableKeyStoreManager);
386 
387         mService.verifyCredential(
388                 password.getBytes(), CREDENTIAL_TYPE_PASSWORD, 1, PRIMARY_USER_ID);
389 
390         verify(mRecoverableKeyStoreManager)
391                 .lockScreenSecretAvailable(
392                         CREDENTIAL_TYPE_PASSWORD, password.getBytes(), PRIMARY_USER_ID);
393     }
394 
testVerifyCredential_forProfileWithSeparateChallenge_sendsCredentials()395     public void testVerifyCredential_forProfileWithSeparateChallenge_sendsCredentials()
396             throws Exception {
397         final byte[] pattern = "12345".getBytes();
398         mService.setLockCredential(
399                 pattern,
400                 CREDENTIAL_TYPE_PATTERN,
401                 null,
402                 PASSWORD_QUALITY_SOMETHING,
403                 MANAGED_PROFILE_USER_ID,
404                 false);
405         reset(mRecoverableKeyStoreManager);
406 
407         mService.verifyCredential(pattern, CREDENTIAL_TYPE_PATTERN, 1, MANAGED_PROFILE_USER_ID);
408 
409         verify(mRecoverableKeyStoreManager)
410                 .lockScreenSecretAvailable(
411                         CREDENTIAL_TYPE_PATTERN, pattern, MANAGED_PROFILE_USER_ID);
412     }
413 
414     public void
testVerifyCredential_forPrimaryUserWithUnifiedChallengeProfile_sendsCredentialsForBoth()415             testVerifyCredential_forPrimaryUserWithUnifiedChallengeProfile_sendsCredentialsForBoth()
416                     throws Exception {
417         final String pattern = "12345";
418         initializeStorageWithCredential(PRIMARY_USER_ID, pattern, CREDENTIAL_TYPE_PATTERN, 1234);
419         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
420         reset(mRecoverableKeyStoreManager);
421 
422         mService.verifyCredential(pattern.getBytes(), CREDENTIAL_TYPE_PATTERN, 1, PRIMARY_USER_ID);
423 
424         // Parent sends its credentials for both the parent and profile.
425         verify(mRecoverableKeyStoreManager)
426                 .lockScreenSecretAvailable(
427                         CREDENTIAL_TYPE_PATTERN, pattern.getBytes(), PRIMARY_USER_ID);
428         verify(mRecoverableKeyStoreManager)
429                 .lockScreenSecretAvailable(
430                         CREDENTIAL_TYPE_PATTERN, pattern.getBytes(), MANAGED_PROFILE_USER_ID);
431         // Profile doesn't send its own random credentials.
432         verify(mRecoverableKeyStoreManager, never())
433                 .lockScreenSecretAvailable(
434                         eq(CREDENTIAL_TYPE_PASSWORD), any(), eq(MANAGED_PROFILE_USER_ID));
435     }
436 
testCreateCredential(int userId, String credential, int type, int quality)437     private void testCreateCredential(int userId, String credential, int type, int quality)
438             throws RemoteException {
439         mService.setLockCredential(credential.getBytes(), type, null, quality,
440                 userId, false);
441         assertVerifyCredentials(userId, credential, type, -1);
442     }
443 
testCreateCredentialFailsWithoutLockScreen( int userId, String credential, int type, int quality)444     private void testCreateCredentialFailsWithoutLockScreen(
445             int userId, String credential, int type, int quality) throws RemoteException {
446         mHasSecureLockScreen = false;
447 
448         try {
449             mService.setLockCredential(credential.getBytes(), type, null, quality,
450                     userId, false);
451             fail("An exception should have been thrown.");
452         } catch (UnsupportedOperationException e) {
453             // Success - the exception was expected.
454         }
455 
456         assertFalse(mService.havePassword(userId));
457         assertFalse(mService.havePattern(userId));
458     }
459 
testChangeCredentials(int userId, String newCredential, int newType, String oldCredential, int oldType, int quality)460     private void testChangeCredentials(int userId, String newCredential, int newType,
461             String oldCredential, int oldType, int quality) throws RemoteException {
462         final long sid = 1234;
463         initializeStorageWithCredential(userId, oldCredential, oldType, sid);
464         mService.setLockCredential(newCredential.getBytes(), newType, oldCredential.getBytes(),
465                 quality, userId, false);
466         assertVerifyCredentials(userId, newCredential, newType, sid);
467     }
468 
assertVerifyCredentials(int userId, String credential, int type, long sid)469     private void assertVerifyCredentials(int userId, String credential, int type, long sid)
470             throws RemoteException{
471         final long challenge = 54321;
472         VerifyCredentialResponse response = mService.verifyCredential(credential.getBytes(),
473                 type, challenge, userId);
474 
475         assertEquals(GateKeeperResponse.RESPONSE_OK, response.getResponseCode());
476         if (sid != -1) assertEquals(sid, mGateKeeperService.getSecureUserId(userId));
477         final int incorrectType;
478         if (type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {
479             assertTrue(mService.havePassword(userId));
480             assertFalse(mService.havePattern(userId));
481             incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
482         } else if (type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN){
483             assertFalse(mService.havePassword(userId));
484             assertTrue(mService.havePattern(userId));
485             incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
486         } else {
487             assertFalse(mService.havePassword(userId));
488             assertFalse(mService.havePassword(userId));
489             incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
490         }
491         // check for bad type
492         assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(
493                 credential.getBytes(), incorrectType, challenge, userId).getResponseCode());
494         // check for bad credential
495         assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(
496                 ("0" + credential).getBytes(), type, challenge, userId).getResponseCode());
497     }
498 
initializeStorageWithCredential(int userId, String credential, int type, long sid)499     private void initializeStorageWithCredential(int userId, String credential, int type, long sid)
500             throws RemoteException {
501         byte[] credentialBytes = credential == null ? null : credential.getBytes();
502         byte[] oldHash = new VerifyHandle(credential.getBytes(), sid).toBytes();
503         if (mService.shouldMigrateToSyntheticPasswordLocked(userId)) {
504             mService.initializeSyntheticPasswordLocked(oldHash, credentialBytes, type,
505                     type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? PASSWORD_QUALITY_ALPHABETIC
506                             : PASSWORD_QUALITY_SOMETHING, userId);
507         } else {
508             if (type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {
509                 mStorage.writeCredentialHash(CredentialHash.create(oldHash,
510                         LockPatternUtils.CREDENTIAL_TYPE_PASSWORD), userId);
511             } else {
512                 mStorage.writeCredentialHash(CredentialHash.create(oldHash,
513                         LockPatternUtils.CREDENTIAL_TYPE_PATTERN), userId);
514             }
515         }
516     }
517 }
518