LockSettingsService.java revision de1af08dd3a073f007ae4b8a114352cae3775028
152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/* 252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Copyright (C) 2012 The Android Open Source Project 352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License"); 552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * you may not use this file except in compliance with the License. 652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * You may obtain a copy of the License at 752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * http://www.apache.org/licenses/LICENSE-2.0 952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 1052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Unless required by applicable law or agreed to in writing, software 1152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS, 1252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * See the License for the specific language governing permissions and 1452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * limitations under the License. 1552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */ 1652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server; 1852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 19f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Millerimport android.app.ActivityManagerNative; 2052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.ContentResolver; 2152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.ContentValues; 2252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.Context; 23158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Millerimport android.content.pm.PackageManager; 24187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.content.pm.UserInfo; 25187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 26187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport static android.content.Context.USER_SERVICE; 27158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Millerimport static android.Manifest.permission.READ_PROFILE; 2852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.Cursor; 2952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.sqlite.SQLiteDatabase; 3052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.sqlite.SQLiteOpenHelper; 31f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Millerimport android.database.sqlite.SQLiteStatement; 32f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Millerimport android.media.AudioManager; 33f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Millerimport android.media.AudioService; 3452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.Binder; 3561f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasaniimport android.os.Environment; 3652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.RemoteException; 37d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasaniimport android.os.SystemProperties; 38f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 39187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.os.UserManager; 4052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings; 4152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings.Secure; 42187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.provider.Settings.SettingNotFoundException; 43de1af08dd3a073f007ae4b8a114352cae3775028Jim Millerimport android.security.KeyStore; 4452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.text.TextUtils; 45f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Millerimport android.util.Log; 4652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.util.Slog; 4752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 487a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.widget.ILockSettings; 497a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.widget.LockPatternUtils; 507a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey 5152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.File; 5252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.FileNotFoundException; 5352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.IOException; 5452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.RandomAccessFile; 5552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.util.Arrays; 56187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport java.util.List; 5752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 5852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/** 5952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Keeps the lock pattern/password data and related settings for each user. 6052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Used by LockPatternUtils. Needs to be a service because Settings app also needs 6152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * to be able to save lockscreen information for secondary users. 6252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * @hide 6352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */ 6452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasanipublic class LockSettingsService extends ILockSettings.Stub { 6552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 665ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller private static final String PERMISSION = "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"; 6752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private final DatabaseHelper mOpenHelper; 6852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String TAG = "LockSettingsService"; 6952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 7052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String TABLE = "locksettings"; 7152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String COLUMN_KEY = "name"; 7252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String COLUMN_USERID = "user"; 7352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String COLUMN_VALUE = "value"; 7452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 7552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String[] COLUMNS_FOR_QUERY = { 7652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_VALUE 7752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani }; 7852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 7952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String SYSTEM_DIRECTORY = "/system/"; 8052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String LOCK_PATTERN_FILE = "gesture.key"; 8152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String LOCK_PASSWORD_FILE = "password.key"; 8252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 8352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private final Context mContext; 84de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller private LockPatternUtils mLockPatternUtils; 8552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 8652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public LockSettingsService(Context context) { 8752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani mContext = context; 8852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Open the database 8952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani mOpenHelper = new DatabaseHelper(mContext); 90de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 91de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller mLockPatternUtils = new LockPatternUtils(context); 9252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 9352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 9452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void systemReady() { 9552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani migrateOldData(); 9652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 9752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 9852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void migrateOldData() { 9952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 100187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // These Settings moved before multi-user was enabled, so we only have to do it for the 101187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // root user. 102187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller if (getString("migrated", null, 0) == null) { 103187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller final ContentResolver cr = mContext.getContentResolver(); 104187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller for (String validSetting : VALID_SETTINGS) { 105187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller String value = Settings.Secure.getString(cr, validSetting); 106187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller if (value != null) { 107187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller setString(validSetting, value, 0); 108187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller } 109187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller } 110187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // No need to move the password / pattern files. They're already in the right place. 111187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller setString("migrated", "true", 0); 112187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Slog.i(TAG, "Migrated lock settings to new location"); 11352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 11452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 115187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // These Settings changed after multi-user was enabled, hence need to be moved per user. 116187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller if (getString("migrated_user_specific", null, 0) == null) { 117187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); 118187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller final ContentResolver cr = mContext.getContentResolver(); 119187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller List<UserInfo> users = um.getUsers(); 120187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller for (int user = 0; user < users.size(); user++) { 1212d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // Migrate owner info 1222d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller final int userId = users.get(user).id; 1232d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO; 1242d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId); 1252d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller if (ownerInfo != null) { 1262d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller setString(OWNER_INFO, ownerInfo, userId); 1272d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller Settings.Secure.putStringForUser(cr, ownerInfo, "", userId); 1282d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller } 129187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 1302d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // Migrate owner info enabled. Note there was a bug where older platforms only 1312d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // stored this value if the checkbox was toggled at least once. The code detects 1322d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // this case by handling the exception. 1332d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED; 1342d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller boolean enabled; 1352d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller try { 1362d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId); 1372d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller enabled = ivalue != 0; 1382d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId); 1392d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller } catch (SettingNotFoundException e) { 1402d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // Setting was never stored. Store it if the string is not empty. 1412d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller if (!TextUtils.isEmpty(ownerInfo)) { 1422d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller setLong(OWNER_INFO_ENABLED, 1, userId); 143187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller } 144187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller } 1452d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId); 14652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 147187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // No need to move the password / pattern files. They're already in the right place. 148187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller setString("migrated_user_specific", "true", 0); 149187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Slog.i(TAG, "Migrated per-user lock settings to new location"); 15052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 15152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (RemoteException re) { 152187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Slog.e(TAG, "Unable to migrate old data", re); 15352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 15452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 15552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 1565ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller private final void checkWritePermission(int userId) { 1575ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller mContext.checkCallingOrSelfPermission(PERMISSION); 15852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 15952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 1605ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller private final void checkPasswordReadPermission(int userId) { 1615ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller mContext.checkCallingOrSelfPermission(PERMISSION); 16252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 16352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 164158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller private final void checkReadPermission(String requestedKey, int userId) { 16552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final int callingUid = Binder.getCallingUid(); 166158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller for (int i = 0; i < READ_PROFILE_PROTECTED_SETTINGS.length; i++) { 167158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller String key = READ_PROFILE_PROTECTED_SETTINGS[i]; 168158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_PROFILE) 169158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller != PackageManager.PERMISSION_GRANTED) { 170158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller throw new SecurityException("uid=" + callingUid 171158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller + " needs permission " + READ_PROFILE + " to read " 172158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller + requestedKey + " for user " + userId); 173158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller } 17452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 17552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 17652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 17752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 17852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setBoolean(String key, boolean value, int userId) throws RemoteException { 17952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 18052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 18152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeToDb(key, value ? "1" : "0", userId); 18252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 18352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 18452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 18552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setLong(String key, long value, int userId) throws RemoteException { 18652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 18752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 18852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeToDb(key, Long.toString(value), userId); 18952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 19052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 19152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 19252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setString(String key, String value, int userId) throws RemoteException { 19352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 19452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 19552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeToDb(key, value, userId); 19652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 19752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 19852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 19952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException { 200158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller checkReadPermission(key, userId); 20152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 20252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String value = readFromDb(key, null, userId); 20352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return TextUtils.isEmpty(value) ? 20452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani defaultValue : (value.equals("1") || value.equals("true")); 20552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 20652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 20752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 20852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public long getLong(String key, long defaultValue, int userId) throws RemoteException { 209158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller checkReadPermission(key, userId); 21052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 21152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String value = readFromDb(key, null, userId); 21252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value); 21352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 21452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 21552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 21652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public String getString(String key, String defaultValue, int userId) throws RemoteException { 217158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller checkReadPermission(key, userId); 21852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 21952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return readFromDb(key, defaultValue, userId); 22052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 22152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 22252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private String getLockPatternFilename(int userId) { 22352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String dataSystemDirectory = 22452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani android.os.Environment.getDataDirectory().getAbsolutePath() + 22552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SYSTEM_DIRECTORY; 22652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (userId == 0) { 22752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Leave it in the same place for user 0 22852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return dataSystemDirectory + LOCK_PATTERN_FILE; 22952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } else { 23061f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE) 23161f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani .getAbsolutePath(); 23252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 23352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 23452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 23552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private String getLockPasswordFilename(int userId) { 23652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String dataSystemDirectory = 23752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani android.os.Environment.getDataDirectory().getAbsolutePath() + 23852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SYSTEM_DIRECTORY; 23952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (userId == 0) { 24052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Leave it in the same place for user 0 24152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return dataSystemDirectory + LOCK_PASSWORD_FILE; 24252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } else { 24361f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE) 24461f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani .getAbsolutePath(); 24552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 24652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 24752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 24852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 24952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean havePassword(int userId) throws RemoteException { 25052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Do we need a permissions check here? 25152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 25252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return new File(getLockPasswordFilename(userId)).length() > 0; 25352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 25452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 25552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 25652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean havePattern(int userId) throws RemoteException { 25752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Do we need a permissions check here? 25852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 25952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return new File(getLockPatternFilename(userId)).length() > 0; 26052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 26152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 262de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller private void maybeUpdateKeystore(String password, int userId) { 263de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller if (userId == UserHandle.USER_OWNER) { 264de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller final KeyStore keyStore = KeyStore.getInstance(); 265de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller // Conditionally reset the keystore if empty. If non-empty, we are just 266de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller // switching key guard type 267de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller if (TextUtils.isEmpty(password) && keyStore.isEmpty()) { 268de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller keyStore.reset(); 269de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } else { 270de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller // Update the keystore password 271de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller keyStore.password(password); 272de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 273de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 274de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 275de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 27652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 277de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller public void setLockPattern(String pattern, int userId) throws RemoteException { 27852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 27952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 280de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller maybeUpdateKeystore(pattern, userId); 281de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 282de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller final byte[] hash = LockPatternUtils.patternToHash( 283de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller LockPatternUtils.stringToPattern(pattern)); 28452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeFile(getLockPatternFilename(userId), hash); 28552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 28652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 28752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 288de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller public void setLockPassword(String password, int userId) throws RemoteException { 289de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller checkWritePermission(userId); 290de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 291de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller maybeUpdateKeystore(password, userId); 292de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 293de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller writeFile(getLockPasswordFilename(userId), mLockPatternUtils.passwordToHash(password)); 294de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 295de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 296de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller @Override 297de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller public boolean checkPattern(String pattern, int userId) throws RemoteException { 29852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkPasswordReadPermission(userId); 29952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 30052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Read all the bytes from the file 30152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani RandomAccessFile raf = new RandomAccessFile(getLockPatternFilename(userId), "r"); 30252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final byte[] stored = new byte[(int) raf.length()]; 30352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani int got = raf.read(stored, 0, stored.length); 30452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.close(); 30552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (got <= 0) { 30652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return true; 30752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 30852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Compare the hash from the file with the entered pattern's hash 309de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller final byte[] hash = LockPatternUtils.patternToHash( 310de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller LockPatternUtils.stringToPattern(pattern)); 311de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller final boolean matched = Arrays.equals(stored, hash); 312de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller if (matched && !TextUtils.isEmpty(pattern)) { 313de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller maybeUpdateKeystore(pattern, userId); 314de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 315de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller return matched; 31652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (FileNotFoundException fnfe) { 31752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Cannot read file " + fnfe); 31852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (IOException ioe) { 31952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Cannot read file " + ioe); 32052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 321de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller return true; 32252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 32352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 32452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 325de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller public boolean checkPassword(String password, int userId) throws RemoteException { 32652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkPasswordReadPermission(userId); 32752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 32852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 32952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Read all the bytes from the file 33052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani RandomAccessFile raf = new RandomAccessFile(getLockPasswordFilename(userId), "r"); 33152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final byte[] stored = new byte[(int) raf.length()]; 33252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani int got = raf.read(stored, 0, stored.length); 33352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.close(); 33452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (got <= 0) { 33552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return true; 33652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 33752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Compare the hash from the file with the entered password's hash 338de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller final byte[] hash = mLockPatternUtils.passwordToHash(password); 339de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller final boolean matched = Arrays.equals(stored, hash); 340de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller if (matched && !TextUtils.isEmpty(password)) { 341de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller maybeUpdateKeystore(password, userId); 342de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 343de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller return matched; 34452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (FileNotFoundException fnfe) { 34552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Cannot read file " + fnfe); 34652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (IOException ioe) { 34752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Cannot read file " + ioe); 34852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 349de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller return true; 35052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 35152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 35252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 35352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void removeUser(int userId) { 35452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 35552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 35652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 35752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 35852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani File file = new File(getLockPasswordFilename(userId)); 35952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (file.exists()) { 36052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani file.delete(); 36152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 36252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani file = new File(getLockPatternFilename(userId)); 36352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (file.exists()) { 36452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani file.delete(); 36552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 36652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 36752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.beginTransaction(); 36852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null); 36952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.setTransactionSuccessful(); 37052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } finally { 37152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.endTransaction(); 37252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 37352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 37452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 37552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void writeFile(String name, byte[] hash) { 37652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 37752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Write the hash to file 37852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani RandomAccessFile raf = new RandomAccessFile(name, "rw"); 37952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Truncate the file if pattern is null, to clear the lock 38052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (hash == null || hash.length == 0) { 38152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.setLength(0); 38252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } else { 38352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.write(hash, 0, hash.length); 38452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 38552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.close(); 38652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (IOException ioe) { 38752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Error writing to file " + ioe); 38852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 38952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 39052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 39152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void writeToDb(String key, String value, int userId) { 392d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId); 393d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani } 394d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani 395d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani private void writeToDb(SQLiteDatabase db, String key, String value, int userId) { 39652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani ContentValues cv = new ContentValues(); 39752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani cv.put(COLUMN_KEY, key); 39852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani cv.put(COLUMN_USERID, userId); 39952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani cv.put(COLUMN_VALUE, value); 40052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 40152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.beginTransaction(); 40252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 40352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?", 40452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani new String[] {key, Integer.toString(userId)}); 40552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.insert(TABLE, null, cv); 40652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.setTransactionSuccessful(); 40752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } finally { 40852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.endTransaction(); 40952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 41052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 41152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 41252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private String readFromDb(String key, String defaultValue, int userId) { 41352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Cursor cursor; 41452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String result = defaultValue; 41552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 41652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY, 41752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?", 41852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani new String[] { Integer.toString(userId), key }, 41952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani null, null, null)) != null) { 42052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (cursor.moveToFirst()) { 42152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani result = cursor.getString(0); 42252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 42352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani cursor.close(); 42452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 42552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return result; 42652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 42752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 42852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani class DatabaseHelper extends SQLiteOpenHelper { 42952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String TAG = "LockSettingsDB"; 43052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String DATABASE_NAME = "locksettings.db"; 43152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 432f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller private static final int DATABASE_VERSION = 2; 43352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 43452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public DatabaseHelper(Context context) { 43552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani super(context, DATABASE_NAME, null, DATABASE_VERSION); 43652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani setWriteAheadLoggingEnabled(true); 43752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 43852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 43952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void createTable(SQLiteDatabase db) { 44052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.execSQL("CREATE TABLE " + TABLE + " (" + 44152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani "_id INTEGER PRIMARY KEY AUTOINCREMENT," + 44252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_KEY + " TEXT," + 44352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_USERID + " INTEGER," + 44452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_VALUE + " TEXT" + 44552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani ");"); 44652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 44752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 44852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 44952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void onCreate(SQLiteDatabase db) { 45052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani createTable(db); 451d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani initializeDefaults(db); 452d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani } 453d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani 454d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani private void initializeDefaults(SQLiteDatabase db) { 455d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani // Get the lockscreen default from a system property, if available 456d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default", 457d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani false); 458d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani if (lockScreenDisable) { 459d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0); 460d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani } 46152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 46252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 46352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 46452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { 465f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller int upgradeVersion = oldVersion; 466f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller if (upgradeVersion == 1) { 467f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller // Set the initial value for {@link LockPatternUtils#LOCKSCREEN_WIDGETS_ENABLED} 468f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller // during upgrade based on whether each user previously had widgets in keyguard. 469f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller maybeEnableWidgetSettingForUsers(db); 470f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller upgradeVersion = 2; 471f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller } 472f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller 473f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller if (upgradeVersion != DATABASE_VERSION) { 474f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller Log.w(TAG, "Failed to upgrade database!"); 475f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller } 476f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller } 477f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller 478f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller private void maybeEnableWidgetSettingForUsers(SQLiteDatabase db) { 479f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); 480f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller final ContentResolver cr = mContext.getContentResolver(); 481f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller final List<UserInfo> users = um.getUsers(); 482f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller for (int i = 0; i < users.size(); i++) { 483f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller final int userId = users.get(i).id; 484de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller final boolean enabled = mLockPatternUtils.hasWidgetsEnabledInKeyguard(userId); 485f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller Log.v(TAG, "Widget upgrade uid=" + userId + ", enabled=" 486de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller + enabled + ", w[]=" + mLockPatternUtils.getAppWidgets()); 487f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller loadSetting(db, LockPatternUtils.LOCKSCREEN_WIDGETS_ENABLED, userId, enabled); 488f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller } 489f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller } 490f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller 491f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller private void loadSetting(SQLiteDatabase db, String key, int userId, boolean value) { 492f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller SQLiteStatement stmt = null; 493f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller try { 494f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller stmt = db.compileStatement( 495f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller "INSERT OR REPLACE INTO locksettings(name,user,value) VALUES(?,?,?);"); 496f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller stmt.bindString(1, key); 497f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller stmt.bindLong(2, userId); 498f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller stmt.bindLong(3, value ? 1 : 0); 499f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller stmt.execute(); 500f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller } finally { 501f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller if (stmt != null) stmt.close(); 502f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller } 50352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 50452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 50552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 50652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String[] VALID_SETTINGS = new String[] { 50752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKOUT_PERMANENT_KEY, 50852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE, 50952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, 51052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_TYPE_KEY, 51152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 51252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCK_PASSWORD_SALT_KEY, 51352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.DISABLE_LOCKSCREEN_KEY, 51452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_OPTIONS, 51552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, 51652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY, 51752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, 51852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_HISTORY_KEY, 51952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_ENABLED, 52052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 52152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_VISIBLE, 52252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED 523187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller }; 524187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 5252d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // These are protected with a read permission 5262d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller private static final String[] READ_PROFILE_PROTECTED_SETTINGS = new String[] { 527187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 528187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Secure.LOCK_SCREEN_OWNER_INFO 529187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller }; 53052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani} 531