blob: 7d28e3964f8ed4a758ea245dba5cc42b7868a4e5 [file] [log] [blame]
Adrian Roose5424992014-11-07 21:47:17 +01001/*
2 * Copyright (C) 2014 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
17package com.android.server;
18
19import android.content.Context;
20import android.content.ContextWrapper;
21import android.content.pm.UserInfo;
22import android.database.sqlite.SQLiteDatabase;
23import android.os.FileUtils;
24import android.os.UserManager;
25import android.test.AndroidTestCase;
26
27import java.io.File;
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.List;
31import java.util.concurrent.CountDownLatch;
32
33public class LockSettingsStorageTests extends AndroidTestCase {
34 LockSettingsStorage mStorage;
35 File mStorageDir;
36
37 private File mDb;
38
39 @Override
40 protected void setUp() throws Exception {
41 super.setUp();
42 mStorageDir = new File(getContext().getFilesDir(), "locksettings");
43 mDb = getContext().getDatabasePath("locksettings.db");
44
45 assertTrue(mStorageDir.exists() || mStorageDir.mkdirs());
46 assertTrue(FileUtils.deleteContents(mStorageDir));
47 assertTrue(!mDb.exists() || mDb.delete());
48
49 final Context ctx = getContext();
50 setContext(new ContextWrapper(ctx) {
51 @Override
52 public Object getSystemService(String name) {
53 if (USER_SERVICE.equals(name)) {
54 return new UserManager(ctx, null) {
55 @Override
56 public UserInfo getProfileParent(int userHandle) {
57 if (userHandle == 2) {
58 // User 2 is a profile of user 1.
59 return new UserInfo(1, "name", 0);
60 }
61 if (userHandle == 3) {
62 // User 3 is a profile of user 0.
63 return new UserInfo(0, "name", 0);
64 }
65 return null;
66 }
67 };
68 }
69 return super.getSystemService(name);
70 }
71 });
72
73 mStorage = new LockSettingsStorage(getContext(), new LockSettingsStorage.Callback() {
74 @Override
75 public void initialize(SQLiteDatabase db) {
76 mStorage.writeKeyValue(db, "initializedKey", "initialValue", 0);
77 }
78 }) {
79 @Override
80 String getLockPatternFilename(int userId) {
81 return new File(mStorageDir,
82 super.getLockPatternFilename(userId).replace('/', '-')).getAbsolutePath();
83 }
84
85 @Override
86 String getLockPasswordFilename(int userId) {
87 return new File(mStorageDir,
88 super.getLockPasswordFilename(userId).replace('/', '-')).getAbsolutePath();
89 }
Ricky Waia46b40f2016-03-31 16:48:29 +010090
91 @Override
92 String getChildProfileLockFile(int userId) {
93 return new File(mStorageDir,
94 super.getChildProfileLockFile(userId).replace('/', '-')).getAbsolutePath();
95 }
Adrian Roose5424992014-11-07 21:47:17 +010096 };
97 }
98
99 @Override
100 protected void tearDown() throws Exception {
101 super.tearDown();
102 mStorage.closeDatabase();
103 }
104
105 public void testKeyValue_InitializeWorked() {
106 assertEquals("initialValue", mStorage.readKeyValue("initializedKey", "default", 0));
107 mStorage.clearCache();
108 assertEquals("initialValue", mStorage.readKeyValue("initializedKey", "default", 0));
109 }
110
111 public void testKeyValue_WriteThenRead() {
112 mStorage.writeKeyValue("key", "value", 0);
113 assertEquals("value", mStorage.readKeyValue("key", "default", 0));
114 mStorage.clearCache();
115 assertEquals("value", mStorage.readKeyValue("key", "default", 0));
116 }
117
118 public void testKeyValue_DefaultValue() {
119 assertEquals("default", mStorage.readKeyValue("unititialized key", "default", 0));
120 assertEquals("default2", mStorage.readKeyValue("unititialized key", "default2", 0));
121 }
122
123 public void testKeyValue_Concurrency() {
124 final Object monitor = new Object();
125 List<Thread> threads = new ArrayList<>();
126 for (int i = 0; i < 100; i++) {
127 final int threadId = i;
128 threads.add(new Thread() {
129 @Override
130 public void run() {
131 synchronized (monitor) {
132 try {
133 monitor.wait();
134 } catch (InterruptedException e) {
135 return;
136 }
137 mStorage.writeKeyValue("key", "1 from thread " + threadId, 0);
138 mStorage.readKeyValue("key", "default", 0);
139 mStorage.writeKeyValue("key", "2 from thread " + threadId, 0);
140 mStorage.readKeyValue("key", "default", 0);
141 mStorage.writeKeyValue("key", "3 from thread " + threadId, 0);
142 mStorage.readKeyValue("key", "default", 0);
143 mStorage.writeKeyValue("key", "4 from thread " + threadId, 0);
144 mStorage.readKeyValue("key", "default", 0);
145 mStorage.writeKeyValue("key", "5 from thread " + threadId, 0);
146 mStorage.readKeyValue("key", "default", 0);
147 }
148 }
149 });
150 threads.get(i).start();
151 }
152 mStorage.writeKeyValue("key", "initalValue", 0);
153 synchronized (monitor) {
154 monitor.notifyAll();
155 }
156 for (int i = 0; i < threads.size(); i++) {
157 try {
158 threads.get(i).join();
159 } catch (InterruptedException e) {
160 }
161 }
162 assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
163 mStorage.clearCache();
164 assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
165 }
166
167 public void testKeyValue_CacheStarvedWriter() {
168 final CountDownLatch latch = new CountDownLatch(1);
169 List<Thread> threads = new ArrayList<>();
170 for (int i = 0; i < 100; i++) {
171 final int threadId = i;
172 threads.add(new Thread() {
173 @Override
174 public void run() {
175 try {
176 latch.await();
177 } catch (InterruptedException e) {
178 return;
179 }
180 if (threadId == 50) {
181 mStorage.writeKeyValue("starvedWriterKey", "value", 0);
182 } else {
183 mStorage.readKeyValue("starvedWriterKey", "default", 0);
184 }
185 }
186 });
187 threads.get(i).start();
188 }
189 latch.countDown();
190 for (int i = 0; i < threads.size(); i++) {
191 try {
192 threads.get(i).join();
193 } catch (InterruptedException e) {
194 }
195 }
196 String cached = mStorage.readKeyValue("key", "default", 0);
197 mStorage.clearCache();
198 String storage = mStorage.readKeyValue("key", "default", 0);
199 assertEquals("Cached value didn't match stored value", storage, cached);
200 }
201
202 public void testRemoveUser() {
203 mStorage.writeKeyValue("key", "value", 0);
204 mStorage.writePasswordHash(new byte[]{1}, 0);
205 mStorage.writePatternHash(new byte[]{2}, 0);
206
207 mStorage.writeKeyValue("key", "value", 1);
208 mStorage.writePasswordHash(new byte[]{1}, 1);
209 mStorage.writePatternHash(new byte[]{2}, 1);
210
211 mStorage.removeUser(0);
212
213 assertEquals("value", mStorage.readKeyValue("key", "default", 1));
214 assertEquals("default", mStorage.readKeyValue("key", "default", 0));
215 assertNotNull(mStorage.readPasswordHash(1));
216 assertNull(mStorage.readPasswordHash(0));
217 assertNotNull(mStorage.readPatternHash(1));
218 assertNull(mStorage.readPatternHash(0));
219 }
220
221 public void testPassword_Default() {
222 assertNull(mStorage.readPasswordHash(0));
223 }
224
225 public void testPassword_Write() {
226 mStorage.writePasswordHash("thepassword".getBytes(), 0);
227
Andres Morales8fa56652015-03-31 09:19:50 -0700228 assertArrayEquals("thepassword".getBytes(), mStorage.readPasswordHash(0).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100229 mStorage.clearCache();
Andres Morales8fa56652015-03-31 09:19:50 -0700230 assertArrayEquals("thepassword".getBytes(), mStorage.readPasswordHash(0).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100231 }
232
233 public void testPassword_WriteProfileWritesParent() {
234 mStorage.writePasswordHash("parentpasswordd".getBytes(), 1);
235 mStorage.writePasswordHash("profilepassword".getBytes(), 2);
236
Andres Morales8fa56652015-03-31 09:19:50 -0700237 assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(1).hash);
238 assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(2).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100239 mStorage.clearCache();
Andres Morales8fa56652015-03-31 09:19:50 -0700240 assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(1).hash);
241 assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(2).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100242 }
243
Ricky Waia46b40f2016-03-31 16:48:29 +0100244 public void testLockType_WriteProfileWritesParent() {
245 mStorage.writePasswordHash("parentpassword".getBytes(), 10);
246 mStorage.writePatternHash("12345678".getBytes(), 20);
247
248 assertEquals(2, mStorage.getStoredCredentialType(10));
249 assertEquals(1, mStorage.getStoredCredentialType(20));
250 mStorage.clearCache();
251 assertEquals(2, mStorage.getStoredCredentialType(10));
252 assertEquals(1, mStorage.getStoredCredentialType(20));
253 }
254
255 public void testProfileLock_ReadWriteChildProfileLock() {
256 assertFalse(mStorage.hasChildProfileLock(20));
257 mStorage.writeChildProfileLock(20, "profilepassword".getBytes());
258 assertArrayEquals("profilepassword".getBytes(), mStorage.readChildProfileLock(20));
259 assertTrue(mStorage.hasChildProfileLock(20));
260 mStorage.clearCache();
261 assertArrayEquals("profilepassword".getBytes(), mStorage.readChildProfileLock(20));
262 assertTrue(mStorage.hasChildProfileLock(20));
263 }
264
Adrian Roose5424992014-11-07 21:47:17 +0100265 public void testPassword_WriteParentWritesProfile() {
266 mStorage.writePasswordHash("profilepassword".getBytes(), 2);
267 mStorage.writePasswordHash("parentpasswordd".getBytes(), 1);
268
Andres Morales8fa56652015-03-31 09:19:50 -0700269 assertArrayEquals("parentpasswordd".getBytes(), mStorage.readPasswordHash(1).hash);
270 assertArrayEquals("parentpasswordd".getBytes(), mStorage.readPasswordHash(2).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100271 mStorage.clearCache();
Andres Morales8fa56652015-03-31 09:19:50 -0700272 assertArrayEquals("parentpasswordd".getBytes(), mStorage.readPasswordHash(1).hash);
273 assertArrayEquals("parentpasswordd".getBytes(), mStorage.readPasswordHash(2).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100274 }
275
276 public void testPattern_Default() {
277 assertNull(mStorage.readPasswordHash(0));
278 }
279
280 public void testPattern_Write() {
281 mStorage.writePatternHash("thepattern".getBytes(), 0);
282
Andres Morales8fa56652015-03-31 09:19:50 -0700283 assertArrayEquals("thepattern".getBytes(), mStorage.readPatternHash(0).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100284 mStorage.clearCache();
Andres Morales8fa56652015-03-31 09:19:50 -0700285 assertArrayEquals("thepattern".getBytes(), mStorage.readPatternHash(0).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100286 }
287
288 public void testPattern_WriteProfileWritesParent() {
289 mStorage.writePatternHash("parentpatternn".getBytes(), 1);
290 mStorage.writePatternHash("profilepattern".getBytes(), 2);
291
Andres Morales8fa56652015-03-31 09:19:50 -0700292 assertArrayEquals("profilepattern".getBytes(), mStorage.readPatternHash(1).hash);
293 assertArrayEquals("profilepattern".getBytes(), mStorage.readPatternHash(2).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100294 mStorage.clearCache();
Andres Morales8fa56652015-03-31 09:19:50 -0700295 assertArrayEquals("profilepattern".getBytes(), mStorage.readPatternHash(1).hash);
296 assertArrayEquals("profilepattern".getBytes(), mStorage.readPatternHash(2).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100297 }
298
299 public void testPattern_WriteParentWritesProfile() {
300 mStorage.writePatternHash("profilepattern".getBytes(), 2);
301 mStorage.writePatternHash("parentpatternn".getBytes(), 1);
302
Andres Morales8fa56652015-03-31 09:19:50 -0700303 assertArrayEquals("parentpatternn".getBytes(), mStorage.readPatternHash(1).hash);
304 assertArrayEquals("parentpatternn".getBytes(), mStorage.readPatternHash(2).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100305 mStorage.clearCache();
Andres Morales8fa56652015-03-31 09:19:50 -0700306 assertArrayEquals("parentpatternn".getBytes(), mStorage.readPatternHash(1).hash);
307 assertArrayEquals("parentpatternn".getBytes(), mStorage.readPatternHash(2).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100308 }
309
310 public void testPrefetch() {
311 mStorage.writeKeyValue("key", "toBeFetched", 0);
312 mStorage.writePatternHash("pattern".getBytes(), 0);
313 mStorage.writePasswordHash("password".getBytes(), 0);
314
315 mStorage.clearCache();
316 mStorage.prefetchUser(0);
317
318 assertEquals("toBeFetched", mStorage.readKeyValue("key", "default", 0));
Andres Morales8fa56652015-03-31 09:19:50 -0700319 assertArrayEquals("pattern".getBytes(), mStorage.readPatternHash(0).hash);
320 assertArrayEquals("password".getBytes(), mStorage.readPasswordHash(0).hash);
Adrian Roose5424992014-11-07 21:47:17 +0100321 }
322
323 public void testFileLocation_Owner() {
324 LockSettingsStorage storage = new LockSettingsStorage(getContext(), null);
325
326 assertEquals("/data/system/gesture.key", storage.getLockPatternFilename(0));
327 assertEquals("/data/system/password.key", storage.getLockPasswordFilename(0));
328 }
329
330 public void testFileLocation_SecondaryUser() {
331 LockSettingsStorage storage = new LockSettingsStorage(getContext(), null);
332
333 assertEquals("/data/system/users/1/gesture.key", storage.getLockPatternFilename(1));
334 assertEquals("/data/system/users/1/password.key", storage.getLockPasswordFilename(1));
335 }
336
337 public void testFileLocation_ProfileToSecondary() {
338 LockSettingsStorage storage = new LockSettingsStorage(getContext(), null);
339
340 assertEquals("/data/system/users/1/gesture.key", storage.getLockPatternFilename(2));
341 assertEquals("/data/system/users/1/password.key", storage.getLockPasswordFilename(2));
342 }
343
344 public void testFileLocation_ProfileToOwner() {
345 LockSettingsStorage storage = new LockSettingsStorage(getContext(), null);
346
347 assertEquals("/data/system/gesture.key", storage.getLockPatternFilename(3));
348 assertEquals("/data/system/password.key", storage.getLockPasswordFilename(3));
349 }
350
351 private static void assertArrayEquals(byte[] expected, byte[] actual) {
352 if (!Arrays.equals(expected, actual)) {
353 fail("expected:<" + Arrays.toString(expected) +
354 "> but was:<" + Arrays.toString(actual) + ">");
355 }
356 }
357}