2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package com.android.server;
19 import static org.mockito.Matchers.eq;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.when;
23 import android.app.NotificationManager;
24 import android.app.admin.DevicePolicyManager;
25 import android.content.Context;
26 import android.content.ContextWrapper;
27 import android.content.pm.UserInfo;
28 import android.database.sqlite.SQLiteDatabase;
29 import android.os.FileUtils;
30 import android.os.UserManager;
31 import android.os.storage.StorageManager;
32 import android.test.AndroidTestCase;
34 import com.android.internal.widget.LockPatternUtils;
35 import com.android.server.LockSettingsStorage.CredentialHash;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.List;
40 import java.util.concurrent.CountDownLatch;
43 * runtest frameworks-services -c com.android.server.LockSettingsStorageTests
45 public class LockSettingsStorageTests extends AndroidTestCase {
46 private final byte[] PASSWORD_0 = "thepassword0".getBytes();
47 private final byte[] PASSWORD_1 = "password1".getBytes();
48 private final byte[] PATTERN_0 = "123654".getBytes();
49 private final byte[] PATTERN_1 = "147852369".getBytes();
51 LockSettingsStorage mStorage;
57 protected void setUp() throws Exception {
59 mStorageDir = new File(getContext().getFilesDir(), "locksettings");
60 mDb = getContext().getDatabasePath("locksettings.db");
62 assertTrue(mStorageDir.exists() || mStorageDir.mkdirs());
63 assertTrue(FileUtils.deleteContents(mStorageDir));
64 assertTrue(!mDb.exists() || mDb.delete());
66 final UserManager mockUserManager = mock(UserManager.class);
67 // User 2 is a profile of user 1.
68 when(mockUserManager.getProfileParent(eq(2))).thenReturn(new UserInfo(1, "name", 0));
69 // User 3 is a profile of user 0.
70 when(mockUserManager.getProfileParent(eq(3))).thenReturn(new UserInfo(0, "name", 0));
72 MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager,
73 mock(NotificationManager.class), mock(DevicePolicyManager.class),
74 mock(StorageManager.class));
75 mStorage = new LockSettingsStorageTestable(context,
76 new File(getContext().getFilesDir(), "locksettings"));
77 mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
79 public void initialize(SQLiteDatabase db) {
80 mStorage.writeKeyValue(db, "initializedKey", "initialValue", 0);
86 protected void tearDown() throws Exception {
88 mStorage.closeDatabase();
91 public void testKeyValue_InitializeWorked() {
92 assertEquals("initialValue", mStorage.readKeyValue("initializedKey", "default", 0));
93 mStorage.clearCache();
94 assertEquals("initialValue", mStorage.readKeyValue("initializedKey", "default", 0));
97 public void testKeyValue_WriteThenRead() {
98 mStorage.writeKeyValue("key", "value", 0);
99 assertEquals("value", mStorage.readKeyValue("key", "default", 0));
100 mStorage.clearCache();
101 assertEquals("value", mStorage.readKeyValue("key", "default", 0));
104 public void testKeyValue_DefaultValue() {
105 assertEquals("default", mStorage.readKeyValue("unititialized key", "default", 0));
106 assertEquals("default2", mStorage.readKeyValue("unititialized key", "default2", 0));
109 public void testKeyValue_Concurrency() {
110 final Object monitor = new Object();
111 List<Thread> threads = new ArrayList<>();
112 for (int i = 0; i < 100; i++) {
113 final int threadId = i;
114 threads.add(new Thread() {
117 synchronized (monitor) {
120 } catch (InterruptedException e) {
123 mStorage.writeKeyValue("key", "1 from thread " + threadId, 0);
124 mStorage.readKeyValue("key", "default", 0);
125 mStorage.writeKeyValue("key", "2 from thread " + threadId, 0);
126 mStorage.readKeyValue("key", "default", 0);
127 mStorage.writeKeyValue("key", "3 from thread " + threadId, 0);
128 mStorage.readKeyValue("key", "default", 0);
129 mStorage.writeKeyValue("key", "4 from thread " + threadId, 0);
130 mStorage.readKeyValue("key", "default", 0);
131 mStorage.writeKeyValue("key", "5 from thread " + threadId, 0);
132 mStorage.readKeyValue("key", "default", 0);
136 threads.get(i).start();
138 mStorage.writeKeyValue("key", "initalValue", 0);
139 synchronized (monitor) {
142 for (int i = 0; i < threads.size(); i++) {
144 threads.get(i).join();
145 } catch (InterruptedException e) {
148 assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
149 mStorage.clearCache();
150 assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
153 public void testKeyValue_CacheStarvedWriter() {
154 final CountDownLatch latch = new CountDownLatch(1);
155 List<Thread> threads = new ArrayList<>();
156 for (int i = 0; i < 100; i++) {
157 final int threadId = i;
158 threads.add(new Thread() {
163 } catch (InterruptedException e) {
166 if (threadId == 50) {
167 mStorage.writeKeyValue("starvedWriterKey", "value", 0);
169 mStorage.readKeyValue("starvedWriterKey", "default", 0);
173 threads.get(i).start();
176 for (int i = 0; i < threads.size(); i++) {
178 threads.get(i).join();
179 } catch (InterruptedException e) {
182 String cached = mStorage.readKeyValue("key", "default", 0);
183 mStorage.clearCache();
184 String storage = mStorage.readKeyValue("key", "default", 0);
185 assertEquals("Cached value didn't match stored value", storage, cached);
188 public void testRemoveUser() {
189 mStorage.writeKeyValue("key", "value", 0);
190 writePasswordBytes(PASSWORD_0, 0);
191 writePatternBytes(PATTERN_0, 0);
193 mStorage.writeKeyValue("key", "value", 1);
194 writePasswordBytes(PASSWORD_1, 1);
195 writePatternBytes(PATTERN_1, 1);
197 mStorage.removeUser(0);
199 assertEquals("value", mStorage.readKeyValue("key", "default", 1));
200 assertEquals("default", mStorage.readKeyValue("key", "default", 0));
201 assertEquals(LockPatternUtils.CREDENTIAL_TYPE_NONE, mStorage.readCredentialHash(0).type);
202 assertPatternBytes(PATTERN_1, 1);
205 public void testCredential_Default() {
206 assertEquals(mStorage.readCredentialHash(0).type, LockPatternUtils.CREDENTIAL_TYPE_NONE);
209 public void testPassword_Write() {
210 writePasswordBytes(PASSWORD_0, 0);
212 assertPasswordBytes(PASSWORD_0, 0);
213 mStorage.clearCache();
214 assertPasswordBytes(PASSWORD_0, 0);
217 public void testPassword_WriteProfileWritesParent() {
218 writePasswordBytes(PASSWORD_0, 1);
219 writePasswordBytes(PASSWORD_1, 2);
221 assertPasswordBytes(PASSWORD_0, 1);
222 assertPasswordBytes(PASSWORD_1, 2);
223 mStorage.clearCache();
224 assertPasswordBytes(PASSWORD_0, 1);
225 assertPasswordBytes(PASSWORD_1, 2);
228 public void testLockType_WriteProfileWritesParent() {
229 writePasswordBytes(PASSWORD_0, 10);
230 writePatternBytes(PATTERN_0, 20);
232 assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
233 mStorage.readCredentialHash(10).type);
234 assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
235 mStorage.readCredentialHash(20).type);
236 mStorage.clearCache();
237 assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
238 mStorage.readCredentialHash(10).type);
239 assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
240 mStorage.readCredentialHash(20).type);
243 public void testPassword_WriteParentWritesProfile() {
244 writePasswordBytes(PASSWORD_0, 2);
245 writePasswordBytes(PASSWORD_1, 1);
247 assertPasswordBytes(PASSWORD_1, 1);
248 assertPasswordBytes(PASSWORD_0, 2);
249 mStorage.clearCache();
250 assertPasswordBytes(PASSWORD_1, 1);
251 assertPasswordBytes(PASSWORD_0, 2);
254 public void testProfileLock_ReadWriteChildProfileLock() {
255 assertFalse(mStorage.hasChildProfileLock(20));
256 mStorage.writeChildProfileLock(20, PASSWORD_0);
257 assertArrayEquals(PASSWORD_0, mStorage.readChildProfileLock(20));
258 assertTrue(mStorage.hasChildProfileLock(20));
259 mStorage.clearCache();
260 assertArrayEquals(PASSWORD_0, mStorage.readChildProfileLock(20));
261 assertTrue(mStorage.hasChildProfileLock(20));
264 public void testPattern_Write() {
265 writePatternBytes(PATTERN_0, 0);
267 assertPatternBytes(PATTERN_0, 0);
268 mStorage.clearCache();
269 assertPatternBytes(PATTERN_0, 0);
272 public void testPattern_WriteProfileWritesParent() {
273 writePatternBytes(PATTERN_0, 1);
274 writePatternBytes(PATTERN_1, 2);
276 assertPatternBytes(PATTERN_0, 1);
277 assertPatternBytes(PATTERN_1, 2);
278 mStorage.clearCache();
279 assertPatternBytes(PATTERN_0, 1);
280 assertPatternBytes(PATTERN_1, 2);
283 public void testPattern_WriteParentWritesProfile() {
284 writePatternBytes(PATTERN_1, 2);
285 writePatternBytes(PATTERN_0, 1);
287 assertPatternBytes(PATTERN_0, 1);
288 assertPatternBytes(PATTERN_1, 2);
289 mStorage.clearCache();
290 assertPatternBytes(PATTERN_0, 1);
291 assertPatternBytes(PATTERN_1, 2);
294 public void testPrefetch() {
295 mStorage.writeKeyValue("key", "toBeFetched", 0);
296 writePatternBytes(PATTERN_0, 0);
298 mStorage.clearCache();
299 mStorage.prefetchUser(0);
301 assertEquals("toBeFetched", mStorage.readKeyValue("key", "default", 0));
302 assertPatternBytes(PATTERN_0, 0);
305 public void testFileLocation_Owner() {
306 LockSettingsStorage storage = new LockSettingsStorage(getContext());
308 assertEquals("/data/system/gesture.key", storage.getLegacyLockPatternFilename(0));
309 assertEquals("/data/system/password.key", storage.getLegacyLockPasswordFilename(0));
310 assertEquals("/data/system/gatekeeper.pattern.key", storage.getLockPatternFilename(0));
311 assertEquals("/data/system/gatekeeper.password.key", storage.getLockPasswordFilename(0));
314 public void testFileLocation_SecondaryUser() {
315 LockSettingsStorage storage = new LockSettingsStorage(getContext());
317 assertEquals("/data/system/users/1/gatekeeper.pattern.key", storage.getLockPatternFilename(1));
318 assertEquals("/data/system/users/1/gatekeeper.password.key", storage.getLockPasswordFilename(1));
321 public void testFileLocation_ProfileToSecondary() {
322 LockSettingsStorage storage = new LockSettingsStorage(getContext());
324 assertEquals("/data/system/users/2/gatekeeper.pattern.key", storage.getLockPatternFilename(2));
325 assertEquals("/data/system/users/2/gatekeeper.password.key", storage.getLockPasswordFilename(2));
328 public void testFileLocation_ProfileToOwner() {
329 LockSettingsStorage storage = new LockSettingsStorage(getContext());
331 assertEquals("/data/system/users/3/gatekeeper.pattern.key", storage.getLockPatternFilename(3));
332 assertEquals("/data/system/users/3/gatekeeper.password.key", storage.getLockPasswordFilename(3));
335 public void testSyntheticPasswordState() {
336 final byte[] data = {1,2,3,4};
337 mStorage.writeSyntheticPasswordState(10, 1234L, "state", data);
338 assertArrayEquals(data, mStorage.readSyntheticPasswordState(10, 1234L, "state"));
339 assertEquals(null, mStorage.readSyntheticPasswordState(0, 1234L, "state"));
341 mStorage.deleteSyntheticPasswordState(10, 1234L, "state");
342 assertEquals(null, mStorage.readSyntheticPasswordState(10, 1234L, "state"));
345 private static void assertArrayEquals(byte[] expected, byte[] actual) {
346 if (!Arrays.equals(expected, actual)) {
347 fail("expected:<" + Arrays.toString(expected) +
348 "> but was:<" + Arrays.toString(actual) + ">");
352 private void writePasswordBytes(byte[] password, int userId) {
353 mStorage.writeCredentialHash(CredentialHash.create(
354 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD), userId);
357 private void writePatternBytes(byte[] pattern, int userId) {
358 mStorage.writeCredentialHash(CredentialHash.create(
359 pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN), userId);
362 private void assertPasswordBytes(byte[] password, int userId) {
363 CredentialHash cred = mStorage.readCredentialHash(userId);
364 assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, cred.type);
365 assertArrayEquals(password, cred.hash);
368 private void assertPatternBytes(byte[] pattern, int userId) {
369 CredentialHash cred = mStorage.readCredentialHash(userId);
370 assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN, cred.type);
371 assertArrayEquals(pattern, cred.hash);