LockSettingsService.java revision 945490c12e32b1c13b9097c00702558260b2011f
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
1952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.ContentResolver;
2052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.ContentValues;
2152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.Context;
22158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Millerimport android.content.pm.PackageManager;
23187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.content.pm.UserInfo;
24187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller
25187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport static android.content.Context.USER_SERVICE;
26158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Millerimport static android.Manifest.permission.READ_PROFILE;
2752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.Cursor;
2852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.sqlite.SQLiteDatabase;
2952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.sqlite.SQLiteOpenHelper;
30f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Millerimport android.database.sqlite.SQLiteStatement;
3152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.Binder;
3261f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasaniimport android.os.Environment;
33945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.IBinder;
3452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.RemoteException;
35945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.storage.IMountService;
36945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.ServiceManager;
37945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.storage.StorageManager;
38d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasaniimport android.os.SystemProperties;
39f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
40187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.os.UserManager;
4152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings;
4252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings.Secure;
43187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.provider.Settings.SettingNotFoundException;
44de1af08dd3a073f007ae4b8a114352cae3775028Jim Millerimport android.security.KeyStore;
4552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.text.TextUtils;
46f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Millerimport android.util.Log;
4752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.util.Slog;
4852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
497a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.widget.ILockSettings;
507a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.widget.LockPatternUtils;
517a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey
5252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.File;
5352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.FileNotFoundException;
5452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.IOException;
5552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.io.RandomAccessFile;
5652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.util.Arrays;
57187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport java.util.List;
5852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
5952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/**
6052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Keeps the lock pattern/password data and related settings for each user.
6152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Used by LockPatternUtils. Needs to be a service because Settings app also needs
6252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * to be able to save lockscreen information for secondary users.
6352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * @hide
6452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */
6552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasanipublic class LockSettingsService extends ILockSettings.Stub {
6652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
675ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller    private static final String PERMISSION = "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE";
6852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private final DatabaseHelper mOpenHelper;
6952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String TAG = "LockSettingsService";
7052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
7152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String TABLE = "locksettings";
7252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String COLUMN_KEY = "name";
7352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String COLUMN_USERID = "user";
7452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String COLUMN_VALUE = "value";
7552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
7652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String[] COLUMNS_FOR_QUERY = {
7752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        COLUMN_VALUE
7852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    };
7952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
8052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String SYSTEM_DIRECTORY = "/system/";
8152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String LOCK_PATTERN_FILE = "gesture.key";
8252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String LOCK_PASSWORD_FILE = "password.key";
8352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
8452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private final Context mContext;
85de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    private LockPatternUtils mLockPatternUtils;
86945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence    private boolean mFirstCallToVold;
8752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
8852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public LockSettingsService(Context context) {
8952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        mContext = context;
9052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        // Open the database
9152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        mOpenHelper = new DatabaseHelper(mContext);
92de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
93de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        mLockPatternUtils = new LockPatternUtils(context);
94945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        mFirstCallToVold = true;
9552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
9652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
9752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public void systemReady() {
9852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        migrateOldData();
9952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
10052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
10152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private void migrateOldData() {
10252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        try {
103187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller            // These Settings moved before multi-user was enabled, so we only have to do it for the
104187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller            // root user.
105187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller            if (getString("migrated", null, 0) == null) {
106187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                final ContentResolver cr = mContext.getContentResolver();
107187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                for (String validSetting : VALID_SETTINGS) {
108187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                    String value = Settings.Secure.getString(cr, validSetting);
109187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                    if (value != null) {
110187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                        setString(validSetting, value, 0);
111187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                    }
112187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                }
113187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                // No need to move the password / pattern files. They're already in the right place.
114187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                setString("migrated", "true", 0);
115187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                Slog.i(TAG, "Migrated lock settings to new location");
11652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
11752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
118187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller            // These Settings changed after multi-user was enabled, hence need to be moved per user.
119187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller            if (getString("migrated_user_specific", null, 0) == null) {
120187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
121187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                final ContentResolver cr = mContext.getContentResolver();
122187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                List<UserInfo> users = um.getUsers();
123187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                for (int user = 0; user < users.size(); user++) {
1242d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    // Migrate owner info
1252d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    final int userId = users.get(user).id;
1262d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
1272d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
1282d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    if (ownerInfo != null) {
1292d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                        setString(OWNER_INFO, ownerInfo, userId);
1302d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                        Settings.Secure.putStringForUser(cr, ownerInfo, "", userId);
1312d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    }
132187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller
1332d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    // Migrate owner info enabled.  Note there was a bug where older platforms only
1342d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    // stored this value if the checkbox was toggled at least once. The code detects
1352d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    // this case by handling the exception.
1362d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
1372d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    boolean enabled;
1382d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    try {
1392d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                        int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
1402d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                        enabled = ivalue != 0;
1412d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                        setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
1422d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    } catch (SettingNotFoundException e) {
1432d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                        // Setting was never stored. Store it if the string is not empty.
1442d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                        if (!TextUtils.isEmpty(ownerInfo)) {
1452d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                            setLong(OWNER_INFO_ENABLED, 1, userId);
146187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                        }
147187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                    }
1482d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
14952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                }
150187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                // No need to move the password / pattern files. They're already in the right place.
151187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                setString("migrated_user_specific", "true", 0);
152187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                Slog.i(TAG, "Migrated per-user lock settings to new location");
15352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
15452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } catch (RemoteException re) {
155187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller            Slog.e(TAG, "Unable to migrate old data", re);
15652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
15752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
15852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
1595ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller    private final void checkWritePermission(int userId) {
160505329b21b743c6e74e0d1b14bea78a22f7b4145Jim Miller        mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
16152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
16252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
1635ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller    private final void checkPasswordReadPermission(int userId) {
164505329b21b743c6e74e0d1b14bea78a22f7b4145Jim Miller        mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
16552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
16652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
167158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller    private final void checkReadPermission(String requestedKey, int userId) {
16852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        final int callingUid = Binder.getCallingUid();
169158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller        for (int i = 0; i < READ_PROFILE_PROTECTED_SETTINGS.length; i++) {
170158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller            String key = READ_PROFILE_PROTECTED_SETTINGS[i];
171158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller            if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_PROFILE)
172158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller                    != PackageManager.PERMISSION_GRANTED) {
173158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller                throw new SecurityException("uid=" + callingUid
174158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller                        + " needs permission " + READ_PROFILE + " to read "
175158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller                        + requestedKey + " for user " + userId);
176158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller            }
17752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
17852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
17952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
18052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
18152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public void setBoolean(String key, boolean value, int userId) throws RemoteException {
18252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkWritePermission(userId);
18352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
18452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        writeToDb(key, value ? "1" : "0", userId);
18552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
18652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
18752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
18852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public void setLong(String key, long value, int userId) throws RemoteException {
18952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkWritePermission(userId);
19052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
19152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        writeToDb(key, Long.toString(value), userId);
19252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
19352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
19452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
19552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public void setString(String key, String value, int userId) throws RemoteException {
19652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkWritePermission(userId);
19752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
19852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        writeToDb(key, value, userId);
19952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
20052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
20152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
20252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
203158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller        checkReadPermission(key, userId);
20452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
20552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        String value = readFromDb(key, null, userId);
20652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        return TextUtils.isEmpty(value) ?
20752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                defaultValue : (value.equals("1") || value.equals("true"));
20852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
20952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
21052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
21152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public long getLong(String key, long defaultValue, int userId) throws RemoteException {
212158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller        checkReadPermission(key, userId);
21352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
21452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        String value = readFromDb(key, null, userId);
21552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
21652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
21752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
21852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
21952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public String getString(String key, String defaultValue, int userId) throws RemoteException {
220158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller        checkReadPermission(key, userId);
22152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
22252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        return readFromDb(key, defaultValue, userId);
22352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
22452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
22552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private String getLockPatternFilename(int userId) {
22652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        String dataSystemDirectory =
22752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                android.os.Environment.getDataDirectory().getAbsolutePath() +
22852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                SYSTEM_DIRECTORY;
22952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        if (userId == 0) {
23052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            // Leave it in the same place for user 0
23152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            return dataSystemDirectory + LOCK_PATTERN_FILE;
23252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } else {
23361f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani            return  new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
23461f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani                    .getAbsolutePath();
23552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
23652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
23752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
23852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private String getLockPasswordFilename(int userId) {
23952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        String dataSystemDirectory =
24052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                android.os.Environment.getDataDirectory().getAbsolutePath() +
24152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                SYSTEM_DIRECTORY;
24252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        if (userId == 0) {
24352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            // Leave it in the same place for user 0
24452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            return dataSystemDirectory + LOCK_PASSWORD_FILE;
24552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } else {
24661f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani            return  new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE)
24761f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani                    .getAbsolutePath();
24852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
24952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
25052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
25152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
25252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public boolean havePassword(int userId) throws RemoteException {
25352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        // Do we need a permissions check here?
25452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
25552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        return new File(getLockPasswordFilename(userId)).length() > 0;
25652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
25752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
25852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
25952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public boolean havePattern(int userId) throws RemoteException {
26052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        // Do we need a permissions check here?
26152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
26252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        return new File(getLockPatternFilename(userId)).length() > 0;
26352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
26452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
265de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    private void maybeUpdateKeystore(String password, int userId) {
266de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        if (userId == UserHandle.USER_OWNER) {
267de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            final KeyStore keyStore = KeyStore.getInstance();
268de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            // Conditionally reset the keystore if empty. If non-empty, we are just
269de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            // switching key guard type
270de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            if (TextUtils.isEmpty(password) && keyStore.isEmpty()) {
271de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                keyStore.reset();
272de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            } else {
273de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                // Update the keystore password
274de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                keyStore.password(password);
275de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            }
276de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        }
277de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    }
278de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
27952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
280de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    public void setLockPattern(String pattern, int userId) throws RemoteException {
28152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkWritePermission(userId);
28252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
283de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        maybeUpdateKeystore(pattern, userId);
284de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
285de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        final byte[] hash = LockPatternUtils.patternToHash(
286de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                LockPatternUtils.stringToPattern(pattern));
28752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        writeFile(getLockPatternFilename(userId), hash);
28852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
28952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
29052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
291de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    public void setLockPassword(String password, int userId) throws RemoteException {
292de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        checkWritePermission(userId);
293de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
294de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        maybeUpdateKeystore(password, userId);
295de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
296de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        writeFile(getLockPasswordFilename(userId), mLockPatternUtils.passwordToHash(password));
297de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    }
298de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
299de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    @Override
300de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    public boolean checkPattern(String pattern, int userId) throws RemoteException {
30152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkPasswordReadPermission(userId);
30252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        try {
30352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            // Read all the bytes from the file
30452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            RandomAccessFile raf = new RandomAccessFile(getLockPatternFilename(userId), "r");
30552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            final byte[] stored = new byte[(int) raf.length()];
30652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            int got = raf.read(stored, 0, stored.length);
30752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            raf.close();
30852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            if (got <= 0) {
30952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                return true;
31052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
31152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            // Compare the hash from the file with the entered pattern's hash
312de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            final byte[] hash = LockPatternUtils.patternToHash(
313de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                    LockPatternUtils.stringToPattern(pattern));
314de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            final boolean matched = Arrays.equals(stored, hash);
315de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            if (matched && !TextUtils.isEmpty(pattern)) {
316de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                maybeUpdateKeystore(pattern, userId);
317de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            }
318de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            return matched;
31952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } catch (FileNotFoundException fnfe) {
32052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            Slog.e(TAG, "Cannot read file " + fnfe);
32152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } catch (IOException ioe) {
32252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            Slog.e(TAG, "Cannot read file " + ioe);
32352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
324de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        return true;
32552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
32652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
32752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
328de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    public boolean checkPassword(String password, int userId) throws RemoteException {
32952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkPasswordReadPermission(userId);
33052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
33152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        try {
33252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            // Read all the bytes from the file
33352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            RandomAccessFile raf = new RandomAccessFile(getLockPasswordFilename(userId), "r");
33452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            final byte[] stored = new byte[(int) raf.length()];
33552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            int got = raf.read(stored, 0, stored.length);
33652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            raf.close();
33752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            if (got <= 0) {
33852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                return true;
33952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
34052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            // Compare the hash from the file with the entered password's hash
341de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            final byte[] hash = mLockPatternUtils.passwordToHash(password);
342de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            final boolean matched = Arrays.equals(stored, hash);
343de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            if (matched && !TextUtils.isEmpty(password)) {
344de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                maybeUpdateKeystore(password, userId);
345de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            }
346de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller            return matched;
34752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } catch (FileNotFoundException fnfe) {
34852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            Slog.e(TAG, "Cannot read file " + fnfe);
34952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } catch (IOException ioe) {
35052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            Slog.e(TAG, "Cannot read file " + ioe);
35152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
352de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        return true;
35352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
35452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
35552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
356945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        public boolean checkVoldPassword(int userId) throws RemoteException {
357945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        if (!mFirstCallToVold) {
358945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            return false;
359945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
360945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        mFirstCallToVold = false;
361945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
362945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        checkPasswordReadPermission(userId);
363945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
364945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // There's no guarantee that this will safely connect, but if it fails
365945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // we will simply show the lock screen when we shouldn't, so relatively
366945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // benign. There is an outside chance something nasty would happen if
367945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // this service restarted before vold stales out the password in this
368945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // case. The nastiness is limited to not showing the lock screen when
369945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // we should, within the first minute of decrypting the phone if this
370945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // service can't connect to vold, it restarts, and then the new instance
371945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // does successfully connect.
372945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        final IMountService service = getMountService();
373945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        String password = service.getPassword();
374945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        service.clearPassword();
375945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        if (password == null) {
376945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            return false;
377945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
378945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
379945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        try {
380945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            if (mLockPatternUtils.isLockPatternEnabled()) {
381945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                if (checkPattern(password, userId)) {
382945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                    return true;
383945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                }
384945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            }
385945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        } catch (Exception e) {
386945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
387945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
388945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        try {
389945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            if (mLockPatternUtils.isLockPasswordEnabled()) {
390945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                if (checkPassword(password, userId)) {
391945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                    return true;
392945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                }
393945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            }
394945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        } catch (Exception e) {
395945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
396945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
397945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        return false;
398945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence    }
399945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
400945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence    @Override
40152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public void removeUser(int userId) {
40252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkWritePermission(userId);
40352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
40452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
40552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        try {
40652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            File file = new File(getLockPasswordFilename(userId));
40752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            if (file.exists()) {
40852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                file.delete();
40952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
41052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            file = new File(getLockPatternFilename(userId));
41152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            if (file.exists()) {
41252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                file.delete();
41352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
41452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
41552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.beginTransaction();
41652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null);
41752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.setTransactionSuccessful();
41852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } finally {
41952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.endTransaction();
42052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
42152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
42252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
42352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private void writeFile(String name, byte[] hash) {
42452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        try {
42552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            // Write the hash to file
42652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            RandomAccessFile raf = new RandomAccessFile(name, "rw");
42752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            // Truncate the file if pattern is null, to clear the lock
42852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            if (hash == null || hash.length == 0) {
42952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                raf.setLength(0);
43052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            } else {
43152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                raf.write(hash, 0, hash.length);
43252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
43352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            raf.close();
43452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } catch (IOException ioe) {
43552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            Slog.e(TAG, "Error writing to file " + ioe);
43652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
43752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
43852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
43952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private void writeToDb(String key, String value, int userId) {
440d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani        writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId);
441d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani    }
442d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani
443d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani    private void writeToDb(SQLiteDatabase db, String key, String value, int userId) {
44452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        ContentValues cv = new ContentValues();
44552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        cv.put(COLUMN_KEY, key);
44652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        cv.put(COLUMN_USERID, userId);
44752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        cv.put(COLUMN_VALUE, value);
44852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
44952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        db.beginTransaction();
45052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        try {
45152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
45252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                    new String[] {key, Integer.toString(userId)});
45352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.insert(TABLE, null, cv);
45452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.setTransactionSuccessful();
45552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        } finally {
45652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.endTransaction();
45752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
45852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
45952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
46052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private String readFromDb(String key, String defaultValue, int userId) {
46152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        Cursor cursor;
46252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        String result = defaultValue;
46352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
46452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
46552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
46652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                new String[] { Integer.toString(userId), key },
46752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                null, null, null)) != null) {
46852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            if (cursor.moveToFirst()) {
46952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                result = cursor.getString(0);
47052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
47152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            cursor.close();
47252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
47352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        return result;
47452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
47552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
47652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    class DatabaseHelper extends SQLiteOpenHelper {
47752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        private static final String TAG = "LockSettingsDB";
47852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        private static final String DATABASE_NAME = "locksettings.db";
47952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
480f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller        private static final int DATABASE_VERSION = 2;
48152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
48252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        public DatabaseHelper(Context context) {
48352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            super(context, DATABASE_NAME, null, DATABASE_VERSION);
48452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            setWriteAheadLoggingEnabled(true);
48552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
48652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
48752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        private void createTable(SQLiteDatabase db) {
48852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            db.execSQL("CREATE TABLE " + TABLE + " (" +
48952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
49052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                    COLUMN_KEY + " TEXT," +
49152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                    COLUMN_USERID + " INTEGER," +
49252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                    COLUMN_VALUE + " TEXT" +
49352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                    ");");
49452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
49552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
49652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        @Override
49752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        public void onCreate(SQLiteDatabase db) {
49852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            createTable(db);
499d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani            initializeDefaults(db);
500d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani        }
501d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani
502d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani        private void initializeDefaults(SQLiteDatabase db) {
503d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani            // Get the lockscreen default from a system property, if available
504d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani            boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default",
505d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani                    false);
506d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani            if (lockScreenDisable) {
507d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani                writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
508d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani            }
50952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
51052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
51152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        @Override
51252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
513f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            int upgradeVersion = oldVersion;
514f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            if (upgradeVersion == 1) {
515f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                // Set the initial value for {@link LockPatternUtils#LOCKSCREEN_WIDGETS_ENABLED}
516f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                // during upgrade based on whether each user previously had widgets in keyguard.
517f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                maybeEnableWidgetSettingForUsers(db);
518f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                upgradeVersion = 2;
519f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            }
520f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller
521f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            if (upgradeVersion != DATABASE_VERSION) {
522f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                Log.w(TAG, "Failed to upgrade database!");
523f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            }
524f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller        }
525f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller
526f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller        private void maybeEnableWidgetSettingForUsers(SQLiteDatabase db) {
527f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
528f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            final ContentResolver cr = mContext.getContentResolver();
529f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            final List<UserInfo> users = um.getUsers();
530f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            for (int i = 0; i < users.size(); i++) {
531f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                final int userId = users.get(i).id;
532de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                final boolean enabled = mLockPatternUtils.hasWidgetsEnabledInKeyguard(userId);
533f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                Log.v(TAG, "Widget upgrade uid=" + userId + ", enabled="
534de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller                        + enabled + ", w[]=" + mLockPatternUtils.getAppWidgets());
535f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                loadSetting(db, LockPatternUtils.LOCKSCREEN_WIDGETS_ENABLED, userId, enabled);
536f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            }
537f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller        }
538f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller
539f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller        private void loadSetting(SQLiteDatabase db, String key, int userId, boolean value) {
540f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            SQLiteStatement stmt = null;
541f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            try {
542f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                stmt = db.compileStatement(
543f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                        "INSERT OR REPLACE INTO locksettings(name,user,value) VALUES(?,?,?);");
544f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                stmt.bindString(1, key);
545f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                stmt.bindLong(2, userId);
546f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                stmt.bindLong(3, value ? 1 : 0);
547f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                stmt.execute();
548f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            } finally {
549f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller                if (stmt != null) stmt.close();
550f45bb403884f30ecb383698ef1bcb1c7dc1964b8Jim Miller            }
55152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
55252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
55352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
55452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String[] VALID_SETTINGS = new String[] {
55552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.LOCKOUT_PERMANENT_KEY,
55652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
55752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
55852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.PASSWORD_TYPE_KEY,
55952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
56052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
56152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
56252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.LOCKSCREEN_OPTIONS,
56352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
56452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
56552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
56652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        LockPatternUtils.PASSWORD_HISTORY_KEY,
56752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        Secure.LOCK_PATTERN_ENABLED,
56852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
56952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        Secure.LOCK_PATTERN_VISIBLE,
57052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
571187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller    };
572187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller
5732d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller    // These are protected with a read permission
5742d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller    private static final String[] READ_PROFILE_PROTECTED_SETTINGS = new String[] {
575187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller        Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
576187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller        Secure.LOCK_SCREEN_OWNER_INFO
577187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller    };
578945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
579945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence    private IMountService getMountService() {
580945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        final IBinder service = ServiceManager.getService("mount");
581945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        if (service != null) {
582945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            return IMountService.Stub.asInterface(service);
583945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
584945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        return null;
585945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence    }
58652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani}
587