blob: bf0e75d297ffa2cfaa55142baa580523458c9751 [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 }
90 };
91 }
92
93 @Override
94 protected void tearDown() throws Exception {
95 super.tearDown();
96 mStorage.closeDatabase();
97 }
98
99 public void testKeyValue_InitializeWorked() {
100 assertEquals("initialValue", mStorage.readKeyValue("initializedKey", "default", 0));
101 mStorage.clearCache();
102 assertEquals("initialValue", mStorage.readKeyValue("initializedKey", "default", 0));
103 }
104
105 public void testKeyValue_WriteThenRead() {
106 mStorage.writeKeyValue("key", "value", 0);
107 assertEquals("value", mStorage.readKeyValue("key", "default", 0));
108 mStorage.clearCache();
109 assertEquals("value", mStorage.readKeyValue("key", "default", 0));
110 }
111
112 public void testKeyValue_DefaultValue() {
113 assertEquals("default", mStorage.readKeyValue("unititialized key", "default", 0));
114 assertEquals("default2", mStorage.readKeyValue("unititialized key", "default2", 0));
115 }
116
117 public void testKeyValue_Concurrency() {
118 final Object monitor = new Object();
119 List<Thread> threads = new ArrayList<>();
120 for (int i = 0; i < 100; i++) {
121 final int threadId = i;
122 threads.add(new Thread() {
123 @Override
124 public void run() {
125 synchronized (monitor) {
126 try {
127 monitor.wait();
128 } catch (InterruptedException e) {
129 return;
130 }
131 mStorage.writeKeyValue("key", "1 from thread " + threadId, 0);
132 mStorage.readKeyValue("key", "default", 0);
133 mStorage.writeKeyValue("key", "2 from thread " + threadId, 0);
134 mStorage.readKeyValue("key", "default", 0);
135 mStorage.writeKeyValue("key", "3 from thread " + threadId, 0);
136 mStorage.readKeyValue("key", "default", 0);
137 mStorage.writeKeyValue("key", "4 from thread " + threadId, 0);
138 mStorage.readKeyValue("key", "default", 0);
139 mStorage.writeKeyValue("key", "5 from thread " + threadId, 0);
140 mStorage.readKeyValue("key", "default", 0);
141 }
142 }
143 });
144 threads.get(i).start();
145 }
146 mStorage.writeKeyValue("key", "initalValue", 0);
147 synchronized (monitor) {
148 monitor.notifyAll();
149 }
150 for (int i = 0; i < threads.size(); i++) {
151 try {
152 threads.get(i).join();
153 } catch (InterruptedException e) {
154 }
155 }
156 assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
157 mStorage.clearCache();
158 assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
159 }
160
161 public void testKeyValue_CacheStarvedWriter() {
162 final CountDownLatch latch = new CountDownLatch(1);
163 List<Thread> threads = new ArrayList<>();
164 for (int i = 0; i < 100; i++) {
165 final int threadId = i;
166 threads.add(new Thread() {
167 @Override
168 public void run() {
169 try {
170 latch.await();
171 } catch (InterruptedException e) {
172 return;
173 }
174 if (threadId == 50) {
175 mStorage.writeKeyValue("starvedWriterKey", "value", 0);
176 } else {
177 mStorage.readKeyValue("starvedWriterKey", "default", 0);
178 }
179 }
180 });
181 threads.get(i).start();
182 }
183 latch.countDown();
184 for (int i = 0; i < threads.size(); i++) {
185 try {
186 threads.get(i).join();
187 } catch (InterruptedException e) {
188 }
189 }
190 String cached = mStorage.readKeyValue("key", "default", 0);
191 mStorage.clearCache();
192 String storage = mStorage.readKeyValue("key", "default", 0);
193 assertEquals("Cached value didn't match stored value", storage, cached);
194 }
195
196 public void testRemoveUser() {
197 mStorage.writeKeyValue("key", "value", 0);
198 mStorage.writePasswordHash(new byte[]{1}, 0);
199 mStorage.writePatternHash(new byte[]{2}, 0);
200
201 mStorage.writeKeyValue("key", "value", 1);
202 mStorage.writePasswordHash(new byte[]{1}, 1);
203 mStorage.writePatternHash(new byte[]{2}, 1);
204
205 mStorage.removeUser(0);
206
207 assertEquals("value", mStorage.readKeyValue("key", "default", 1));
208 assertEquals("default", mStorage.readKeyValue("key", "default", 0));
209 assertNotNull(mStorage.readPasswordHash(1));
210 assertNull(mStorage.readPasswordHash(0));
211 assertNotNull(mStorage.readPatternHash(1));
212 assertNull(mStorage.readPatternHash(0));
213 }
214
215 public void testPassword_Default() {
216 assertNull(mStorage.readPasswordHash(0));
217 }
218
219 public void testPassword_Write() {
220 mStorage.writePasswordHash("thepassword".getBytes(), 0);
221
222 assertArrayEquals("thepassword".getBytes(), mStorage.readPasswordHash(0));
223 mStorage.clearCache();
224 assertArrayEquals("thepassword".getBytes(), mStorage.readPasswordHash(0));
225 }
226
227 public void testPassword_WriteProfileWritesParent() {
228 mStorage.writePasswordHash("parentpasswordd".getBytes(), 1);
229 mStorage.writePasswordHash("profilepassword".getBytes(), 2);
230
231 assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(1));
232 assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(2));
233 mStorage.clearCache();
234 assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(1));
235 assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(2));
236 }
237
238 public void testPassword_WriteParentWritesProfile() {
239 mStorage.writePasswordHash("profilepassword".getBytes(), 2);
240 mStorage.writePasswordHash("parentpasswordd".getBytes(), 1);
241
242 assertArrayEquals("parentpasswordd".getBytes(), mStorage.readPasswordHash(1));
243 assertArrayEquals("parentpasswordd".getBytes(), mStorage.readPasswordHash(2));
244 mStorage.clearCache();
245 assertArrayEquals("parentpasswordd".getBytes(), mStorage.readPasswordHash(1));
246 assertArrayEquals("parentpasswordd".getBytes(), mStorage.readPasswordHash(2));
247 }
248
249 public void testPattern_Default() {
250 assertNull(mStorage.readPasswordHash(0));
251 }
252
253 public void testPattern_Write() {
254 mStorage.writePatternHash("thepattern".getBytes(), 0);
255
256 assertArrayEquals("thepattern".getBytes(), mStorage.readPatternHash(0));
257 mStorage.clearCache();
258 assertArrayEquals("thepattern".getBytes(), mStorage.readPatternHash(0));
259 }
260
261 public void testPattern_WriteProfileWritesParent() {
262 mStorage.writePatternHash("parentpatternn".getBytes(), 1);
263 mStorage.writePatternHash("profilepattern".getBytes(), 2);
264
265 assertArrayEquals("profilepattern".getBytes(), mStorage.readPatternHash(1));
266 assertArrayEquals("profilepattern".getBytes(), mStorage.readPatternHash(2));
267 mStorage.clearCache();
268 assertArrayEquals("profilepattern".getBytes(), mStorage.readPatternHash(1));
269 assertArrayEquals("profilepattern".getBytes(), mStorage.readPatternHash(2));
270 }
271
272 public void testPattern_WriteParentWritesProfile() {
273 mStorage.writePatternHash("profilepattern".getBytes(), 2);
274 mStorage.writePatternHash("parentpatternn".getBytes(), 1);
275
276 assertArrayEquals("parentpatternn".getBytes(), mStorage.readPatternHash(1));
277 assertArrayEquals("parentpatternn".getBytes(), mStorage.readPatternHash(2));
278 mStorage.clearCache();
279 assertArrayEquals("parentpatternn".getBytes(), mStorage.readPatternHash(1));
280 assertArrayEquals("parentpatternn".getBytes(), mStorage.readPatternHash(2));
281 }
282
283 public void testPrefetch() {
284 mStorage.writeKeyValue("key", "toBeFetched", 0);
285 mStorage.writePatternHash("pattern".getBytes(), 0);
286 mStorage.writePasswordHash("password".getBytes(), 0);
287
288 mStorage.clearCache();
289 mStorage.prefetchUser(0);
290
291 assertEquals("toBeFetched", mStorage.readKeyValue("key", "default", 0));
292 assertArrayEquals("pattern".getBytes(), mStorage.readPatternHash(0));
293 assertArrayEquals("password".getBytes(), mStorage.readPasswordHash(0));
294 }
295
296 public void testFileLocation_Owner() {
297 LockSettingsStorage storage = new LockSettingsStorage(getContext(), null);
298
299 assertEquals("/data/system/gesture.key", storage.getLockPatternFilename(0));
300 assertEquals("/data/system/password.key", storage.getLockPasswordFilename(0));
301 }
302
303 public void testFileLocation_SecondaryUser() {
304 LockSettingsStorage storage = new LockSettingsStorage(getContext(), null);
305
306 assertEquals("/data/system/users/1/gesture.key", storage.getLockPatternFilename(1));
307 assertEquals("/data/system/users/1/password.key", storage.getLockPasswordFilename(1));
308 }
309
310 public void testFileLocation_ProfileToSecondary() {
311 LockSettingsStorage storage = new LockSettingsStorage(getContext(), null);
312
313 assertEquals("/data/system/users/1/gesture.key", storage.getLockPatternFilename(2));
314 assertEquals("/data/system/users/1/password.key", storage.getLockPasswordFilename(2));
315 }
316
317 public void testFileLocation_ProfileToOwner() {
318 LockSettingsStorage storage = new LockSettingsStorage(getContext(), null);
319
320 assertEquals("/data/system/gesture.key", storage.getLockPatternFilename(3));
321 assertEquals("/data/system/password.key", storage.getLockPasswordFilename(3));
322 }
323
324 private static void assertArrayEquals(byte[] expected, byte[] actual) {
325 if (!Arrays.equals(expected, actual)) {
326 fail("expected:<" + Arrays.toString(expected) +
327 "> but was:<" + Arrays.toString(actual) + ">");
328 }
329 }
330}