blob: 35e7afad301ccce55e9047d4d858636be246ae2d [file] [log] [blame]
Amith Yamasani52c489c2012-03-28 11:42:42 -07001/*
2 * Copyright (C) 2012 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
Jeff Sharkey7a96c392012-11-15 14:01:46 -080017package com.android.server;
Amith Yamasani52c489c2012-03-28 11:42:42 -070018
Jim Millerf45bb402013-08-20 18:58:32 -070019import android.app.ActivityManagerNative;
Amith Yamasani52c489c2012-03-28 11:42:42 -070020import android.content.ContentResolver;
21import android.content.ContentValues;
22import android.content.Context;
Jim Miller158fe192013-04-17 15:23:55 -070023import android.content.pm.PackageManager;
Jim Miller187ec582013-04-15 18:27:54 -070024import android.content.pm.UserInfo;
25
26import static android.content.Context.USER_SERVICE;
Jim Miller158fe192013-04-17 15:23:55 -070027import static android.Manifest.permission.READ_PROFILE;
Amith Yamasani52c489c2012-03-28 11:42:42 -070028import android.database.Cursor;
29import android.database.sqlite.SQLiteDatabase;
30import android.database.sqlite.SQLiteOpenHelper;
Jim Millerf45bb402013-08-20 18:58:32 -070031import android.database.sqlite.SQLiteStatement;
32import android.media.AudioManager;
33import android.media.AudioService;
Amith Yamasani52c489c2012-03-28 11:42:42 -070034import android.os.Binder;
Amith Yamasani61f57372012-08-31 12:12:28 -070035import android.os.Environment;
Amith Yamasani52c489c2012-03-28 11:42:42 -070036import android.os.RemoteException;
Amith Yamasanid1645f82012-06-12 11:53:26 -070037import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070038import android.os.UserHandle;
Jim Miller187ec582013-04-15 18:27:54 -070039import android.os.UserManager;
Amith Yamasani52c489c2012-03-28 11:42:42 -070040import android.provider.Settings;
41import android.provider.Settings.Secure;
Jim Miller187ec582013-04-15 18:27:54 -070042import android.provider.Settings.SettingNotFoundException;
Jim Millerde1af082013-09-11 14:58:26 -070043import android.security.KeyStore;
Amith Yamasani52c489c2012-03-28 11:42:42 -070044import android.text.TextUtils;
Jim Millerf45bb402013-08-20 18:58:32 -070045import android.util.Log;
Amith Yamasani52c489c2012-03-28 11:42:42 -070046import android.util.Slog;
47
Jeff Sharkey7a96c392012-11-15 14:01:46 -080048import com.android.internal.widget.ILockSettings;
49import com.android.internal.widget.LockPatternUtils;
50
Amith Yamasani52c489c2012-03-28 11:42:42 -070051import java.io.File;
52import java.io.FileNotFoundException;
53import java.io.IOException;
54import java.io.RandomAccessFile;
55import java.util.Arrays;
Jim Miller187ec582013-04-15 18:27:54 -070056import java.util.List;
Amith Yamasani52c489c2012-03-28 11:42:42 -070057
58/**
59 * Keeps the lock pattern/password data and related settings for each user.
60 * Used by LockPatternUtils. Needs to be a service because Settings app also needs
61 * to be able to save lockscreen information for secondary users.
62 * @hide
63 */
64public class LockSettingsService extends ILockSettings.Stub {
65
Jim Miller5ecd8112013-01-09 18:50:26 -080066 private static final String PERMISSION = "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE";
Amith Yamasani52c489c2012-03-28 11:42:42 -070067 private final DatabaseHelper mOpenHelper;
68 private static final String TAG = "LockSettingsService";
69
70 private static final String TABLE = "locksettings";
71 private static final String COLUMN_KEY = "name";
72 private static final String COLUMN_USERID = "user";
73 private static final String COLUMN_VALUE = "value";
74
75 private static final String[] COLUMNS_FOR_QUERY = {
76 COLUMN_VALUE
77 };
78
79 private static final String SYSTEM_DIRECTORY = "/system/";
80 private static final String LOCK_PATTERN_FILE = "gesture.key";
81 private static final String LOCK_PASSWORD_FILE = "password.key";
82
83 private final Context mContext;
Jim Millerde1af082013-09-11 14:58:26 -070084 private LockPatternUtils mLockPatternUtils;
Amith Yamasani52c489c2012-03-28 11:42:42 -070085
86 public LockSettingsService(Context context) {
87 mContext = context;
88 // Open the database
89 mOpenHelper = new DatabaseHelper(mContext);
Jim Millerde1af082013-09-11 14:58:26 -070090
91 mLockPatternUtils = new LockPatternUtils(context);
Amith Yamasani52c489c2012-03-28 11:42:42 -070092 }
93
94 public void systemReady() {
95 migrateOldData();
96 }
97
98 private void migrateOldData() {
99 try {
Jim Miller187ec582013-04-15 18:27:54 -0700100 // These Settings moved before multi-user was enabled, so we only have to do it for the
101 // root user.
102 if (getString("migrated", null, 0) == null) {
103 final ContentResolver cr = mContext.getContentResolver();
104 for (String validSetting : VALID_SETTINGS) {
105 String value = Settings.Secure.getString(cr, validSetting);
106 if (value != null) {
107 setString(validSetting, value, 0);
108 }
109 }
110 // No need to move the password / pattern files. They're already in the right place.
111 setString("migrated", "true", 0);
112 Slog.i(TAG, "Migrated lock settings to new location");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700113 }
114
Jim Miller187ec582013-04-15 18:27:54 -0700115 // These Settings changed after multi-user was enabled, hence need to be moved per user.
116 if (getString("migrated_user_specific", null, 0) == null) {
117 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
118 final ContentResolver cr = mContext.getContentResolver();
119 List<UserInfo> users = um.getUsers();
120 for (int user = 0; user < users.size(); user++) {
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700121 // Migrate owner info
122 final int userId = users.get(user).id;
123 final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
124 String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
125 if (ownerInfo != null) {
126 setString(OWNER_INFO, ownerInfo, userId);
127 Settings.Secure.putStringForUser(cr, ownerInfo, "", userId);
128 }
Jim Miller187ec582013-04-15 18:27:54 -0700129
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700130 // Migrate owner info enabled. Note there was a bug where older platforms only
131 // stored this value if the checkbox was toggled at least once. The code detects
132 // this case by handling the exception.
133 final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
134 boolean enabled;
135 try {
136 int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
137 enabled = ivalue != 0;
138 setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
139 } catch (SettingNotFoundException e) {
140 // Setting was never stored. Store it if the string is not empty.
141 if (!TextUtils.isEmpty(ownerInfo)) {
142 setLong(OWNER_INFO_ENABLED, 1, userId);
Jim Miller187ec582013-04-15 18:27:54 -0700143 }
144 }
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700145 Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700146 }
Jim Miller187ec582013-04-15 18:27:54 -0700147 // No need to move the password / pattern files. They're already in the right place.
148 setString("migrated_user_specific", "true", 0);
149 Slog.i(TAG, "Migrated per-user lock settings to new location");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700150 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700151 } catch (RemoteException re) {
Jim Miller187ec582013-04-15 18:27:54 -0700152 Slog.e(TAG, "Unable to migrate old data", re);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700153 }
154 }
155
Jim Miller5ecd8112013-01-09 18:50:26 -0800156 private final void checkWritePermission(int userId) {
Jim Miller505329b2013-11-08 13:25:36 -0800157 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700158 }
159
Jim Miller5ecd8112013-01-09 18:50:26 -0800160 private final void checkPasswordReadPermission(int userId) {
Jim Miller505329b2013-11-08 13:25:36 -0800161 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700162 }
163
Jim Miller158fe192013-04-17 15:23:55 -0700164 private final void checkReadPermission(String requestedKey, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700165 final int callingUid = Binder.getCallingUid();
Jim Miller158fe192013-04-17 15:23:55 -0700166 for (int i = 0; i < READ_PROFILE_PROTECTED_SETTINGS.length; i++) {
167 String key = READ_PROFILE_PROTECTED_SETTINGS[i];
168 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_PROFILE)
169 != PackageManager.PERMISSION_GRANTED) {
170 throw new SecurityException("uid=" + callingUid
171 + " needs permission " + READ_PROFILE + " to read "
172 + requestedKey + " for user " + userId);
173 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700174 }
175 }
176
177 @Override
178 public void setBoolean(String key, boolean value, int userId) throws RemoteException {
179 checkWritePermission(userId);
180
181 writeToDb(key, value ? "1" : "0", userId);
182 }
183
184 @Override
185 public void setLong(String key, long value, int userId) throws RemoteException {
186 checkWritePermission(userId);
187
188 writeToDb(key, Long.toString(value), userId);
189 }
190
191 @Override
192 public void setString(String key, String value, int userId) throws RemoteException {
193 checkWritePermission(userId);
194
195 writeToDb(key, value, userId);
196 }
197
198 @Override
199 public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700200 checkReadPermission(key, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700201
202 String value = readFromDb(key, null, userId);
203 return TextUtils.isEmpty(value) ?
204 defaultValue : (value.equals("1") || value.equals("true"));
205 }
206
207 @Override
208 public long getLong(String key, long defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700209 checkReadPermission(key, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700210
211 String value = readFromDb(key, null, userId);
212 return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
213 }
214
215 @Override
216 public String getString(String key, String defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700217 checkReadPermission(key, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700218
219 return readFromDb(key, defaultValue, userId);
220 }
221
222 private String getLockPatternFilename(int userId) {
223 String dataSystemDirectory =
224 android.os.Environment.getDataDirectory().getAbsolutePath() +
225 SYSTEM_DIRECTORY;
226 if (userId == 0) {
227 // Leave it in the same place for user 0
228 return dataSystemDirectory + LOCK_PATTERN_FILE;
229 } else {
Amith Yamasani61f57372012-08-31 12:12:28 -0700230 return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
231 .getAbsolutePath();
Amith Yamasani52c489c2012-03-28 11:42:42 -0700232 }
233 }
234
235 private String getLockPasswordFilename(int userId) {
236 String dataSystemDirectory =
237 android.os.Environment.getDataDirectory().getAbsolutePath() +
238 SYSTEM_DIRECTORY;
239 if (userId == 0) {
240 // Leave it in the same place for user 0
241 return dataSystemDirectory + LOCK_PASSWORD_FILE;
242 } else {
Amith Yamasani61f57372012-08-31 12:12:28 -0700243 return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE)
244 .getAbsolutePath();
Amith Yamasani52c489c2012-03-28 11:42:42 -0700245 }
246 }
247
248 @Override
249 public boolean havePassword(int userId) throws RemoteException {
250 // Do we need a permissions check here?
251
252 return new File(getLockPasswordFilename(userId)).length() > 0;
253 }
254
255 @Override
256 public boolean havePattern(int userId) throws RemoteException {
257 // Do we need a permissions check here?
258
259 return new File(getLockPatternFilename(userId)).length() > 0;
260 }
261
Jim Millerde1af082013-09-11 14:58:26 -0700262 private void maybeUpdateKeystore(String password, int userId) {
263 if (userId == UserHandle.USER_OWNER) {
264 final KeyStore keyStore = KeyStore.getInstance();
265 // Conditionally reset the keystore if empty. If non-empty, we are just
266 // switching key guard type
267 if (TextUtils.isEmpty(password) && keyStore.isEmpty()) {
268 keyStore.reset();
269 } else {
270 // Update the keystore password
271 keyStore.password(password);
272 }
273 }
274 }
275
Amith Yamasani52c489c2012-03-28 11:42:42 -0700276 @Override
Jim Millerde1af082013-09-11 14:58:26 -0700277 public void setLockPattern(String pattern, int userId) throws RemoteException {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700278 checkWritePermission(userId);
279
Jim Millerde1af082013-09-11 14:58:26 -0700280 maybeUpdateKeystore(pattern, userId);
281
282 final byte[] hash = LockPatternUtils.patternToHash(
283 LockPatternUtils.stringToPattern(pattern));
Amith Yamasani52c489c2012-03-28 11:42:42 -0700284 writeFile(getLockPatternFilename(userId), hash);
285 }
286
287 @Override
Jim Millerde1af082013-09-11 14:58:26 -0700288 public void setLockPassword(String password, int userId) throws RemoteException {
289 checkWritePermission(userId);
290
291 maybeUpdateKeystore(password, userId);
292
293 writeFile(getLockPasswordFilename(userId), mLockPatternUtils.passwordToHash(password));
294 }
295
296 @Override
297 public boolean checkPattern(String pattern, int userId) throws RemoteException {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700298 checkPasswordReadPermission(userId);
299 try {
300 // Read all the bytes from the file
301 RandomAccessFile raf = new RandomAccessFile(getLockPatternFilename(userId), "r");
302 final byte[] stored = new byte[(int) raf.length()];
303 int got = raf.read(stored, 0, stored.length);
304 raf.close();
305 if (got <= 0) {
306 return true;
307 }
308 // Compare the hash from the file with the entered pattern's hash
Jim Millerde1af082013-09-11 14:58:26 -0700309 final byte[] hash = LockPatternUtils.patternToHash(
310 LockPatternUtils.stringToPattern(pattern));
311 final boolean matched = Arrays.equals(stored, hash);
312 if (matched && !TextUtils.isEmpty(pattern)) {
313 maybeUpdateKeystore(pattern, userId);
314 }
315 return matched;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700316 } catch (FileNotFoundException fnfe) {
317 Slog.e(TAG, "Cannot read file " + fnfe);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700318 } catch (IOException ioe) {
319 Slog.e(TAG, "Cannot read file " + ioe);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700320 }
Jim Millerde1af082013-09-11 14:58:26 -0700321 return true;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700322 }
323
324 @Override
Jim Millerde1af082013-09-11 14:58:26 -0700325 public boolean checkPassword(String password, int userId) throws RemoteException {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700326 checkPasswordReadPermission(userId);
327
328 try {
329 // Read all the bytes from the file
330 RandomAccessFile raf = new RandomAccessFile(getLockPasswordFilename(userId), "r");
331 final byte[] stored = new byte[(int) raf.length()];
332 int got = raf.read(stored, 0, stored.length);
333 raf.close();
334 if (got <= 0) {
335 return true;
336 }
337 // Compare the hash from the file with the entered password's hash
Jim Millerde1af082013-09-11 14:58:26 -0700338 final byte[] hash = mLockPatternUtils.passwordToHash(password);
339 final boolean matched = Arrays.equals(stored, hash);
340 if (matched && !TextUtils.isEmpty(password)) {
341 maybeUpdateKeystore(password, userId);
342 }
343 return matched;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700344 } catch (FileNotFoundException fnfe) {
345 Slog.e(TAG, "Cannot read file " + fnfe);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700346 } catch (IOException ioe) {
347 Slog.e(TAG, "Cannot read file " + ioe);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700348 }
Jim Millerde1af082013-09-11 14:58:26 -0700349 return true;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700350 }
351
352 @Override
353 public void removeUser(int userId) {
354 checkWritePermission(userId);
355
356 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
357 try {
358 File file = new File(getLockPasswordFilename(userId));
359 if (file.exists()) {
360 file.delete();
361 }
362 file = new File(getLockPatternFilename(userId));
363 if (file.exists()) {
364 file.delete();
365 }
366
367 db.beginTransaction();
368 db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null);
369 db.setTransactionSuccessful();
370 } finally {
371 db.endTransaction();
372 }
373 }
374
375 private void writeFile(String name, byte[] hash) {
376 try {
377 // Write the hash to file
378 RandomAccessFile raf = new RandomAccessFile(name, "rw");
379 // Truncate the file if pattern is null, to clear the lock
380 if (hash == null || hash.length == 0) {
381 raf.setLength(0);
382 } else {
383 raf.write(hash, 0, hash.length);
384 }
385 raf.close();
386 } catch (IOException ioe) {
387 Slog.e(TAG, "Error writing to file " + ioe);
388 }
389 }
390
391 private void writeToDb(String key, String value, int userId) {
Amith Yamasanid1645f82012-06-12 11:53:26 -0700392 writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId);
393 }
394
395 private void writeToDb(SQLiteDatabase db, String key, String value, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700396 ContentValues cv = new ContentValues();
397 cv.put(COLUMN_KEY, key);
398 cv.put(COLUMN_USERID, userId);
399 cv.put(COLUMN_VALUE, value);
400
Amith Yamasani52c489c2012-03-28 11:42:42 -0700401 db.beginTransaction();
402 try {
403 db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
404 new String[] {key, Integer.toString(userId)});
405 db.insert(TABLE, null, cv);
406 db.setTransactionSuccessful();
407 } finally {
408 db.endTransaction();
409 }
410 }
411
412 private String readFromDb(String key, String defaultValue, int userId) {
413 Cursor cursor;
414 String result = defaultValue;
415 SQLiteDatabase db = mOpenHelper.getReadableDatabase();
416 if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
417 COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
418 new String[] { Integer.toString(userId), key },
419 null, null, null)) != null) {
420 if (cursor.moveToFirst()) {
421 result = cursor.getString(0);
422 }
423 cursor.close();
424 }
425 return result;
426 }
427
428 class DatabaseHelper extends SQLiteOpenHelper {
429 private static final String TAG = "LockSettingsDB";
430 private static final String DATABASE_NAME = "locksettings.db";
431
Jim Millerf45bb402013-08-20 18:58:32 -0700432 private static final int DATABASE_VERSION = 2;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700433
434 public DatabaseHelper(Context context) {
435 super(context, DATABASE_NAME, null, DATABASE_VERSION);
436 setWriteAheadLoggingEnabled(true);
437 }
438
439 private void createTable(SQLiteDatabase db) {
440 db.execSQL("CREATE TABLE " + TABLE + " (" +
441 "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
442 COLUMN_KEY + " TEXT," +
443 COLUMN_USERID + " INTEGER," +
444 COLUMN_VALUE + " TEXT" +
445 ");");
446 }
447
448 @Override
449 public void onCreate(SQLiteDatabase db) {
450 createTable(db);
Amith Yamasanid1645f82012-06-12 11:53:26 -0700451 initializeDefaults(db);
452 }
453
454 private void initializeDefaults(SQLiteDatabase db) {
455 // Get the lockscreen default from a system property, if available
456 boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default",
457 false);
458 if (lockScreenDisable) {
459 writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
460 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700461 }
462
463 @Override
464 public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
Jim Millerf45bb402013-08-20 18:58:32 -0700465 int upgradeVersion = oldVersion;
466 if (upgradeVersion == 1) {
467 // Set the initial value for {@link LockPatternUtils#LOCKSCREEN_WIDGETS_ENABLED}
468 // during upgrade based on whether each user previously had widgets in keyguard.
469 maybeEnableWidgetSettingForUsers(db);
470 upgradeVersion = 2;
471 }
472
473 if (upgradeVersion != DATABASE_VERSION) {
474 Log.w(TAG, "Failed to upgrade database!");
475 }
476 }
477
478 private void maybeEnableWidgetSettingForUsers(SQLiteDatabase db) {
479 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
480 final ContentResolver cr = mContext.getContentResolver();
Jim Millerf45bb402013-08-20 18:58:32 -0700481 final List<UserInfo> users = um.getUsers();
482 for (int i = 0; i < users.size(); i++) {
483 final int userId = users.get(i).id;
Jim Millerde1af082013-09-11 14:58:26 -0700484 final boolean enabled = mLockPatternUtils.hasWidgetsEnabledInKeyguard(userId);
Jim Millerf45bb402013-08-20 18:58:32 -0700485 Log.v(TAG, "Widget upgrade uid=" + userId + ", enabled="
Jim Millerde1af082013-09-11 14:58:26 -0700486 + enabled + ", w[]=" + mLockPatternUtils.getAppWidgets());
Jim Millerf45bb402013-08-20 18:58:32 -0700487 loadSetting(db, LockPatternUtils.LOCKSCREEN_WIDGETS_ENABLED, userId, enabled);
488 }
489 }
490
491 private void loadSetting(SQLiteDatabase db, String key, int userId, boolean value) {
492 SQLiteStatement stmt = null;
493 try {
494 stmt = db.compileStatement(
495 "INSERT OR REPLACE INTO locksettings(name,user,value) VALUES(?,?,?);");
496 stmt.bindString(1, key);
497 stmt.bindLong(2, userId);
498 stmt.bindLong(3, value ? 1 : 0);
499 stmt.execute();
500 } finally {
501 if (stmt != null) stmt.close();
502 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700503 }
504 }
505
506 private static final String[] VALID_SETTINGS = new String[] {
507 LockPatternUtils.LOCKOUT_PERMANENT_KEY,
508 LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
509 LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
510 LockPatternUtils.PASSWORD_TYPE_KEY,
511 LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
512 LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
513 LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
514 LockPatternUtils.LOCKSCREEN_OPTIONS,
515 LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
516 LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
517 LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
518 LockPatternUtils.PASSWORD_HISTORY_KEY,
519 Secure.LOCK_PATTERN_ENABLED,
520 Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
521 Secure.LOCK_PATTERN_VISIBLE,
522 Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
Jim Miller187ec582013-04-15 18:27:54 -0700523 };
524
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700525 // These are protected with a read permission
526 private static final String[] READ_PROFILE_PROTECTED_SETTINGS = new String[] {
Jim Miller187ec582013-04-15 18:27:54 -0700527 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
528 Secure.LOCK_SCREEN_OWNER_INFO
529 };
Amith Yamasani52c489c2012-03-28 11:42:42 -0700530}