diff options
-rw-r--r-- | services/core/java/com/android/server/LockSettingsService.java | 335 | ||||
-rw-r--r-- | services/core/java/com/android/server/LockSettingsStorage.java | 307 |
2 files changed, 364 insertions, 278 deletions
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index b708c3f96ae7..11ba8e8114b3 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -18,49 +18,38 @@ package com.android.server; import android.content.BroadcastReceiver; import android.content.ContentResolver; -import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.UserInfo; +import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE; import static android.content.Context.USER_SERVICE; import static android.Manifest.permission.READ_PROFILE; -import android.database.Cursor; + import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteStatement; import android.os.Binder; -import android.os.Environment; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.os.storage.IMountService; import android.os.ServiceManager; -import android.os.storage.StorageManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Secure; import android.provider.Settings.SettingNotFoundException; -import android.security.KeyChain; -import android.security.KeyChain.KeyChainConnection; import android.security.KeyStore; import android.text.TextUtils; import android.util.Log; import android.util.Slog; -import com.android.internal.os.BackgroundThread; import com.android.internal.widget.ILockSettings; import com.android.internal.widget.ILockSettingsObserver; import com.android.internal.widget.LockPatternUtils; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -73,27 +62,17 @@ import java.util.List; */ public class LockSettingsService extends ILockSettings.Stub { - private static final String PERMISSION = "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"; + private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE; private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; - private final DatabaseHelper mOpenHelper; - private static final String TAG = "LockSettingsService"; - private static final String TABLE = "locksettings"; - private static final String COLUMN_KEY = "name"; - private static final String COLUMN_USERID = "user"; - private static final String COLUMN_VALUE = "value"; + private static final String TAG = "LockSettingsService"; - private static final String[] COLUMNS_FOR_QUERY = { - COLUMN_VALUE - }; + private final Context mContext; - private static final String SYSTEM_DIRECTORY = "/system/"; - private static final String LOCK_PATTERN_FILE = "gesture.key"; - private static final String LOCK_PASSWORD_FILE = "password.key"; + private final LockSettingsStorage mStorage; - private final Context mContext; private LockPatternUtils mLockPatternUtils; private boolean mFirstCallToVold; @@ -102,7 +81,6 @@ public class LockSettingsService extends ILockSettings.Stub { public LockSettingsService(Context context) { mContext = context; // Open the database - mOpenHelper = new DatabaseHelper(mContext); mLockPatternUtils = new LockPatternUtils(context); mFirstCallToVold = true; @@ -110,6 +88,18 @@ public class LockSettingsService extends ILockSettings.Stub { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_ADDED); mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); + + mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() { + @Override + public void initialize(SQLiteDatabase db) { + // Get the lockscreen default from a system property, if available + boolean lockScreenDisable = SystemProperties.getBoolean( + "ro.lockscreen.disable.default", false); + if (lockScreenDisable) { + mStorage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0); + } + } + }); } private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @@ -220,29 +210,31 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public void setBoolean(String key, boolean value, int userId) throws RemoteException { checkWritePermission(userId); - - writeToDb(key, value ? "1" : "0", userId); + setStringUnchecked(key, userId, value ? "1" : "0"); } @Override public void setLong(String key, long value, int userId) throws RemoteException { checkWritePermission(userId); - - writeToDb(key, Long.toString(value), userId); + setStringUnchecked(key, userId, Long.toString(value)); } @Override public void setString(String key, String value, int userId) throws RemoteException { checkWritePermission(userId); + setStringUnchecked(key, userId, value); + } - writeToDb(key, value, userId); + private void setStringUnchecked(String key, int userId, String value) { + mStorage.writeKeyValue(key, value, userId); + notifyObservers(key, userId); } @Override public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException { checkReadPermission(key, userId); - String value = readFromDb(key, null, userId); + String value = mStorage.readKeyValue(key, null, userId); return TextUtils.isEmpty(value) ? defaultValue : (value.equals("1") || value.equals("true")); } @@ -251,7 +243,7 @@ public class LockSettingsService extends ILockSettings.Stub { public long getLong(String key, long defaultValue, int userId) throws RemoteException { checkReadPermission(key, userId); - String value = readFromDb(key, null, userId); + String value = mStorage.readKeyValue(key, null, userId); return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value); } @@ -259,7 +251,7 @@ public class LockSettingsService extends ILockSettings.Stub { public String getString(String key, String defaultValue, int userId) throws RemoteException { checkReadPermission(key, userId); - return readFromDb(key, defaultValue, userId); + return mStorage.readKeyValue(key, defaultValue, userId); } @Override @@ -308,57 +300,18 @@ public class LockSettingsService extends ILockSettings.Stub { } } - private int getUserParentOrSelfId(int userId) { - if (userId != 0) { - final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); - final UserInfo pi = um.getProfileParent(userId); - if (pi != null) { - return pi.id; - } - } - return userId; - } - - private String getLockPatternFilename(int userId) { - String dataSystemDirectory = - android.os.Environment.getDataDirectory().getAbsolutePath() + - SYSTEM_DIRECTORY; - userId = getUserParentOrSelfId(userId); - if (userId == 0) { - // Leave it in the same place for user 0 - return dataSystemDirectory + LOCK_PATTERN_FILE; - } else { - return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE) - .getAbsolutePath(); - } - } - - private String getLockPasswordFilename(int userId) { - userId = getUserParentOrSelfId(userId); - String dataSystemDirectory = - android.os.Environment.getDataDirectory().getAbsolutePath() + - SYSTEM_DIRECTORY; - if (userId == 0) { - // Leave it in the same place for user 0 - return dataSystemDirectory + LOCK_PASSWORD_FILE; - } else { - return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE) - .getAbsolutePath(); - } - } - @Override public boolean havePassword(int userId) throws RemoteException { // Do we need a permissions check here? - return new File(getLockPasswordFilename(userId)).length() > 0; + return mStorage.hasPassword(userId); } @Override public boolean havePattern(int userId) throws RemoteException { // Do we need a permissions check here? - return new File(getLockPatternFilename(userId)).length() > 0; + return mStorage.hasPattern(userId); } private void maybeUpdateKeystore(String password, int userHandle) { @@ -394,7 +347,7 @@ public class LockSettingsService extends ILockSettings.Stub { final byte[] hash = LockPatternUtils.patternToHash( LockPatternUtils.stringToPattern(pattern)); - writeFile(getLockPatternFilename(userId), hash); + mStorage.writePatternHash(hash, userId); } @Override @@ -403,68 +356,46 @@ public class LockSettingsService extends ILockSettings.Stub { maybeUpdateKeystore(password, userId); - writeFile(getLockPasswordFilename(userId), - mLockPatternUtils.passwordToHash(password, userId)); + mStorage.writePasswordHash(mLockPatternUtils.passwordToHash(password, userId), userId); } @Override public boolean checkPattern(String pattern, int userId) throws RemoteException { checkPasswordReadPermission(userId); - try { - // Read all the bytes from the file - RandomAccessFile raf = new RandomAccessFile(getLockPatternFilename(userId), "r"); - final byte[] stored = new byte[(int) raf.length()]; - int got = raf.read(stored, 0, stored.length); - raf.close(); - if (got <= 0) { - return true; - } - // Compare the hash from the file with the entered pattern's hash - final byte[] hash = LockPatternUtils.patternToHash( - LockPatternUtils.stringToPattern(pattern)); - final boolean matched = Arrays.equals(stored, hash); - if (matched && !TextUtils.isEmpty(pattern)) { - maybeUpdateKeystore(pattern, userId); - } - return matched; - } catch (FileNotFoundException fnfe) { - Slog.e(TAG, "Cannot read file " + fnfe); - } catch (IOException ioe) { - Slog.e(TAG, "Cannot read file " + ioe); + byte[] hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(pattern)); + byte[] storedHash = mStorage.readPatternHash(userId); + + if (storedHash == null) { + return true; } - return true; + + boolean matched = Arrays.equals(hash, storedHash); + if (matched && !TextUtils.isEmpty(pattern)) { + maybeUpdateKeystore(pattern, userId); + } + return matched; } @Override public boolean checkPassword(String password, int userId) throws RemoteException { checkPasswordReadPermission(userId); - try { - // Read all the bytes from the file - RandomAccessFile raf = new RandomAccessFile(getLockPasswordFilename(userId), "r"); - final byte[] stored = new byte[(int) raf.length()]; - int got = raf.read(stored, 0, stored.length); - raf.close(); - if (got <= 0) { - return true; - } - // Compare the hash from the file with the entered password's hash - final byte[] hash = mLockPatternUtils.passwordToHash(password, userId); - final boolean matched = Arrays.equals(stored, hash); - if (matched && !TextUtils.isEmpty(password)) { - maybeUpdateKeystore(password, userId); - } - return matched; - } catch (FileNotFoundException fnfe) { - Slog.e(TAG, "Cannot read file " + fnfe); - } catch (IOException ioe) { - Slog.e(TAG, "Cannot read file " + ioe); + byte[] hash = mLockPatternUtils.passwordToHash(password, userId); + byte[] storedHash = mStorage.readPasswordHash(userId); + + if (storedHash == null) { + return true; + } + + boolean matched = Arrays.equals(hash, storedHash); + if (matched && !TextUtils.isEmpty(password)) { + maybeUpdateKeystore(password, userId); } - return true; + return matched; } @Override - public boolean checkVoldPassword(int userId) throws RemoteException { + public boolean checkVoldPassword(int userId) throws RemoteException { if (!mFirstCallToVold) { return false; } @@ -512,166 +443,14 @@ public class LockSettingsService extends ILockSettings.Stub { public void removeUser(int userId) { checkWritePermission(userId); - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - try { - final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); - final UserInfo parentInfo = um.getProfileParent(userId); - if (parentInfo == null) { - // This user owns its lock settings files - safe to delete them - File file = new File(getLockPasswordFilename(userId)); - if (file.exists()) { - file.delete(); - } - file = new File(getLockPatternFilename(userId)); - if (file.exists()) { - file.delete(); - } - } - - db.beginTransaction(); - db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } + mStorage.removeUser(userId); + notifyObservers(null /* key */, userId); final KeyStore ks = KeyStore.getInstance(); final int userUid = UserHandle.getUid(userId, Process.SYSTEM_UID); ks.resetUid(userUid); } - private void writeFile(String name, byte[] hash) { - try { - // Write the hash to file - RandomAccessFile raf = new RandomAccessFile(name, "rw"); - // Truncate the file if pattern is null, to clear the lock - if (hash == null || hash.length == 0) { - raf.setLength(0); - } else { - raf.write(hash, 0, hash.length); - } - raf.close(); - } catch (IOException ioe) { - Slog.e(TAG, "Error writing to file " + ioe); - } - } - - private void writeToDb(String key, String value, int userId) { - writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId); - notifyObservers(key, userId); - } - - private void writeToDb(SQLiteDatabase db, String key, String value, int userId) { - ContentValues cv = new ContentValues(); - cv.put(COLUMN_KEY, key); - cv.put(COLUMN_USERID, userId); - cv.put(COLUMN_VALUE, value); - - db.beginTransaction(); - try { - db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?", - new String[] {key, Integer.toString(userId)}); - db.insert(TABLE, null, cv); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - private String readFromDb(String key, String defaultValue, int userId) { - Cursor cursor; - String result = defaultValue; - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY, - COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?", - new String[] { Integer.toString(userId), key }, - null, null, null)) != null) { - if (cursor.moveToFirst()) { - result = cursor.getString(0); - } - cursor.close(); - } - return result; - } - - class DatabaseHelper extends SQLiteOpenHelper { - private static final String TAG = "LockSettingsDB"; - private static final String DATABASE_NAME = "locksettings.db"; - - private static final int DATABASE_VERSION = 2; - - public DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - setWriteAheadLoggingEnabled(true); - } - - private void createTable(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TABLE + " (" + - "_id INTEGER PRIMARY KEY AUTOINCREMENT," + - COLUMN_KEY + " TEXT," + - COLUMN_USERID + " INTEGER," + - COLUMN_VALUE + " TEXT" + - ");"); - } - - @Override - public void onCreate(SQLiteDatabase db) { - createTable(db); - initializeDefaults(db); - } - - private void initializeDefaults(SQLiteDatabase db) { - // Get the lockscreen default from a system property, if available - boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default", - false); - if (lockScreenDisable) { - writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0); - } - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { - int upgradeVersion = oldVersion; - if (upgradeVersion == 1) { - // Set the initial value for {@link LockPatternUtils#LOCKSCREEN_WIDGETS_ENABLED} - // during upgrade based on whether each user previously had widgets in keyguard. - maybeEnableWidgetSettingForUsers(db); - upgradeVersion = 2; - } - - if (upgradeVersion != DATABASE_VERSION) { - Log.w(TAG, "Failed to upgrade database!"); - } - } - - private void maybeEnableWidgetSettingForUsers(SQLiteDatabase db) { - final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); - final ContentResolver cr = mContext.getContentResolver(); - final List<UserInfo> users = um.getUsers(); - for (int i = 0; i < users.size(); i++) { - final int userId = users.get(i).id; - final boolean enabled = mLockPatternUtils.hasWidgetsEnabledInKeyguard(userId); - Log.v(TAG, "Widget upgrade uid=" + userId + ", enabled=" - + enabled + ", w[]=" + mLockPatternUtils.getAppWidgets()); - loadSetting(db, LockPatternUtils.LOCKSCREEN_WIDGETS_ENABLED, userId, enabled); - } - } - - private void loadSetting(SQLiteDatabase db, String key, int userId, boolean value) { - SQLiteStatement stmt = null; - try { - stmt = db.compileStatement( - "INSERT OR REPLACE INTO locksettings(name,user,value) VALUES(?,?,?);"); - stmt.bindString(1, key); - stmt.bindLong(2, userId); - stmt.bindLong(3, value ? 1 : 0); - stmt.execute(); - } finally { - if (stmt != null) stmt.close(); - } - } - } - private static final String[] VALID_SETTINGS = new String[] { LockPatternUtils.LOCKOUT_PERMANENT_KEY, LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE, diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java new file mode 100644 index 000000000000..acbf8ef9c7cf --- /dev/null +++ b/services/core/java/com/android/server/LockSettingsStorage.java @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server; + +import android.content.ContentValues; +import android.content.Context; +import android.content.pm.UserInfo; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.os.Environment; +import android.os.UserManager; +import android.util.ArrayMap; +import android.util.Log; +import android.util.Slog; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; + +import static android.content.Context.USER_SERVICE; + +/** + * Storage for the lock settings service. + */ +class LockSettingsStorage { + + private static final String TAG = "LockSettingsStorage"; + private static final String TABLE = "locksettings"; + + private static final String COLUMN_KEY = "name"; + private static final String COLUMN_USERID = "user"; + private static final String COLUMN_VALUE = "value"; + + private static final String[] COLUMNS_FOR_QUERY = { + COLUMN_VALUE + }; + + private static final String SYSTEM_DIRECTORY = "/system/"; + private static final String LOCK_PATTERN_FILE = "gesture.key"; + private static final String LOCK_PASSWORD_FILE = "password.key"; + + private final DatabaseHelper mOpenHelper; + private final Context mContext; + private final Object mFileWriteLock = new Object(); + + LockSettingsStorage(Context context, Callback callback) { + mContext = context; + mOpenHelper = new DatabaseHelper(context, callback); + } + + void writeKeyValue(String key, String value, int userId) { + writeKeyValue(mOpenHelper.getWritableDatabase(), key, value, userId); + } + + void writeKeyValue(SQLiteDatabase db, String key, String value, int userId) { + ContentValues cv = new ContentValues(); + cv.put(COLUMN_KEY, key); + cv.put(COLUMN_USERID, userId); + cv.put(COLUMN_VALUE, value); + + db.beginTransaction(); + try { + db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?", + new String[] {key, Integer.toString(userId)}); + db.insert(TABLE, null, cv); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + } + + String readKeyValue(String key, String defaultValue, int userId) { + Cursor cursor; + String result = defaultValue; + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY, + COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?", + new String[] { Integer.toString(userId), key }, + null, null, null)) != null) { + if (cursor.moveToFirst()) { + result = cursor.getString(0); + } + cursor.close(); + } + return result; + } + + byte[] readPasswordHash(int userId) { + final byte[] stored = readFile(getLockPasswordFilename(userId), userId); + if (stored != null && stored.length > 0) { + return stored; + } + return null; + } + + byte[] readPatternHash(int userId) { + final byte[] stored = readFile(getLockPatternFilename(userId), userId); + if (stored != null && stored.length > 0) { + return stored; + } + return null; + } + + boolean hasPassword(int userId) { + return hasFile(getLockPasswordFilename(userId), userId); + } + + boolean hasPattern(int userId) { + return hasFile(getLockPatternFilename(userId), userId); + } + + private boolean hasFile(String name, int userId) { + byte[] contents = readFile(name, userId); + return contents != null && contents.length > 0; + } + + private byte[] readFile(String name, int userId) { + RandomAccessFile raf = null; + byte[] stored = null; + try { + raf = new RandomAccessFile(name, "r"); + stored = new byte[(int) raf.length()]; + raf.readFully(stored, 0, stored.length); + raf.close(); + } catch (IOException e) { + Slog.e(TAG, "Cannot read file " + e); + } finally { + if (raf != null) { + try { + raf.close(); + } catch (IOException e) { + Slog.e(TAG, "Error closing file " + e); + } + } + } + return stored; + } + + private void writeFile(String name, byte[] hash, int userId) { + synchronized (mFileWriteLock) { + RandomAccessFile raf = null; + try { + // Write the hash to file + raf = new RandomAccessFile(name, "rw"); + // Truncate the file if pattern is null, to clear the lock + if (hash == null || hash.length == 0) { + raf.setLength(0); + } else { + raf.write(hash, 0, hash.length); + } + raf.close(); + } catch (IOException e) { + Slog.e(TAG, "Error writing to file " + e); + } finally { + if (raf != null) { + try { + raf.close(); + } catch (IOException e) { + Slog.e(TAG, "Error closing file " + e); + } + } + } + } + } + + public void writePatternHash(byte[] hash, int userId) { + writeFile(getLockPatternFilename(userId), hash, userId); + } + + public void writePasswordHash(byte[] hash, int userId) { + writeFile(getLockPasswordFilename(userId), hash, userId); + } + + + private String getLockPatternFilename(int userId) { + String dataSystemDirectory = + android.os.Environment.getDataDirectory().getAbsolutePath() + + SYSTEM_DIRECTORY; + userId = getUserParentOrSelfId(userId); + if (userId == 0) { + // Leave it in the same place for user 0 + return dataSystemDirectory + LOCK_PATTERN_FILE; + } else { + return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE) + .getAbsolutePath(); + } + } + + private String getLockPasswordFilename(int userId) { + userId = getUserParentOrSelfId(userId); + String dataSystemDirectory = + android.os.Environment.getDataDirectory().getAbsolutePath() + + SYSTEM_DIRECTORY; + if (userId == 0) { + // Leave it in the same place for user 0 + return dataSystemDirectory + LOCK_PASSWORD_FILE; + } else { + return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE) + .getAbsolutePath(); + } + } + + private int getUserParentOrSelfId(int userId) { + if (userId != 0) { + final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); + final UserInfo pi = um.getProfileParent(userId); + if (pi != null) { + return pi.id; + } + } + return userId; + } + + + public void removeUser(int userId) { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + + final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); + final UserInfo parentInfo = um.getProfileParent(userId); + + synchronized (mFileWriteLock) { + if (parentInfo == null) { + // This user owns its lock settings files - safe to delete them + File file = new File(getLockPasswordFilename(userId)); + if (file.exists()) { + file.delete(); + } + file = new File(getLockPatternFilename(userId)); + if (file.exists()) { + file.delete(); + } + } + } + + try { + db.beginTransaction(); + db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + + interface Callback { + void initialize(SQLiteDatabase db); + } + + class DatabaseHelper extends SQLiteOpenHelper { + private static final String TAG = "LockSettingsDB"; + private static final String DATABASE_NAME = "locksettings.db"; + + private static final int DATABASE_VERSION = 2; + + private final Callback mCallback; + + public DatabaseHelper(Context context, Callback callback) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + setWriteAheadLoggingEnabled(true); + mCallback = callback; + } + + private void createTable(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + TABLE + " (" + + "_id INTEGER PRIMARY KEY AUTOINCREMENT," + + COLUMN_KEY + " TEXT," + + COLUMN_USERID + " INTEGER," + + COLUMN_VALUE + " TEXT" + + ");"); + } + + @Override + public void onCreate(SQLiteDatabase db) { + createTable(db); + mCallback.initialize(db); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { + int upgradeVersion = oldVersion; + if (upgradeVersion == 1) { + // Previously migrated lock screen widget settings. Now defunct. + upgradeVersion = 2; + } + + if (upgradeVersion != DATABASE_VERSION) { + Log.w(TAG, "Failed to upgrade database!"); + } + } + } +} |