blob: 77662cc4969aabedc0aeef5026d32ccf8440ce67 [file] [log] [blame]
Amith Yamasani52c489c2012-03-28 11:42:42 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Sharkey7a96c392012-11-15 14:01:46 -080017package com.android.server;
Amith Yamasani52c489c2012-03-28 11:42:42 -070018
Robin Leef0246a82014-08-13 09:50:25 +010019import android.content.BroadcastReceiver;
Amith Yamasani52c489c2012-03-28 11:42:42 -070020import android.content.ContentResolver;
Amith Yamasani52c489c2012-03-28 11:42:42 -070021import android.content.Context;
Robin Leef0246a82014-08-13 09:50:25 +010022import android.content.Intent;
23import android.content.IntentFilter;
Jim Miller158fe192013-04-17 15:23:55 -070024import android.content.pm.PackageManager;
Jim Miller187ec582013-04-15 18:27:54 -070025import android.content.pm.UserInfo;
26
Adrian Roos261d5ab2014-10-29 14:42:38 +010027import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
Jim Miller187ec582013-04-15 18:27:54 -070028import static android.content.Context.USER_SERVICE;
Jim Miller158fe192013-04-17 15:23:55 -070029import static android.Manifest.permission.READ_PROFILE;
Adrian Roos261d5ab2014-10-29 14:42:38 +010030
Amith Yamasani52c489c2012-03-28 11:42:42 -070031import android.database.sqlite.SQLiteDatabase;
Amith Yamasani52c489c2012-03-28 11:42:42 -070032import android.os.Binder;
Paul Lawrence945490c2014-03-27 16:37:28 +000033import android.os.IBinder;
Robin Leef0246a82014-08-13 09:50:25 +010034import android.os.Process;
Amith Yamasani52c489c2012-03-28 11:42:42 -070035import android.os.RemoteException;
Paul Lawrence945490c2014-03-27 16:37:28 +000036import android.os.storage.IMountService;
37import android.os.ServiceManager;
Amith Yamasanid1645f82012-06-12 11:53:26 -070038import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070039import android.os.UserHandle;
Jim Miller187ec582013-04-15 18:27:54 -070040import android.os.UserManager;
Amith Yamasani52c489c2012-03-28 11:42:42 -070041import android.provider.Settings;
42import android.provider.Settings.Secure;
Jim Miller187ec582013-04-15 18:27:54 -070043import android.provider.Settings.SettingNotFoundException;
Jim Millerde1af082013-09-11 14:58:26 -070044import android.security.KeyStore;
Amith Yamasani52c489c2012-03-28 11:42:42 -070045import android.text.TextUtils;
46import android.util.Slog;
47
Jeff Sharkey7a96c392012-11-15 14:01:46 -080048import com.android.internal.widget.ILockSettings;
49import com.android.internal.widget.LockPatternUtils;
50
Adrian Roos4f788452014-05-22 20:45:59 +020051import java.util.ArrayList;
Amith Yamasani52c489c2012-03-28 11:42:42 -070052import java.util.Arrays;
Jim Miller187ec582013-04-15 18:27:54 -070053import java.util.List;
Amith Yamasani52c489c2012-03-28 11:42:42 -070054
55/**
56 * Keeps the lock pattern/password data and related settings for each user.
57 * Used by LockPatternUtils. Needs to be a service because Settings app also needs
58 * to be able to save lockscreen information for secondary users.
59 * @hide
60 */
61public class LockSettingsService extends ILockSettings.Stub {
62
Adrian Roos261d5ab2014-10-29 14:42:38 +010063 private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
Adrian Roos4f788452014-05-22 20:45:59 +020064
Amith Yamasani52c489c2012-03-28 11:42:42 -070065 private static final String TAG = "LockSettingsService";
66
Amith Yamasani52c489c2012-03-28 11:42:42 -070067 private final Context mContext;
Adrian Roos261d5ab2014-10-29 14:42:38 +010068
69 private final LockSettingsStorage mStorage;
70
Jim Millerde1af082013-09-11 14:58:26 -070071 private LockPatternUtils mLockPatternUtils;
Paul Lawrence945490c2014-03-27 16:37:28 +000072 private boolean mFirstCallToVold;
Amith Yamasani52c489c2012-03-28 11:42:42 -070073
74 public LockSettingsService(Context context) {
75 mContext = context;
76 // Open the database
Jim Millerde1af082013-09-11 14:58:26 -070077
78 mLockPatternUtils = new LockPatternUtils(context);
Paul Lawrence945490c2014-03-27 16:37:28 +000079 mFirstCallToVold = true;
Robin Leef0246a82014-08-13 09:50:25 +010080
81 IntentFilter filter = new IntentFilter();
82 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Roos3dcae682014-10-29 14:43:56 +010083 filter.addAction(Intent.ACTION_USER_STARTING);
Robin Leef0246a82014-08-13 09:50:25 +010084 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
Adrian Roos261d5ab2014-10-29 14:42:38 +010085
86 mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
87 @Override
88 public void initialize(SQLiteDatabase db) {
89 // Get the lockscreen default from a system property, if available
90 boolean lockScreenDisable = SystemProperties.getBoolean(
91 "ro.lockscreen.disable.default", false);
92 if (lockScreenDisable) {
93 mStorage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
94 }
95 }
96 });
Amith Yamasani52c489c2012-03-28 11:42:42 -070097 }
98
Robin Leef0246a82014-08-13 09:50:25 +010099 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
100 @Override
101 public void onReceive(Context context, Intent intent) {
Robin Lee1096cf82014-09-01 16:52:47 +0100102 if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
Robin Leef0246a82014-08-13 09:50:25 +0100103 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
Robin Lee49d810c2014-09-23 13:50:22 +0100104 final int userSysUid = UserHandle.getUid(userHandle, Process.SYSTEM_UID);
105 final KeyStore ks = KeyStore.getInstance();
106
107 // Clear up keystore in case anything was left behind by previous users
108 ks.resetUid(userSysUid);
109
110 // If this user has a parent, sync with its keystore password
Robin Leef0246a82014-08-13 09:50:25 +0100111 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
112 final UserInfo parentInfo = um.getProfileParent(userHandle);
113 if (parentInfo != null) {
Robin Lee49d810c2014-09-23 13:50:22 +0100114 final int parentSysUid = UserHandle.getUid(parentInfo.id, Process.SYSTEM_UID);
115 ks.syncUid(parentSysUid, userSysUid);
Robin Leef0246a82014-08-13 09:50:25 +0100116 }
Adrian Roos3dcae682014-10-29 14:43:56 +0100117 } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
118 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
119 mStorage.prefetchUser(userHandle);
Robin Leef0246a82014-08-13 09:50:25 +0100120 }
121 }
122 };
123
Amith Yamasani52c489c2012-03-28 11:42:42 -0700124 public void systemReady() {
125 migrateOldData();
Adrian Roos3dcae682014-10-29 14:43:56 +0100126 mStorage.prefetchUser(UserHandle.USER_OWNER);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700127 }
128
129 private void migrateOldData() {
130 try {
Jim Miller187ec582013-04-15 18:27:54 -0700131 // These Settings moved before multi-user was enabled, so we only have to do it for the
132 // root user.
133 if (getString("migrated", null, 0) == null) {
134 final ContentResolver cr = mContext.getContentResolver();
135 for (String validSetting : VALID_SETTINGS) {
136 String value = Settings.Secure.getString(cr, validSetting);
137 if (value != null) {
138 setString(validSetting, value, 0);
139 }
140 }
141 // No need to move the password / pattern files. They're already in the right place.
142 setString("migrated", "true", 0);
143 Slog.i(TAG, "Migrated lock settings to new location");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700144 }
145
Jim Miller187ec582013-04-15 18:27:54 -0700146 // These Settings changed after multi-user was enabled, hence need to be moved per user.
147 if (getString("migrated_user_specific", null, 0) == null) {
148 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
149 final ContentResolver cr = mContext.getContentResolver();
150 List<UserInfo> users = um.getUsers();
151 for (int user = 0; user < users.size(); user++) {
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700152 // Migrate owner info
153 final int userId = users.get(user).id;
154 final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
155 String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
156 if (ownerInfo != null) {
157 setString(OWNER_INFO, ownerInfo, userId);
158 Settings.Secure.putStringForUser(cr, ownerInfo, "", userId);
159 }
Jim Miller187ec582013-04-15 18:27:54 -0700160
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700161 // Migrate owner info enabled. Note there was a bug where older platforms only
162 // stored this value if the checkbox was toggled at least once. The code detects
163 // this case by handling the exception.
164 final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
165 boolean enabled;
166 try {
167 int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
168 enabled = ivalue != 0;
169 setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
170 } catch (SettingNotFoundException e) {
171 // Setting was never stored. Store it if the string is not empty.
172 if (!TextUtils.isEmpty(ownerInfo)) {
173 setLong(OWNER_INFO_ENABLED, 1, userId);
Jim Miller187ec582013-04-15 18:27:54 -0700174 }
175 }
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700176 Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700177 }
Jim Miller187ec582013-04-15 18:27:54 -0700178 // No need to move the password / pattern files. They're already in the right place.
179 setString("migrated_user_specific", "true", 0);
180 Slog.i(TAG, "Migrated per-user lock settings to new location");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700181 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700182 } catch (RemoteException re) {
Jim Miller187ec582013-04-15 18:27:54 -0700183 Slog.e(TAG, "Unable to migrate old data", re);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700184 }
185 }
186
Jim Miller5ecd8112013-01-09 18:50:26 -0800187 private final void checkWritePermission(int userId) {
Jim Miller505329b2013-11-08 13:25:36 -0800188 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700189 }
190
Jim Miller5ecd8112013-01-09 18:50:26 -0800191 private final void checkPasswordReadPermission(int userId) {
Jim Miller505329b2013-11-08 13:25:36 -0800192 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700193 }
194
Jim Miller158fe192013-04-17 15:23:55 -0700195 private final void checkReadPermission(String requestedKey, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700196 final int callingUid = Binder.getCallingUid();
Jim Miller158fe192013-04-17 15:23:55 -0700197 for (int i = 0; i < READ_PROFILE_PROTECTED_SETTINGS.length; i++) {
198 String key = READ_PROFILE_PROTECTED_SETTINGS[i];
199 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_PROFILE)
200 != PackageManager.PERMISSION_GRANTED) {
201 throw new SecurityException("uid=" + callingUid
202 + " needs permission " + READ_PROFILE + " to read "
203 + requestedKey + " for user " + userId);
204 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700205 }
206 }
207
208 @Override
209 public void setBoolean(String key, boolean value, int userId) throws RemoteException {
210 checkWritePermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100211 setStringUnchecked(key, userId, value ? "1" : "0");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700212 }
213
214 @Override
215 public void setLong(String key, long value, int userId) throws RemoteException {
216 checkWritePermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100217 setStringUnchecked(key, userId, Long.toString(value));
Amith Yamasani52c489c2012-03-28 11:42:42 -0700218 }
219
220 @Override
221 public void setString(String key, String value, int userId) throws RemoteException {
222 checkWritePermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100223 setStringUnchecked(key, userId, value);
224 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700225
Adrian Roos261d5ab2014-10-29 14:42:38 +0100226 private void setStringUnchecked(String key, int userId, String value) {
227 mStorage.writeKeyValue(key, value, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700228 }
229
230 @Override
231 public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700232 checkReadPermission(key, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700233
Adrian Roos261d5ab2014-10-29 14:42:38 +0100234 String value = mStorage.readKeyValue(key, null, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700235 return TextUtils.isEmpty(value) ?
236 defaultValue : (value.equals("1") || value.equals("true"));
237 }
238
239 @Override
240 public long getLong(String key, long defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700241 checkReadPermission(key, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700242
Adrian Roos261d5ab2014-10-29 14:42:38 +0100243 String value = mStorage.readKeyValue(key, null, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700244 return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
245 }
246
247 @Override
248 public String getString(String key, String defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700249 checkReadPermission(key, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700250
Adrian Roos261d5ab2014-10-29 14:42:38 +0100251 return mStorage.readKeyValue(key, defaultValue, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700252 }
253
Adrian Roos4f788452014-05-22 20:45:59 +0200254 @Override
Amith Yamasani52c489c2012-03-28 11:42:42 -0700255 public boolean havePassword(int userId) throws RemoteException {
256 // Do we need a permissions check here?
257
Adrian Roos261d5ab2014-10-29 14:42:38 +0100258 return mStorage.hasPassword(userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700259 }
260
261 @Override
262 public boolean havePattern(int userId) throws RemoteException {
263 // Do we need a permissions check here?
264
Adrian Roos261d5ab2014-10-29 14:42:38 +0100265 return mStorage.hasPattern(userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700266 }
267
Robin Leef0246a82014-08-13 09:50:25 +0100268 private void maybeUpdateKeystore(String password, int userHandle) {
269 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
270 final KeyStore ks = KeyStore.getInstance();
271
272 final List<UserInfo> profiles = um.getProfiles(userHandle);
273 boolean shouldReset = TextUtils.isEmpty(password);
274
275 // For historical reasons, don't wipe a non-empty keystore if we have a single user with a
276 // single profile.
277 if (userHandle == UserHandle.USER_OWNER && profiles.size() == 1) {
278 if (!ks.isEmpty()) {
279 shouldReset = false;
280 }
281 }
282
283 for (UserInfo pi : profiles) {
284 final int profileUid = UserHandle.getUid(pi.id, Process.SYSTEM_UID);
285 if (shouldReset) {
286 ks.resetUid(profileUid);
Jim Millerde1af082013-09-11 14:58:26 -0700287 } else {
Robin Leef0246a82014-08-13 09:50:25 +0100288 ks.passwordUid(password, profileUid);
Jim Millerde1af082013-09-11 14:58:26 -0700289 }
290 }
291 }
292
Amith Yamasani52c489c2012-03-28 11:42:42 -0700293 @Override
Jim Millerde1af082013-09-11 14:58:26 -0700294 public void setLockPattern(String pattern, int userId) throws RemoteException {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700295 checkWritePermission(userId);
296
Jim Millerde1af082013-09-11 14:58:26 -0700297 maybeUpdateKeystore(pattern, userId);
298
299 final byte[] hash = LockPatternUtils.patternToHash(
300 LockPatternUtils.stringToPattern(pattern));
Adrian Roos261d5ab2014-10-29 14:42:38 +0100301 mStorage.writePatternHash(hash, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700302 }
303
304 @Override
Jim Millerde1af082013-09-11 14:58:26 -0700305 public void setLockPassword(String password, int userId) throws RemoteException {
306 checkWritePermission(userId);
307
308 maybeUpdateKeystore(password, userId);
309
Adrian Roos261d5ab2014-10-29 14:42:38 +0100310 mStorage.writePasswordHash(mLockPatternUtils.passwordToHash(password, userId), userId);
Jim Millerde1af082013-09-11 14:58:26 -0700311 }
312
313 @Override
314 public boolean checkPattern(String pattern, int userId) throws RemoteException {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700315 checkPasswordReadPermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100316 byte[] hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(pattern));
317 byte[] storedHash = mStorage.readPatternHash(userId);
318
319 if (storedHash == null) {
320 return true;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700321 }
Adrian Roos261d5ab2014-10-29 14:42:38 +0100322
323 boolean matched = Arrays.equals(hash, storedHash);
324 if (matched && !TextUtils.isEmpty(pattern)) {
325 maybeUpdateKeystore(pattern, userId);
326 }
327 return matched;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700328 }
329
330 @Override
Jim Millerde1af082013-09-11 14:58:26 -0700331 public boolean checkPassword(String password, int userId) throws RemoteException {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700332 checkPasswordReadPermission(userId);
333
Adrian Roos261d5ab2014-10-29 14:42:38 +0100334 byte[] hash = mLockPatternUtils.passwordToHash(password, userId);
335 byte[] storedHash = mStorage.readPasswordHash(userId);
336
337 if (storedHash == null) {
338 return true;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700339 }
Adrian Roos261d5ab2014-10-29 14:42:38 +0100340
341 boolean matched = Arrays.equals(hash, storedHash);
342 if (matched && !TextUtils.isEmpty(password)) {
343 maybeUpdateKeystore(password, userId);
344 }
345 return matched;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700346 }
347
348 @Override
Adrian Roos261d5ab2014-10-29 14:42:38 +0100349 public boolean checkVoldPassword(int userId) throws RemoteException {
Paul Lawrence945490c2014-03-27 16:37:28 +0000350 if (!mFirstCallToVold) {
351 return false;
352 }
353 mFirstCallToVold = false;
354
355 checkPasswordReadPermission(userId);
356
357 // There's no guarantee that this will safely connect, but if it fails
358 // we will simply show the lock screen when we shouldn't, so relatively
359 // benign. There is an outside chance something nasty would happen if
360 // this service restarted before vold stales out the password in this
361 // case. The nastiness is limited to not showing the lock screen when
362 // we should, within the first minute of decrypting the phone if this
363 // service can't connect to vold, it restarts, and then the new instance
364 // does successfully connect.
365 final IMountService service = getMountService();
366 String password = service.getPassword();
367 service.clearPassword();
368 if (password == null) {
369 return false;
370 }
371
372 try {
373 if (mLockPatternUtils.isLockPatternEnabled()) {
374 if (checkPattern(password, userId)) {
375 return true;
376 }
377 }
378 } catch (Exception e) {
379 }
380
381 try {
382 if (mLockPatternUtils.isLockPasswordEnabled()) {
383 if (checkPassword(password, userId)) {
384 return true;
385 }
386 }
387 } catch (Exception e) {
388 }
389
390 return false;
391 }
392
393 @Override
Amith Yamasani52c489c2012-03-28 11:42:42 -0700394 public void removeUser(int userId) {
395 checkWritePermission(userId);
396
Adrian Roos261d5ab2014-10-29 14:42:38 +0100397 mStorage.removeUser(userId);
Robin Lee49d810c2014-09-23 13:50:22 +0100398
399 final KeyStore ks = KeyStore.getInstance();
400 final int userUid = UserHandle.getUid(userId, Process.SYSTEM_UID);
401 ks.resetUid(userUid);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700402 }
403
Amith Yamasani52c489c2012-03-28 11:42:42 -0700404 private static final String[] VALID_SETTINGS = new String[] {
405 LockPatternUtils.LOCKOUT_PERMANENT_KEY,
406 LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
407 LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
408 LockPatternUtils.PASSWORD_TYPE_KEY,
409 LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
410 LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
411 LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
412 LockPatternUtils.LOCKSCREEN_OPTIONS,
413 LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
414 LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
415 LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
416 LockPatternUtils.PASSWORD_HISTORY_KEY,
417 Secure.LOCK_PATTERN_ENABLED,
418 Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
419 Secure.LOCK_PATTERN_VISIBLE,
420 Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
Jim Miller187ec582013-04-15 18:27:54 -0700421 };
422
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700423 // These are protected with a read permission
424 private static final String[] READ_PROFILE_PROTECTED_SETTINGS = new String[] {
Jim Miller187ec582013-04-15 18:27:54 -0700425 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
426 Secure.LOCK_SCREEN_OWNER_INFO
427 };
Paul Lawrence945490c2014-03-27 16:37:28 +0000428
429 private IMountService getMountService() {
430 final IBinder service = ServiceManager.getService("mount");
431 if (service != null) {
432 return IMountService.Stub.asInterface(service);
433 }
434 return null;
435 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700436}