LockSettingsService.java revision 3dcae68501a1fc1c433d12a9d55a31c7eaab016c
1bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber/*
2bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Copyright (C) 2012 The Android Open Source Project
3bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber *
4bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * you may not use this file except in compliance with the License.
6bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * You may obtain a copy of the License at
7bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber *
8bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber *
10bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Unless required by applicable law or agreed to in writing, software
11bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * See the License for the specific language governing permissions and
14bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * limitations under the License.
15bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber */
16bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
17bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberpackage com.android.server;
18bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
19bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.content.BroadcastReceiver;
20bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.content.ContentResolver;
21bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.content.Context;
22bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.content.Intent;
234844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huberimport android.content.IntentFilter;
24bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.content.pm.PackageManager;
25bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.content.pm.UserInfo;
26bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
27bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
28bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport static android.content.Context.USER_SERVICE;
29bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport static android.Manifest.permission.READ_PROFILE;
30bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
31bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.database.sqlite.SQLiteDatabase;
32bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.Binder;
33bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.IBinder;
34bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.Process;
35bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.RemoteException;
36bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.storage.IMountService;
37bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.ServiceManager;
38bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.SystemProperties;
39bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.UserHandle;
40bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.os.UserManager;
41bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.provider.Settings;
42bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.provider.Settings.Secure;
43bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.provider.Settings.SettingNotFoundException;
44bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.security.KeyStore;
45bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.text.TextUtils;
46bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.util.Log;
47bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport android.util.Slog;
48bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
49bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport com.android.internal.widget.ILockSettings;
50bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport com.android.internal.widget.ILockSettingsObserver;
51bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport com.android.internal.widget.LockPatternUtils;
52bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport com.android.internal.widget.LockPatternUtilsCache;
53bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
54bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport java.util.ArrayList;
55bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport java.util.Arrays;
56bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberimport java.util.List;
57bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
58bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber/**
59bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Keeps the lock pattern/password data and related settings for each user.
60bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Used by LockPatternUtils. Needs to be a service because Settings app also needs
61bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * to be able to save lockscreen information for secondary users.
62bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * @hide
63bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber */
64bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberpublic class LockSettingsService extends ILockSettings.Stub {
65bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
66bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
67bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
68bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
69bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
70bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
71bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private static final String TAG = "LockSettingsService";
72bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
73bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private final Context mContext;
74bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
75bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private final LockSettingsStorage mStorage;
76bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
77bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private LockPatternUtils mLockPatternUtils;
78bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private boolean mFirstCallToVold;
79bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
80bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private final ArrayList<LockSettingsObserver> mObservers = new ArrayList<>();
81bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
82bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public LockSettingsService(Context context) {
83bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mContext = context;
84bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // Open the database
85bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
86bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mLockPatternUtils = new LockPatternUtils(context);
87bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mFirstCallToVold = true;
88bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
89bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        IntentFilter filter = new IntentFilter();
90bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        filter.addAction(Intent.ACTION_USER_ADDED);
91bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        filter.addAction(Intent.ACTION_USER_STARTING);
92bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
93bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
94bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
95bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            @Override
96bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            public void initialize(SQLiteDatabase db) {
97bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                // Get the lockscreen default from a system property, if available
98bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                boolean lockScreenDisable = SystemProperties.getBoolean(
99bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        "ro.lockscreen.disable.default", false);
100bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                if (lockScreenDisable) {
101bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    mStorage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
102bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                }
103bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
104bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        });
105bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
106bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
107bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
108bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        @Override
109bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        public void onReceive(Context context, Intent intent) {
110bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
111bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
112bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final int userSysUid = UserHandle.getUid(userHandle, Process.SYSTEM_UID);
113bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final KeyStore ks = KeyStore.getInstance();
114bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
115bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                // Clear up keystore in case anything was left behind by previous users
116bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                ks.resetUid(userSysUid);
117bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
118bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                // If this user has a parent, sync with its keystore password
119bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
120bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final UserInfo parentInfo = um.getProfileParent(userHandle);
121bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                if (parentInfo != null) {
122bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    final int parentSysUid = UserHandle.getUid(parentInfo.id, Process.SYSTEM_UID);
123bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    ks.syncUid(parentSysUid, userSysUid);
124bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                }
125bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
126bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
127bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                mStorage.prefetchUser(userHandle);
128bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
129bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
130bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
131bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
132bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void systemReady() {
133bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        migrateOldData();
134bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mStorage.prefetchUser(UserHandle.USER_OWNER);
135bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
136bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
137bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private void migrateOldData() {
138bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        try {
139bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            // These Settings moved before multi-user was enabled, so we only have to do it for the
140bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            // root user.
141bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            if (getString("migrated", null, 0) == null) {
142bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final ContentResolver cr = mContext.getContentResolver();
143bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                for (String validSetting : VALID_SETTINGS) {
144bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    String value = Settings.Secure.getString(cr, validSetting);
145bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    if (value != null) {
146bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        setString(validSetting, value, 0);
147bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    }
148bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                }
149bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                // No need to move the password / pattern files. They're already in the right place.
150bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                setString("migrated", "true", 0);
151bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                Slog.i(TAG, "Migrated lock settings to new location");
152bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
153bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
154bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            // These Settings changed after multi-user was enabled, hence need to be moved per user.
155bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            if (getString("migrated_user_specific", null, 0) == null) {
156bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
157bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                final ContentResolver cr = mContext.getContentResolver();
158bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                List<UserInfo> users = um.getUsers();
159bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                for (int user = 0; user < users.size(); user++) {
160bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    // Migrate owner info
161bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    final int userId = users.get(user).id;
162bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
163bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
164bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    if (ownerInfo != null) {
165bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        setString(OWNER_INFO, ownerInfo, userId);
166bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        Settings.Secure.putStringForUser(cr, ownerInfo, "", userId);
167bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    }
168bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
169bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    // Migrate owner info enabled.  Note there was a bug where older platforms only
170bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    // stored this value if the checkbox was toggled at least once. The code detects
171bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    // this case by handling the exception.
172bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
173bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    boolean enabled;
174bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    try {
175bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
176bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        enabled = ivalue != 0;
177bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
178bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    } catch (SettingNotFoundException e) {
179bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        // Setting was never stored. Store it if the string is not empty.
180bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        if (!TextUtils.isEmpty(ownerInfo)) {
181bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                            setLong(OWNER_INFO_ENABLED, 1, userId);
182bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        }
183bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    }
184bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
185bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                }
186bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                // No need to move the password / pattern files. They're already in the right place.
187bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                setString("migrated_user_specific", "true", 0);
188bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                Slog.i(TAG, "Migrated per-user lock settings to new location");
189bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
190bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        } catch (RemoteException re) {
191bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            Slog.e(TAG, "Unable to migrate old data", re);
192bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
193bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
194bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
195bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private final void checkWritePermission(int userId) {
196bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
197bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
198bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
199bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private final void checkPasswordReadPermission(int userId) {
200bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
201bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
202bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
203bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private final void checkReadPermission(String requestedKey, int userId) {
204bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        final int callingUid = Binder.getCallingUid();
205bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        for (int i = 0; i < READ_PROFILE_PROTECTED_SETTINGS.length; i++) {
206bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            String key = READ_PROFILE_PROTECTED_SETTINGS[i];
207bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_PROFILE)
208bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    != PackageManager.PERMISSION_GRANTED) {
209bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                throw new SecurityException("uid=" + callingUid
210bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        + " needs permission " + READ_PROFILE + " to read "
211bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        + requestedKey + " for user " + userId);
212bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
213bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
214bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
215bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
216bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
217bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void setBoolean(String key, boolean value, int userId) throws RemoteException {
218bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkWritePermission(userId);
219bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        setStringUnchecked(key, userId, value ? "1" : "0");
220bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
221bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
222bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
223bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void setLong(String key, long value, int userId) throws RemoteException {
224bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkWritePermission(userId);
225bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        setStringUnchecked(key, userId, Long.toString(value));
226bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
227bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
228bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
229bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void setString(String key, String value, int userId) throws RemoteException {
230bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkWritePermission(userId);
231bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        setStringUnchecked(key, userId, value);
232bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
233bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
234bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private void setStringUnchecked(String key, int userId, String value) {
235bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mStorage.writeKeyValue(key, value, userId);
236bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        notifyObservers(key, userId);
237bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
238bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
239bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
240bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
241bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkReadPermission(key, userId);
242bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
243bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        String value = mStorage.readKeyValue(key, null, userId);
244bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return TextUtils.isEmpty(value) ?
245bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                defaultValue : (value.equals("1") || value.equals("true"));
246bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
247bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
248bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
249bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public long getLong(String key, long defaultValue, int userId) throws RemoteException {
250bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkReadPermission(key, userId);
251bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
252bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        String value = mStorage.readKeyValue(key, null, userId);
253bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
254bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
255bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
256bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
257bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public String getString(String key, String defaultValue, int userId) throws RemoteException {
258bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkReadPermission(key, userId);
259bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
260bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return mStorage.readKeyValue(key, defaultValue, userId);
261bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
262bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
263bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
264fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber    public void registerObserver(ILockSettingsObserver remote) throws RemoteException {
265fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber        synchronized (mObservers) {
266bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            for (int i = 0; i < mObservers.size(); i++) {
267bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                if (mObservers.get(i).remote.asBinder() == remote.asBinder()) {
268bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
269bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    if (isDebuggable) {
270bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        throw new IllegalStateException("Observer was already registered.");
271bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    } else {
272bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        Log.e(TAG, "Observer was already registered.");
273bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                        return;
274bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    }
275bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                }
276bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
277bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            LockSettingsObserver o = new LockSettingsObserver();
278bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            o.remote = remote;
279bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            o.remote.asBinder().linkToDeath(o, 0);
280fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber            mObservers.add(o);
281bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
282bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
283bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
284bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
285bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void unregisterObserver(ILockSettingsObserver remote) throws RemoteException {
286bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        synchronized (mObservers) {
287bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            for (int i = 0; i < mObservers.size(); i++) {
288bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                if (mObservers.get(i).remote.asBinder() == remote.asBinder()) {
289bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    mObservers.remove(i);
290bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    return;
291bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                }
292bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
293bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
294bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
295bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
296bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void notifyObservers(String key, int userId) {
297bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        synchronized (mObservers) {
298bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            for (int i = 0; i < mObservers.size(); i++) {
299bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                try {
300bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    mObservers.get(i).remote.onLockSettingChanged(key, userId);
301bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                } catch (RemoteException e) {
302fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber                    // The stack trace is not really helpful here.
303fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber                    Log.e(TAG, "Failed to notify ILockSettingsObserver: " + e);
304fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber                }
305fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber            }
306fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber        }
307fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber    }
308bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
309bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
310bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public boolean havePassword(int userId) throws RemoteException {
311bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // Do we need a permissions check here?
312bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
313bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return mStorage.hasPassword(userId);
314bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
315bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
316bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
317bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public boolean havePattern(int userId) throws RemoteException {
318bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // Do we need a permissions check here?
319bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
320bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return mStorage.hasPattern(userId);
321bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
322bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
3234844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber    private void maybeUpdateKeystore(String password, int userHandle) {
3244844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber        final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
3254844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber        final KeyStore ks = KeyStore.getInstance();
3264844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber
3274844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber        final List<UserInfo> profiles = um.getProfiles(userHandle);
3284844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber        boolean shouldReset = TextUtils.isEmpty(password);
329bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
330bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // For historical reasons, don't wipe a non-empty keystore if we have a single user with a
331bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // single profile.
332bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        if (userHandle == UserHandle.USER_OWNER && profiles.size() == 1) {
333bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            if (!ks.isEmpty()) {
334bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                shouldReset = false;
335bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
336bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
337bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
338bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        for (UserInfo pi : profiles) {
339bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            final int profileUid = UserHandle.getUid(pi.id, Process.SYSTEM_UID);
340bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            if (shouldReset) {
341bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                ks.resetUid(profileUid);
342bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            } else {
343bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                ks.passwordUid(password, profileUid);
344bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
345bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
346bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
347bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
348bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
349bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void setLockPattern(String pattern, int userId) throws RemoteException {
350bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkWritePermission(userId);
351bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
352bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        maybeUpdateKeystore(pattern, userId);
353bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
354bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        final byte[] hash = LockPatternUtils.patternToHash(
355bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                LockPatternUtils.stringToPattern(pattern));
356bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mStorage.writePatternHash(hash, userId);
357bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        notifyObservers(LockPatternUtilsCache.HAS_LOCK_PATTERN_CACHE_KEY, userId);
358bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
359bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
360bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
361bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void setLockPassword(String password, int userId) throws RemoteException {
362bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkWritePermission(userId);
363bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
364bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        maybeUpdateKeystore(password, userId);
365bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
366bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mStorage.writePasswordHash(mLockPatternUtils.passwordToHash(password, userId), userId);
367bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        notifyObservers(LockPatternUtilsCache.HAS_LOCK_PASSWORD_CACHE_KEY, userId);
368bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
369bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
370bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
371bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public boolean checkPattern(String pattern, int userId) throws RemoteException {
372bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkPasswordReadPermission(userId);
373bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        byte[] hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(pattern));
374bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        byte[] storedHash = mStorage.readPatternHash(userId);
375bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
376bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        if (storedHash == null) {
377bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            return true;
378bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
379bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
380bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        boolean matched = Arrays.equals(hash, storedHash);
381bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        if (matched && !TextUtils.isEmpty(pattern)) {
382bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            maybeUpdateKeystore(pattern, userId);
383bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
384bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return matched;
385bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
386bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
387bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
388bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public boolean checkPassword(String password, int userId) throws RemoteException {
389bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkPasswordReadPermission(userId);
390bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
391bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        byte[] hash = mLockPatternUtils.passwordToHash(password, userId);
392bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        byte[] storedHash = mStorage.readPasswordHash(userId);
393bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
394bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        if (storedHash == null) {
395bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            return true;
396bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
397bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
398bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        boolean matched = Arrays.equals(hash, storedHash);
399bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        if (matched && !TextUtils.isEmpty(password)) {
400bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            maybeUpdateKeystore(password, userId);
401bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
402bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return matched;
403bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
404bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
405bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
406bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public boolean checkVoldPassword(int userId) throws RemoteException {
407bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        if (!mFirstCallToVold) {
408bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            return false;
409bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
410bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mFirstCallToVold = false;
411bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
412bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkPasswordReadPermission(userId);
413bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
414bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // There's no guarantee that this will safely connect, but if it fails
415bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // we will simply show the lock screen when we shouldn't, so relatively
416bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // benign. There is an outside chance something nasty would happen if
417bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // this service restarted before vold stales out the password in this
418bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // case. The nastiness is limited to not showing the lock screen when
419bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // we should, within the first minute of decrypting the phone if this
420bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // service can't connect to vold, it restarts, and then the new instance
421bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        // does successfully connect.
422bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        final IMountService service = getMountService();
423bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        String password = service.getPassword();
424bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        service.clearPassword();
425bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        if (password == null) {
426bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            return false;
427bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
428bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
429bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        try {
430bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            if (mLockPatternUtils.isLockPatternEnabled()) {
431bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                if (checkPattern(password, userId)) {
432bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    return true;
433bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                }
434bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
435bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        } catch (Exception e) {
436bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
437bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
438bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        try {
439bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            if (mLockPatternUtils.isLockPasswordEnabled()) {
440bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                if (checkPassword(password, userId)) {
441bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                    return true;
442bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                }
443bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            }
444bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        } catch (Exception e) {
445bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
446bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
447bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return false;
448bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
449bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
450bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    @Override
451bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    public void removeUser(int userId) {
452bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        checkWritePermission(userId);
453bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
454bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mStorage.removeUser(userId);
455bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        notifyObservers(null /* key */, userId);
456bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
457bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        final KeyStore ks = KeyStore.getInstance();
458bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        final int userUid = UserHandle.getUid(userId, Process.SYSTEM_UID);
459bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        ks.resetUid(userUid);
460bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
461bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
462bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private static final String[] VALID_SETTINGS = new String[] {
463bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.LOCKOUT_PERMANENT_KEY,
464bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
465bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
466bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.PASSWORD_TYPE_KEY,
467bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
468bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
469bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
470bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.LOCKSCREEN_OPTIONS,
471bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
472bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
473bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
474bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        LockPatternUtils.PASSWORD_HISTORY_KEY,
475bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        Secure.LOCK_PATTERN_ENABLED,
476bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
477bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        Secure.LOCK_PATTERN_VISIBLE,
478bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
479bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
480bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
481bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    // These are protected with a read permission
482bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private static final String[] READ_PROFILE_PROTECTED_SETTINGS = new String[] {
483bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
484bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        Secure.LOCK_SCREEN_OWNER_INFO
485bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
486bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
487bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private IMountService getMountService() {
488bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        final IBinder service = ServiceManager.getService("mount");
489bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        if (service != null) {
490bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            return IMountService.Stub.asInterface(service);
491bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
492bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return null;
493bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
494bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
495bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    private class LockSettingsObserver implements DeathRecipient {
496bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        ILockSettingsObserver remote;
497bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
498bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        @Override
499bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        public void binderDied() {
500bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            mObservers.remove(this);
501bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        }
502bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
503bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber}
504bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber