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 1752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasanipackage com.android.internal.widget; 1852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 1952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.ContentResolver; 2052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.ContentValues; 2152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.Context; 2252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.Cursor; 2352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.sqlite.SQLiteDatabase; 2452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.sqlite.SQLiteOpenHelper; 2552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.Binder; 2661f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasaniimport android.os.Environment; 2752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.RemoteException; 28d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasaniimport android.os.SystemProperties; 29f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 3052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings; 3152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings.Secure; 3252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.text.TextUtils; 3352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.util.Slog; 3452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 3552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.File; 3652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.FileNotFoundException; 3752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.IOException; 3852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.RandomAccessFile; 3952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.util.Arrays; 4052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 4152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/** 4252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Keeps the lock pattern/password data and related settings for each user. 4352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Used by LockPatternUtils. Needs to be a service because Settings app also needs 4452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * to be able to save lockscreen information for secondary users. 4552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * @hide 4652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */ 4752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasanipublic class LockSettingsService extends ILockSettings.Stub { 4852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 4952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private final DatabaseHelper mOpenHelper; 5052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String TAG = "LockSettingsService"; 5152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 5252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String TABLE = "locksettings"; 5352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String COLUMN_KEY = "name"; 5452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String COLUMN_USERID = "user"; 5552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String COLUMN_VALUE = "value"; 5652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 5752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String[] COLUMNS_FOR_QUERY = { 5852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_VALUE 5952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani }; 6052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 6152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String SYSTEM_DIRECTORY = "/system/"; 6252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String LOCK_PATTERN_FILE = "gesture.key"; 6352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String LOCK_PASSWORD_FILE = "password.key"; 6452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 6552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private final Context mContext; 6652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 6752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public LockSettingsService(Context context) { 6852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani mContext = context; 6952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Open the database 7052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani mOpenHelper = new DatabaseHelper(mContext); 7152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 7252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 7352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void systemReady() { 7452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani migrateOldData(); 7552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 7652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 7752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void migrateOldData() { 7852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 7952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (getString("migrated", null, 0) != null) { 8052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Already migrated 8152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return; 8252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 8352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 8452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final ContentResolver cr = mContext.getContentResolver(); 8552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani for (String validSetting : VALID_SETTINGS) { 8652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String value = Settings.Secure.getString(cr, validSetting); 8752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (value != null) { 8852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani setString(validSetting, value, 0); 8952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 9052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 9152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // No need to move the password / pattern files. They're already in the right place. 9252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani setString("migrated", "true", 0); 9352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.i(TAG, "Migrated lock settings to new location"); 9452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (RemoteException re) { 9552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Unable to migrate old data"); 9652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 9752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 9852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 9952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final void checkWritePermission(int userId) { 10052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final int callingUid = Binder.getCallingUid(); 101f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn if (UserHandle.getAppId(callingUid) != android.os.Process.SYSTEM_UID) { 10252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani throw new SecurityException("uid=" + callingUid 10352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani + " not authorized to write lock settings"); 10452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 10552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 10652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 10752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final void checkPasswordReadPermission(int userId) { 10852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final int callingUid = Binder.getCallingUid(); 109f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn if (UserHandle.getAppId(callingUid) != android.os.Process.SYSTEM_UID) { 11052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani throw new SecurityException("uid=" + callingUid 11152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani + " not authorized to read lock password"); 11252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 11352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 11452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 11552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final void checkReadPermission(int userId) { 11652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final int callingUid = Binder.getCallingUid(); 117f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn if (UserHandle.getAppId(callingUid) != android.os.Process.SYSTEM_UID 118f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn && UserHandle.getUserId(callingUid) != userId) { 11952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani throw new SecurityException("uid=" + callingUid 12052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani + " not authorized to read settings of user " + userId); 12152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 12252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 12352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 12452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 12552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setBoolean(String key, boolean value, int userId) throws RemoteException { 12652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 12752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 12852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeToDb(key, value ? "1" : "0", userId); 12952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 13052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 13152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 13252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setLong(String key, long value, int userId) throws RemoteException { 13352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 13452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 13552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeToDb(key, Long.toString(value), userId); 13652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 13752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 13852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 13952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setString(String key, String value, int userId) throws RemoteException { 14052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 14152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 14252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeToDb(key, value, userId); 14352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 14452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 14552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 14652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException { 14752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani //checkReadPermission(userId); 14852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 14952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String value = readFromDb(key, null, userId); 15052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return TextUtils.isEmpty(value) ? 15152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani defaultValue : (value.equals("1") || value.equals("true")); 15252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 15352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 15452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 15552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public long getLong(String key, long defaultValue, int userId) throws RemoteException { 15652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani //checkReadPermission(userId); 15752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 15852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String value = readFromDb(key, null, userId); 15952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value); 16052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 16152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 16252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 16352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public String getString(String key, String defaultValue, int userId) throws RemoteException { 16452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani //checkReadPermission(userId); 16552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 16652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return readFromDb(key, defaultValue, userId); 16752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 16852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 16952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private String getLockPatternFilename(int userId) { 17052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String dataSystemDirectory = 17152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani android.os.Environment.getDataDirectory().getAbsolutePath() + 17252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SYSTEM_DIRECTORY; 17352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (userId == 0) { 17452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Leave it in the same place for user 0 17552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return dataSystemDirectory + LOCK_PATTERN_FILE; 17652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } else { 17761f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE) 17861f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani .getAbsolutePath(); 17952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 18052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 18152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 18252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private String getLockPasswordFilename(int userId) { 18352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String dataSystemDirectory = 18452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani android.os.Environment.getDataDirectory().getAbsolutePath() + 18552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SYSTEM_DIRECTORY; 18652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (userId == 0) { 18752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Leave it in the same place for user 0 18852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return dataSystemDirectory + LOCK_PASSWORD_FILE; 18952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } else { 19061f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE) 19161f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani .getAbsolutePath(); 19252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 19352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 19452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 19552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 19652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean havePassword(int userId) throws RemoteException { 19752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Do we need a permissions check here? 19852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 19952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return new File(getLockPasswordFilename(userId)).length() > 0; 20052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 20152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 20252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 20352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean havePattern(int userId) throws RemoteException { 20452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Do we need a permissions check here? 20552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 20652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return new File(getLockPatternFilename(userId)).length() > 0; 20752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 20852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 20952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 21052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setLockPattern(byte[] hash, int userId) throws RemoteException { 21152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 21252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 21352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeFile(getLockPatternFilename(userId), hash); 21452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 21552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 21652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 21752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean checkPattern(byte[] hash, int userId) throws RemoteException { 21852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkPasswordReadPermission(userId); 21952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 22052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Read all the bytes from the file 22152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani RandomAccessFile raf = new RandomAccessFile(getLockPatternFilename(userId), "r"); 22252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final byte[] stored = new byte[(int) raf.length()]; 22352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani int got = raf.read(stored, 0, stored.length); 22452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.close(); 22552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (got <= 0) { 22652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return true; 22752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 22852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Compare the hash from the file with the entered pattern's hash 22952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return Arrays.equals(stored, hash); 23052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (FileNotFoundException fnfe) { 23152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Cannot read file " + fnfe); 23252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return true; 23352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (IOException ioe) { 23452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Cannot read file " + ioe); 23552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return true; 23652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 23752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 23852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 23952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 24052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setLockPassword(byte[] hash, int userId) throws RemoteException { 24152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 24252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 24352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani writeFile(getLockPasswordFilename(userId), hash); 24452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 24552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 24652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 24752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean checkPassword(byte[] hash, int userId) throws RemoteException { 24852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkPasswordReadPermission(userId); 24952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 25052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 25152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Read all the bytes from the file 25252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani RandomAccessFile raf = new RandomAccessFile(getLockPasswordFilename(userId), "r"); 25352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final byte[] stored = new byte[(int) raf.length()]; 25452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani int got = raf.read(stored, 0, stored.length); 25552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.close(); 25652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (got <= 0) { 25752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return true; 25852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 25952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Compare the hash from the file with the entered password's hash 26052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return Arrays.equals(stored, hash); 26152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (FileNotFoundException fnfe) { 26252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Cannot read file " + fnfe); 26352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return true; 26452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (IOException ioe) { 26552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Cannot read file " + ioe); 26652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return true; 26752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 26852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 26952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 27052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 27152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void removeUser(int userId) { 27252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 27352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 27452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 27552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 27652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani File file = new File(getLockPasswordFilename(userId)); 27752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (file.exists()) { 27852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani file.delete(); 27952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 28052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani file = new File(getLockPatternFilename(userId)); 28152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (file.exists()) { 28252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani file.delete(); 28352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 28452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 28552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.beginTransaction(); 28652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null); 28752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.setTransactionSuccessful(); 28852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } finally { 28952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.endTransaction(); 29052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 29152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 29252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 29352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void writeFile(String name, byte[] hash) { 29452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 29552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Write the hash to file 29652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani RandomAccessFile raf = new RandomAccessFile(name, "rw"); 29752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Truncate the file if pattern is null, to clear the lock 29852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (hash == null || hash.length == 0) { 29952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.setLength(0); 30052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } else { 30152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.write(hash, 0, hash.length); 30252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 30352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani raf.close(); 30452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (IOException ioe) { 30552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Slog.e(TAG, "Error writing to file " + ioe); 30652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 30752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 30852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 30952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void writeToDb(String key, String value, int userId) { 310d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId); 311d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani } 312d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani 313d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani private void writeToDb(SQLiteDatabase db, String key, String value, int userId) { 31452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani ContentValues cv = new ContentValues(); 31552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani cv.put(COLUMN_KEY, key); 31652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani cv.put(COLUMN_USERID, userId); 31752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani cv.put(COLUMN_VALUE, value); 31852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 31952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.beginTransaction(); 32052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 32152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?", 32252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani new String[] {key, Integer.toString(userId)}); 32352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.insert(TABLE, null, cv); 32452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.setTransactionSuccessful(); 32552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } finally { 32652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.endTransaction(); 32752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 32852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 32952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 33052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private String readFromDb(String key, String defaultValue, int userId) { 33152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Cursor cursor; 33252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani String result = defaultValue; 33352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 33452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY, 33552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?", 33652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani new String[] { Integer.toString(userId), key }, 33752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani null, null, null)) != null) { 33852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani if (cursor.moveToFirst()) { 33952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani result = cursor.getString(0); 34052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 34152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani cursor.close(); 34252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 34352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return result; 34452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 34552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 34652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani class DatabaseHelper extends SQLiteOpenHelper { 34752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String TAG = "LockSettingsDB"; 34852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String DATABASE_NAME = "locksettings.db"; 34952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 35052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final int DATABASE_VERSION = 1; 35152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 35252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public DatabaseHelper(Context context) { 35352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani super(context, DATABASE_NAME, null, DATABASE_VERSION); 35452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani setWriteAheadLoggingEnabled(true); 35552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 35652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 35752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void createTable(SQLiteDatabase db) { 35852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani db.execSQL("CREATE TABLE " + TABLE + " (" + 35952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani "_id INTEGER PRIMARY KEY AUTOINCREMENT," + 36052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_KEY + " TEXT," + 36152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_USERID + " INTEGER," + 36252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani COLUMN_VALUE + " TEXT" + 36352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani ");"); 36452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 36552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 36652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 36752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void onCreate(SQLiteDatabase db) { 36852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani createTable(db); 369d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani initializeDefaults(db); 370d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani } 371d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani 372d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani private void initializeDefaults(SQLiteDatabase db) { 373d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani // Get the lockscreen default from a system property, if available 374d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default", 375d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani false); 376d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani if (lockScreenDisable) { 377d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0); 378d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani } 37952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 38052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 38152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 38252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { 38352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Nothing yet 38452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 38552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 38652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 38752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String[] VALID_SETTINGS = new String[] { 38852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKOUT_PERMANENT_KEY, 38952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE, 39052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, 39152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_TYPE_KEY, 39252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 39352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCK_PASSWORD_SALT_KEY, 39452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.DISABLE_LOCKSCREEN_KEY, 39552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_OPTIONS, 39652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, 39752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY, 39852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, 39952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_HISTORY_KEY, 40052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_ENABLED, 40152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 40252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_VISIBLE, 40352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED 40452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani }; 40552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani} 406