blob: f6f05fe8f01a47de832f77b4e956b90f12cb4034 [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
Jeff Sharkey8924e872015-11-30 12:52:10 -070019import android.app.ActivityManagerNative;
20import android.app.AppGlobals;
Adrian Roos230635e2015-01-07 20:50:29 +010021import android.app.admin.DevicePolicyManager;
Amith Yamasani072543f2015-02-13 11:09:45 -080022import android.app.backup.BackupManager;
Adrian Roosb5e47222015-08-14 15:53:06 -070023import android.app.trust.IStrongAuthTracker;
Clara Bayarri56878a92015-10-29 15:43:55 +000024import android.app.trust.ITrustManager;
25import android.app.trust.TrustManager;
Robin Leef0246a82014-08-13 09:50:25 +010026import android.content.BroadcastReceiver;
Amith Yamasani52c489c2012-03-28 11:42:42 -070027import android.content.ContentResolver;
Amith Yamasani52c489c2012-03-28 11:42:42 -070028import android.content.Context;
Robin Leef0246a82014-08-13 09:50:25 +010029import android.content.Intent;
30import android.content.IntentFilter;
Jim Miller158fe192013-04-17 15:23:55 -070031import android.content.pm.PackageManager;
Jim Miller187ec582013-04-15 18:27:54 -070032import android.content.pm.UserInfo;
Adrian Roos261d5ab2014-10-29 14:42:38 +010033import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
Jim Miller187ec582013-04-15 18:27:54 -070034import static android.content.Context.USER_SERVICE;
Svetoslav Ganov6d2c0e52015-06-23 16:33:36 +000035import static android.Manifest.permission.READ_CONTACTS;
Adrian Roos873010d2015-08-25 15:59:00 -070036import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
37
Amith Yamasani52c489c2012-03-28 11:42:42 -070038import android.database.sqlite.SQLiteDatabase;
Amith Yamasani52c489c2012-03-28 11:42:42 -070039import android.os.Binder;
Paul Lawrence945490c2014-03-27 16:37:28 +000040import android.os.IBinder;
Amith Yamasani52c489c2012-03-28 11:42:42 -070041import android.os.RemoteException;
Paul Lawrence945490c2014-03-27 16:37:28 +000042import android.os.storage.IMountService;
Clara Bayarri56878a92015-10-29 15:43:55 +000043import android.os.storage.StorageManager;
Paul Lawrence945490c2014-03-27 16:37:28 +000044import android.os.ServiceManager;
Amith Yamasanid1645f82012-06-12 11:53:26 -070045import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070046import android.os.UserHandle;
Jim Miller187ec582013-04-15 18:27:54 -070047import android.os.UserManager;
Amith Yamasani52c489c2012-03-28 11:42:42 -070048import android.provider.Settings;
49import android.provider.Settings.Secure;
Jim Miller187ec582013-04-15 18:27:54 -070050import android.provider.Settings.SettingNotFoundException;
Jim Millerde1af082013-09-11 14:58:26 -070051import android.security.KeyStore;
Andres Morales23974272015-05-14 22:42:26 -070052import android.service.gatekeeper.GateKeeperResponse;
Andres Morales8fa56652015-03-31 09:19:50 -070053import android.service.gatekeeper.IGateKeeperService;
Amith Yamasani52c489c2012-03-28 11:42:42 -070054import android.text.TextUtils;
55import android.util.Slog;
56
Amith Yamasani072543f2015-02-13 11:09:45 -080057import com.android.internal.util.ArrayUtils;
Jeff Sharkey7a96c392012-11-15 14:01:46 -080058import com.android.internal.widget.ILockSettings;
59import com.android.internal.widget.LockPatternUtils;
Andres Morales23974272015-05-14 22:42:26 -070060import com.android.internal.widget.VerifyCredentialResponse;
Andres Morales8fa56652015-03-31 09:19:50 -070061import com.android.server.LockSettingsStorage.CredentialHash;
Jeff Sharkey7a96c392012-11-15 14:01:46 -080062
Amith Yamasani52c489c2012-03-28 11:42:42 -070063import java.util.Arrays;
Jim Miller187ec582013-04-15 18:27:54 -070064import java.util.List;
Amith Yamasani52c489c2012-03-28 11:42:42 -070065
66/**
67 * Keeps the lock pattern/password data and related settings for each user.
68 * Used by LockPatternUtils. Needs to be a service because Settings app also needs
69 * to be able to save lockscreen information for secondary users.
70 * @hide
71 */
72public class LockSettingsService extends ILockSettings.Stub {
73
Adrian Roos261d5ab2014-10-29 14:42:38 +010074 private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
Adrian Roos4f788452014-05-22 20:45:59 +020075
Amith Yamasani52c489c2012-03-28 11:42:42 -070076 private static final String TAG = "LockSettingsService";
77
Amith Yamasani52c489c2012-03-28 11:42:42 -070078 private final Context mContext;
Adrian Roos261d5ab2014-10-29 14:42:38 +010079
80 private final LockSettingsStorage mStorage;
Rakesh Iyera7aa4d62016-01-19 17:27:23 -080081 private final LockSettingsStrongAuth mStrongAuth;
Adrian Roos261d5ab2014-10-29 14:42:38 +010082
Jim Millerde1af082013-09-11 14:58:26 -070083 private LockPatternUtils mLockPatternUtils;
Paul Lawrence945490c2014-03-27 16:37:28 +000084 private boolean mFirstCallToVold;
Andres Morales8fa56652015-03-31 09:19:50 -070085 private IGateKeeperService mGateKeeperService;
Amith Yamasani52c489c2012-03-28 11:42:42 -070086
Andres Morales23974272015-05-14 22:42:26 -070087 private interface CredentialUtil {
88 void setCredential(String credential, String savedCredential, int userId)
89 throws RemoteException;
90 byte[] toHash(String credential, int userId);
Andres Morales59ef1262015-06-26 13:56:39 -070091 String adjustForKeystore(String credential);
Andres Morales23974272015-05-14 22:42:26 -070092 }
93
Amith Yamasani52c489c2012-03-28 11:42:42 -070094 public LockSettingsService(Context context) {
95 mContext = context;
Rakesh Iyera7aa4d62016-01-19 17:27:23 -080096 mStrongAuth = new LockSettingsStrongAuth(context);
Amith Yamasani52c489c2012-03-28 11:42:42 -070097 // Open the database
Jim Millerde1af082013-09-11 14:58:26 -070098
99 mLockPatternUtils = new LockPatternUtils(context);
Paul Lawrence945490c2014-03-27 16:37:28 +0000100 mFirstCallToVold = true;
Robin Leef0246a82014-08-13 09:50:25 +0100101
102 IntentFilter filter = new IntentFilter();
103 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Roos3dcae682014-10-29 14:43:56 +0100104 filter.addAction(Intent.ACTION_USER_STARTING);
Adrian Roosdb0f76e2015-01-07 22:19:38 +0100105 filter.addAction(Intent.ACTION_USER_REMOVED);
Adrian Roosb5e47222015-08-14 15:53:06 -0700106 filter.addAction(Intent.ACTION_USER_PRESENT);
Robin Leef0246a82014-08-13 09:50:25 +0100107 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100108
109 mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
110 @Override
111 public void initialize(SQLiteDatabase db) {
112 // Get the lockscreen default from a system property, if available
113 boolean lockScreenDisable = SystemProperties.getBoolean(
114 "ro.lockscreen.disable.default", false);
115 if (lockScreenDisable) {
116 mStorage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
117 }
118 }
119 });
Amith Yamasani52c489c2012-03-28 11:42:42 -0700120 }
121
Robin Leef0246a82014-08-13 09:50:25 +0100122 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
123 @Override
124 public void onReceive(Context context, Intent intent) {
Robin Lee1096cf82014-09-01 16:52:47 +0100125 if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
Chad Brubaker83ce0952015-05-12 13:00:02 -0700126 // Notify keystore that a new user was added.
Robin Leef0246a82014-08-13 09:50:25 +0100127 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
Robin Lee49d810c2014-09-23 13:50:22 +0100128 final KeyStore ks = KeyStore.getInstance();
Robin Leef0246a82014-08-13 09:50:25 +0100129 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
130 final UserInfo parentInfo = um.getProfileParent(userHandle);
Chad Brubaker83ce0952015-05-12 13:00:02 -0700131 final int parentHandle = parentInfo != null ? parentInfo.id : -1;
132 ks.onUserAdded(userHandle, parentHandle);
Adrian Roos3dcae682014-10-29 14:43:56 +0100133 } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
134 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
135 mStorage.prefetchUser(userHandle);
Adrian Roosb5e47222015-08-14 15:53:06 -0700136 } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
137 mStrongAuth.reportUnlock(getSendingUserId());
Adrian Roosdb0f76e2015-01-07 22:19:38 +0100138 } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
139 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
140 if (userHandle > 0) {
141 removeUser(userHandle);
142 }
Robin Leef0246a82014-08-13 09:50:25 +0100143 }
144 }
145 };
146
Amith Yamasani52c489c2012-03-28 11:42:42 -0700147 public void systemReady() {
148 migrateOldData();
Andres Morales301ea442015-04-17 09:15:47 -0700149 try {
150 getGateKeeperService();
151 } catch (RemoteException e) {
152 Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
153 }
Xiaohui Chen7c696362015-09-16 09:56:14 -0700154 // TODO: maybe skip this for split system user mode.
155 mStorage.prefetchUser(UserHandle.USER_SYSTEM);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700156 }
157
158 private void migrateOldData() {
159 try {
Jim Miller187ec582013-04-15 18:27:54 -0700160 // These Settings moved before multi-user was enabled, so we only have to do it for the
161 // root user.
162 if (getString("migrated", null, 0) == null) {
163 final ContentResolver cr = mContext.getContentResolver();
164 for (String validSetting : VALID_SETTINGS) {
165 String value = Settings.Secure.getString(cr, validSetting);
166 if (value != null) {
167 setString(validSetting, value, 0);
168 }
169 }
170 // No need to move the password / pattern files. They're already in the right place.
171 setString("migrated", "true", 0);
172 Slog.i(TAG, "Migrated lock settings to new location");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700173 }
174
Jim Miller187ec582013-04-15 18:27:54 -0700175 // These Settings changed after multi-user was enabled, hence need to be moved per user.
176 if (getString("migrated_user_specific", null, 0) == null) {
177 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
178 final ContentResolver cr = mContext.getContentResolver();
179 List<UserInfo> users = um.getUsers();
180 for (int user = 0; user < users.size(); user++) {
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700181 // Migrate owner info
182 final int userId = users.get(user).id;
183 final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
184 String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
185 if (ownerInfo != null) {
186 setString(OWNER_INFO, ownerInfo, userId);
187 Settings.Secure.putStringForUser(cr, ownerInfo, "", userId);
188 }
Jim Miller187ec582013-04-15 18:27:54 -0700189
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700190 // Migrate owner info enabled. Note there was a bug where older platforms only
191 // stored this value if the checkbox was toggled at least once. The code detects
192 // this case by handling the exception.
193 final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
194 boolean enabled;
195 try {
196 int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
197 enabled = ivalue != 0;
198 setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
199 } catch (SettingNotFoundException e) {
200 // Setting was never stored. Store it if the string is not empty.
201 if (!TextUtils.isEmpty(ownerInfo)) {
202 setLong(OWNER_INFO_ENABLED, 1, userId);
Jim Miller187ec582013-04-15 18:27:54 -0700203 }
204 }
Jim Miller2d8ecf9d2013-04-22 17:17:03 -0700205 Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700206 }
Jim Miller187ec582013-04-15 18:27:54 -0700207 // No need to move the password / pattern files. They're already in the right place.
208 setString("migrated_user_specific", "true", 0);
209 Slog.i(TAG, "Migrated per-user lock settings to new location");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700210 }
Adrian Roos230635e2015-01-07 20:50:29 +0100211
212 // Migrates biometric weak such that the fallback mechanism becomes the primary.
213 if (getString("migrated_biometric_weak", null, 0) == null) {
214 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
215 List<UserInfo> users = um.getUsers();
216 for (int i = 0; i < users.size(); i++) {
217 int userId = users.get(i).id;
218 long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
219 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
220 userId);
221 long alternateType = getLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
222 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
223 userId);
224 if (type == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
225 setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
226 alternateType,
227 userId);
228 }
229 setLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
230 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
231 userId);
232 }
233 setString("migrated_biometric_weak", "true", 0);
234 Slog.i(TAG, "Migrated biometric weak to use the fallback instead");
235 }
Adrian Roos43830582015-04-21 16:04:43 -0700236
237 // Migrates lockscreen.disabled. Prior to M, the flag was ignored when more than one
238 // user was present on the system, so if we're upgrading to M and there is more than one
239 // user we disable the flag to remain consistent.
240 if (getString("migrated_lockscreen_disabled", null, 0) == null) {
241 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
242
243 final List<UserInfo> users = um.getUsers();
244 final int userCount = users.size();
245 int switchableUsers = 0;
246 for (int i = 0; i < userCount; i++) {
247 if (users.get(i).supportsSwitchTo()) {
248 switchableUsers++;
249 }
250 }
251
252 if (switchableUsers > 1) {
253 for (int i = 0; i < userCount; i++) {
254 int id = users.get(i).id;
255
256 if (getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id)) {
257 setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
258 }
259 }
260 }
261
262 setString("migrated_lockscreen_disabled", "true", 0);
263 Slog.i(TAG, "Migrated lockscreen disabled flag");
264 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700265 } catch (RemoteException re) {
Jim Miller187ec582013-04-15 18:27:54 -0700266 Slog.e(TAG, "Unable to migrate old data", re);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700267 }
268 }
269
Jim Miller5ecd8112013-01-09 18:50:26 -0800270 private final void checkWritePermission(int userId) {
Jim Miller505329b2013-11-08 13:25:36 -0800271 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700272 }
273
Jim Miller5ecd8112013-01-09 18:50:26 -0800274 private final void checkPasswordReadPermission(int userId) {
Jim Miller505329b2013-11-08 13:25:36 -0800275 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700276 }
277
Jim Miller158fe192013-04-17 15:23:55 -0700278 private final void checkReadPermission(String requestedKey, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700279 final int callingUid = Binder.getCallingUid();
Adrian Roos001b00d2015-02-24 17:08:48 +0100280
Svetoslav Ganov6d2c0e52015-06-23 16:33:36 +0000281 for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) {
282 String key = READ_CONTACTS_PROTECTED_SETTINGS[i];
283 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS)
Jim Miller158fe192013-04-17 15:23:55 -0700284 != PackageManager.PERMISSION_GRANTED) {
285 throw new SecurityException("uid=" + callingUid
Svetoslav Ganov6d2c0e52015-06-23 16:33:36 +0000286 + " needs permission " + READ_CONTACTS + " to read "
Jim Miller158fe192013-04-17 15:23:55 -0700287 + requestedKey + " for user " + userId);
288 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700289 }
Adrian Roos001b00d2015-02-24 17:08:48 +0100290
291 for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) {
292 String key = READ_PASSWORD_PROTECTED_SETTINGS[i];
293 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION)
294 != PackageManager.PERMISSION_GRANTED) {
295 throw new SecurityException("uid=" + callingUid
296 + " needs permission " + PERMISSION + " to read "
297 + requestedKey + " for user " + userId);
298 }
299 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700300 }
301
302 @Override
303 public void setBoolean(String key, boolean value, int userId) throws RemoteException {
304 checkWritePermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100305 setStringUnchecked(key, userId, value ? "1" : "0");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700306 }
307
308 @Override
309 public void setLong(String key, long value, int userId) throws RemoteException {
310 checkWritePermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100311 setStringUnchecked(key, userId, Long.toString(value));
Amith Yamasani52c489c2012-03-28 11:42:42 -0700312 }
313
314 @Override
315 public void setString(String key, String value, int userId) throws RemoteException {
316 checkWritePermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100317 setStringUnchecked(key, userId, value);
318 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700319
Adrian Roos261d5ab2014-10-29 14:42:38 +0100320 private void setStringUnchecked(String key, int userId, String value) {
321 mStorage.writeKeyValue(key, value, userId);
Amith Yamasani072543f2015-02-13 11:09:45 -0800322 if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
323 BackupManager.dataChanged("com.android.providers.settings");
324 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700325 }
326
327 @Override
328 public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700329 checkReadPermission(key, userId);
Adrian Roos9dd16eb2015-01-08 16:20:49 +0100330 String value = getStringUnchecked(key, null, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700331 return TextUtils.isEmpty(value) ?
332 defaultValue : (value.equals("1") || value.equals("true"));
333 }
334
335 @Override
336 public long getLong(String key, long defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700337 checkReadPermission(key, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700338
Adrian Roos9dd16eb2015-01-08 16:20:49 +0100339 String value = getStringUnchecked(key, null, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700340 return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
341 }
342
343 @Override
344 public String getString(String key, String defaultValue, int userId) throws RemoteException {
Jim Miller158fe192013-04-17 15:23:55 -0700345 checkReadPermission(key, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700346
Adrian Roos9dd16eb2015-01-08 16:20:49 +0100347 return getStringUnchecked(key, defaultValue, userId);
348 }
349
350 public String getStringUnchecked(String key, String defaultValue, int userId) {
351 if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
Adrian Roos7811d9f2015-07-27 15:10:13 -0700352 long ident = Binder.clearCallingIdentity();
353 try {
354 return mLockPatternUtils.isLockPatternEnabled(userId) ? "1" : "0";
355 } finally {
356 Binder.restoreCallingIdentity(ident);
357 }
Adrian Roos9dd16eb2015-01-08 16:20:49 +0100358 }
359
Bryce Lee46145962015-12-14 14:39:10 -0800360 if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
361 key = Settings.Secure.LOCK_PATTERN_ENABLED;
362 }
363
Adrian Roos261d5ab2014-10-29 14:42:38 +0100364 return mStorage.readKeyValue(key, defaultValue, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700365 }
366
Adrian Roos4f788452014-05-22 20:45:59 +0200367 @Override
Amith Yamasani52c489c2012-03-28 11:42:42 -0700368 public boolean havePassword(int userId) throws RemoteException {
369 // Do we need a permissions check here?
370
Adrian Roos261d5ab2014-10-29 14:42:38 +0100371 return mStorage.hasPassword(userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700372 }
373
374 @Override
375 public boolean havePattern(int userId) throws RemoteException {
376 // Do we need a permissions check here?
377
Adrian Roos261d5ab2014-10-29 14:42:38 +0100378 return mStorage.hasPattern(userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700379 }
380
Chad Brubakera91a8502015-05-07 10:02:22 -0700381 private void setKeystorePassword(String password, int userHandle) {
Robin Leef0246a82014-08-13 09:50:25 +0100382 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
383 final KeyStore ks = KeyStore.getInstance();
384
385 final List<UserInfo> profiles = um.getProfiles(userHandle);
Robin Leef0246a82014-08-13 09:50:25 +0100386 for (UserInfo pi : profiles) {
Chad Brubakera91a8502015-05-07 10:02:22 -0700387 ks.onUserPasswordChanged(pi.id, password);
388 }
389 }
390
391 private void unlockKeystore(String password, int userHandle) {
392 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
393 final KeyStore ks = KeyStore.getInstance();
394
395 final List<UserInfo> profiles = um.getProfiles(userHandle);
396 for (UserInfo pi : profiles) {
397 ks.unlock(pi.id, password);
Jim Millerde1af082013-09-11 14:58:26 -0700398 }
399 }
400
Jeff Sharkey8924e872015-11-30 12:52:10 -0700401 private void unlockUser(int userId, byte[] token) {
402 try {
403 ActivityManagerNative.getDefault().unlockUser(userId, token);
404 } catch (RemoteException e) {
405 throw e.rethrowAsRuntimeException();
406 }
407 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700408
Andres Morales8fa56652015-03-31 09:19:50 -0700409 private byte[] getCurrentHandle(int userId) {
410 CredentialHash credential;
411 byte[] currentHandle;
Jim Millerde1af082013-09-11 14:58:26 -0700412
Andres Morales8fa56652015-03-31 09:19:50 -0700413 int currentHandleType = mStorage.getStoredCredentialType(userId);
414 switch (currentHandleType) {
415 case CredentialHash.TYPE_PATTERN:
416 credential = mStorage.readPatternHash(userId);
417 currentHandle = credential != null
418 ? credential.hash
419 : null;
420 break;
421 case CredentialHash.TYPE_PASSWORD:
422 credential = mStorage.readPasswordHash(userId);
423 currentHandle = credential != null
424 ? credential.hash
425 : null;
426 break;
427 case CredentialHash.TYPE_NONE:
428 default:
429 currentHandle = null;
430 break;
431 }
432
433 // sanity check
434 if (currentHandleType != CredentialHash.TYPE_NONE && currentHandle == null) {
435 Slog.e(TAG, "Stored handle type [" + currentHandleType + "] but no handle available");
436 }
437
438 return currentHandle;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700439 }
440
Andres Morales8fa56652015-03-31 09:19:50 -0700441
Amith Yamasani52c489c2012-03-28 11:42:42 -0700442 @Override
Andres Morales8fa56652015-03-31 09:19:50 -0700443 public void setLockPattern(String pattern, String savedCredential, int userId)
444 throws RemoteException {
445 byte[] currentHandle = getCurrentHandle(userId);
446
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700447 if (pattern == null) {
Andres Moralescfb61602015-04-16 16:31:15 -0700448 getGateKeeperService().clearSecureUserId(userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700449 mStorage.writePatternHash(null, userId);
Chad Brubakera91a8502015-05-07 10:02:22 -0700450 setKeystorePassword(null, userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700451 return;
452 }
453
Andres Morales8fa56652015-03-31 09:19:50 -0700454 if (currentHandle == null) {
455 if (savedCredential != null) {
456 Slog.w(TAG, "Saved credential provided, but none stored");
457 }
458 savedCredential = null;
459 }
460
461 byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, pattern, userId);
462 if (enrolledHandle != null) {
463 mStorage.writePatternHash(enrolledHandle, userId);
464 } else {
Andres Morales2c4a5732015-07-09 16:11:00 -0700465 throw new RemoteException("Failed to enroll pattern");
Andres Morales8fa56652015-03-31 09:19:50 -0700466 }
467 }
468
469
470 @Override
471 public void setLockPassword(String password, String savedCredential, int userId)
472 throws RemoteException {
Andres Morales8fa56652015-03-31 09:19:50 -0700473 byte[] currentHandle = getCurrentHandle(userId);
474
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700475 if (password == null) {
Andres Moralescfb61602015-04-16 16:31:15 -0700476 getGateKeeperService().clearSecureUserId(userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700477 mStorage.writePasswordHash(null, userId);
Chad Brubakera91a8502015-05-07 10:02:22 -0700478 setKeystorePassword(null, userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700479 return;
480 }
481
Andres Morales8fa56652015-03-31 09:19:50 -0700482 if (currentHandle == null) {
483 if (savedCredential != null) {
484 Slog.w(TAG, "Saved credential provided, but none stored");
485 }
486 savedCredential = null;
487 }
488
489 byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, password, userId);
490 if (enrolledHandle != null) {
491 mStorage.writePasswordHash(enrolledHandle, userId);
492 } else {
Andres Morales2c4a5732015-07-09 16:11:00 -0700493 throw new RemoteException("Failed to enroll password");
Andres Morales8fa56652015-03-31 09:19:50 -0700494 }
495 }
496
497 private byte[] enrollCredential(byte[] enrolledHandle,
498 String enrolledCredential, String toEnroll, int userId)
499 throws RemoteException {
Jim Millerde1af082013-09-11 14:58:26 -0700500 checkWritePermission(userId);
Andres Morales8fa56652015-03-31 09:19:50 -0700501 byte[] enrolledCredentialBytes = enrolledCredential == null
502 ? null
503 : enrolledCredential.getBytes();
504 byte[] toEnrollBytes = toEnroll == null
505 ? null
506 : toEnroll.getBytes();
Andres Morales23974272015-05-14 22:42:26 -0700507 GateKeeperResponse response = getGateKeeperService().enroll(userId, enrolledHandle,
508 enrolledCredentialBytes, toEnrollBytes);
Jim Millerde1af082013-09-11 14:58:26 -0700509
Andres Morales23974272015-05-14 22:42:26 -0700510 if (response == null) {
511 return null;
Andres Morales8fa56652015-03-31 09:19:50 -0700512 }
Jim Millerde1af082013-09-11 14:58:26 -0700513
Andres Morales23974272015-05-14 22:42:26 -0700514 byte[] hash = response.getPayload();
515 if (hash != null) {
516 setKeystorePassword(toEnroll, userId);
517 } else {
518 // Should not happen
519 Slog.e(TAG, "Throttled while enrolling a password");
520 }
Andres Morales8fa56652015-03-31 09:19:50 -0700521 return hash;
Jim Millerde1af082013-09-11 14:58:26 -0700522 }
523
524 @Override
Andres Morales23974272015-05-14 22:42:26 -0700525 public VerifyCredentialResponse checkPattern(String pattern, int userId) throws RemoteException {
526 return doVerifyPattern(pattern, false, 0, userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700527 }
Adrian Roos261d5ab2014-10-29 14:42:38 +0100528
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700529 @Override
Andres Morales23974272015-05-14 22:42:26 -0700530 public VerifyCredentialResponse verifyPattern(String pattern, long challenge, int userId)
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700531 throws RemoteException {
Andres Morales23974272015-05-14 22:42:26 -0700532 return doVerifyPattern(pattern, true, challenge, userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700533 }
534
Andres Moralese40bad82015-05-28 14:21:36 -0700535 private VerifyCredentialResponse doVerifyPattern(String pattern, boolean hasChallenge,
536 long challenge, int userId) throws RemoteException {
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700537 checkPasswordReadPermission(userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700538 CredentialHash storedHash = mStorage.readPatternHash(userId);
Andres Moralese40bad82015-05-28 14:21:36 -0700539 boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern;
540
541 String patternToVerify;
542 if (shouldReEnrollBaseZero) {
543 patternToVerify = LockPatternUtils.patternStringToBaseZero(pattern);
544 } else {
545 patternToVerify = pattern;
546 }
547
548 VerifyCredentialResponse response = verifyCredential(userId, storedHash, patternToVerify,
549 hasChallenge, challenge,
Andres Morales23974272015-05-14 22:42:26 -0700550 new CredentialUtil() {
551 @Override
552 public void setCredential(String pattern, String oldPattern, int userId)
553 throws RemoteException {
554 setLockPattern(pattern, oldPattern, userId);
555 }
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700556
Andres Morales23974272015-05-14 22:42:26 -0700557 @Override
558 public byte[] toHash(String pattern, int userId) {
Andres Moralese40bad82015-05-28 14:21:36 -0700559 return LockPatternUtils.patternToHash(
560 LockPatternUtils.stringToPattern(pattern));
Andres Morales23974272015-05-14 22:42:26 -0700561 }
Andres Morales59ef1262015-06-26 13:56:39 -0700562
563 @Override
564 public String adjustForKeystore(String pattern) {
565 return LockPatternUtils.patternStringToBaseZero(pattern);
566 }
Andres Morales23974272015-05-14 22:42:26 -0700567 }
568 );
Andres Moralese40bad82015-05-28 14:21:36 -0700569
570 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK
571 && shouldReEnrollBaseZero) {
572 setLockPattern(pattern, patternToVerify, userId);
573 }
574
575 return response;
576
Amith Yamasani52c489c2012-03-28 11:42:42 -0700577 }
578
579 @Override
Andres Morales23974272015-05-14 22:42:26 -0700580 public VerifyCredentialResponse checkPassword(String password, int userId)
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700581 throws RemoteException {
Andres Morales23974272015-05-14 22:42:26 -0700582 return doVerifyPassword(password, false, 0, userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700583 }
584
Andres Morales23974272015-05-14 22:42:26 -0700585 @Override
586 public VerifyCredentialResponse verifyPassword(String password, long challenge, int userId)
587 throws RemoteException {
588 return doVerifyPassword(password, true, challenge, userId);
589 }
590
591 private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge,
592 long challenge, int userId) throws RemoteException {
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700593 checkPasswordReadPermission(userId);
Andres Morales8fa56652015-03-31 09:19:50 -0700594 CredentialHash storedHash = mStorage.readPasswordHash(userId);
Andres Morales23974272015-05-14 22:42:26 -0700595 return verifyCredential(userId, storedHash, password, hasChallenge, challenge,
596 new CredentialUtil() {
597 @Override
598 public void setCredential(String password, String oldPassword, int userId)
599 throws RemoteException {
600 setLockPassword(password, oldPassword, userId);
601 }
Adrian Roos261d5ab2014-10-29 14:42:38 +0100602
Andres Morales23974272015-05-14 22:42:26 -0700603 @Override
604 public byte[] toHash(String password, int userId) {
605 return mLockPatternUtils.passwordToHash(password, userId);
606 }
Andres Morales59ef1262015-06-26 13:56:39 -0700607
608 @Override
609 public String adjustForKeystore(String password) {
610 return password;
611 }
Andres Morales23974272015-05-14 22:42:26 -0700612 }
613 );
614 }
615
616 private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
617 String credential, boolean hasChallenge, long challenge, CredentialUtil credentialUtil)
618 throws RemoteException {
619 if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) {
620 // don't need to pass empty credentials to GateKeeper
621 return VerifyCredentialResponse.OK;
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700622 }
623
Andres Morales23974272015-05-14 22:42:26 -0700624 if (TextUtils.isEmpty(credential)) {
625 return VerifyCredentialResponse.ERROR;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700626 }
Adrian Roos261d5ab2014-10-29 14:42:38 +0100627
Andres Morales8fa56652015-03-31 09:19:50 -0700628 if (storedHash.version == CredentialHash.VERSION_LEGACY) {
Andres Morales23974272015-05-14 22:42:26 -0700629 byte[] hash = credentialUtil.toHash(credential, userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700630 if (Arrays.equals(hash, storedHash.hash)) {
Andres Morales59ef1262015-06-26 13:56:39 -0700631 unlockKeystore(credentialUtil.adjustForKeystore(credential), userId);
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700632
633 // TODO: pass through a meaningful token from gatekeeper to
634 // unlock credential keys; for now pass through a stub value to
635 // indicate that we came from a user challenge.
636 final byte[] token = String.valueOf(userId).getBytes();
637 unlockUser(userId, token);
638
Andres Morales23974272015-05-14 22:42:26 -0700639 // migrate credential to GateKeeper
640 credentialUtil.setCredential(credential, null, userId);
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700641 if (!hasChallenge) {
Andres Morales23974272015-05-14 22:42:26 -0700642 return VerifyCredentialResponse.OK;
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700643 }
644 // Fall through to get the auth token. Technically this should never happen,
Andres Morales23974272015-05-14 22:42:26 -0700645 // as a user that had a legacy credential would have to unlock their device
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700646 // before getting to a flow with a challenge, but supporting for consistency.
647 } else {
Andres Morales23974272015-05-14 22:42:26 -0700648 return VerifyCredentialResponse.ERROR;
Andres Morales8fa56652015-03-31 09:19:50 -0700649 }
Andres Morales8fa56652015-03-31 09:19:50 -0700650 }
651
Andres Morales23974272015-05-14 22:42:26 -0700652 VerifyCredentialResponse response;
653 boolean shouldReEnroll = false;;
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700654 if (hasChallenge) {
Andres Morales23974272015-05-14 22:42:26 -0700655 byte[] token = null;
656 GateKeeperResponse gateKeeperResponse = getGateKeeperService()
657 .verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
658 int responseCode = gateKeeperResponse.getResponseCode();
659 if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
660 response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
661 } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
662 token = gateKeeperResponse.getPayload();
663 if (token == null) {
664 // something's wrong if there's no payload with a challenge
665 Slog.e(TAG, "verifyChallenge response had no associated payload");
666 response = VerifyCredentialResponse.ERROR;
667 } else {
668 shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
669 response = new VerifyCredentialResponse(token);
670 }
671 } else {
672 response = VerifyCredentialResponse.ERROR;
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700673 }
Andres Morales23974272015-05-14 22:42:26 -0700674 } else {
675 GateKeeperResponse gateKeeperResponse = getGateKeeperService().verify(
676 userId, storedHash.hash, credential.getBytes());
677 int responseCode = gateKeeperResponse.getResponseCode();
678 if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
679 response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
680 } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
681 shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
682 response = VerifyCredentialResponse.OK;
683 } else {
684 response = VerifyCredentialResponse.ERROR;
685 }
Adrian Roos261d5ab2014-10-29 14:42:38 +0100686 }
Andres Morales8fa56652015-03-31 09:19:50 -0700687
Andres Morales23974272015-05-14 22:42:26 -0700688 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
689 // credential has matched
690 unlockKeystore(credential, userId);
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -0700691
692 // TODO: pass through a meaningful token from gatekeeper to
693 // unlock credential keys; for now pass through a stub value to
694 // indicate that we came from a user challenge.
695 final byte[] token = String.valueOf(userId).getBytes();
696 unlockUser(userId, token);
697
Clara Bayarri56878a92015-10-29 15:43:55 +0000698 UserInfo info = UserManager.get(mContext).getUserInfo(userId);
Clara Bayarria1771112015-12-18 16:29:18 +0000699 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
Clara Bayarri56878a92015-10-29 15:43:55 +0000700 TrustManager trustManager =
701 (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
702 trustManager.setDeviceLockedForUser(userId, false);
703 }
Andres Morales23974272015-05-14 22:42:26 -0700704 if (shouldReEnroll) {
705 credentialUtil.setCredential(credential, credential, userId);
706 }
Adrian Roos873010d2015-08-25 15:59:00 -0700707 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
708 if (response.getTimeout() > 0) {
709 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
710 }
Andres Morales23974272015-05-14 22:42:26 -0700711 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700712
Andres Morales23974272015-05-14 22:42:26 -0700713 return response;
714 }
Andres Moralesd9fc85a2015-04-09 19:14:42 -0700715
Amith Yamasani52c489c2012-03-28 11:42:42 -0700716 @Override
Adrian Roos261d5ab2014-10-29 14:42:38 +0100717 public boolean checkVoldPassword(int userId) throws RemoteException {
Paul Lawrence945490c2014-03-27 16:37:28 +0000718 if (!mFirstCallToVold) {
719 return false;
720 }
721 mFirstCallToVold = false;
722
723 checkPasswordReadPermission(userId);
724
725 // There's no guarantee that this will safely connect, but if it fails
726 // we will simply show the lock screen when we shouldn't, so relatively
727 // benign. There is an outside chance something nasty would happen if
728 // this service restarted before vold stales out the password in this
729 // case. The nastiness is limited to not showing the lock screen when
730 // we should, within the first minute of decrypting the phone if this
731 // service can't connect to vold, it restarts, and then the new instance
732 // does successfully connect.
733 final IMountService service = getMountService();
734 String password = service.getPassword();
735 service.clearPassword();
736 if (password == null) {
737 return false;
738 }
739
740 try {
Adrian Roos9dd16eb2015-01-08 16:20:49 +0100741 if (mLockPatternUtils.isLockPatternEnabled(userId)) {
Andres Morales23974272015-05-14 22:42:26 -0700742 if (checkPattern(password, userId).getResponseCode()
743 == GateKeeperResponse.RESPONSE_OK) {
Paul Lawrence945490c2014-03-27 16:37:28 +0000744 return true;
745 }
746 }
747 } catch (Exception e) {
748 }
749
750 try {
Adrian Roos9dd16eb2015-01-08 16:20:49 +0100751 if (mLockPatternUtils.isLockPasswordEnabled(userId)) {
Andres Morales23974272015-05-14 22:42:26 -0700752 if (checkPassword(password, userId).getResponseCode()
753 == GateKeeperResponse.RESPONSE_OK) {
Paul Lawrence945490c2014-03-27 16:37:28 +0000754 return true;
755 }
756 }
757 } catch (Exception e) {
758 }
759
760 return false;
761 }
762
Adrian Roosdb0f76e2015-01-07 22:19:38 +0100763 private void removeUser(int userId) {
Adrian Roos261d5ab2014-10-29 14:42:38 +0100764 mStorage.removeUser(userId);
Adrian Roosb5e47222015-08-14 15:53:06 -0700765 mStrongAuth.removeUser(userId);
Robin Lee49d810c2014-09-23 13:50:22 +0100766
767 final KeyStore ks = KeyStore.getInstance();
Chad Brubaker83ce0952015-05-12 13:00:02 -0700768 ks.onUserRemoved(userId);
Andres Morales070fe632015-06-24 10:37:10 -0700769
770 try {
771 final IGateKeeperService gk = getGateKeeperService();
772 if (gk != null) {
773 gk.clearSecureUserId(userId);
774 }
775 } catch (RemoteException ex) {
776 Slog.w(TAG, "unable to clear GK secure user id");
777 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700778 }
779
Adrian Roosb5e47222015-08-14 15:53:06 -0700780 @Override
781 public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
782 checkPasswordReadPermission(UserHandle.USER_ALL);
783 mStrongAuth.registerStrongAuthTracker(tracker);
784 }
785
786 @Override
787 public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
788 checkPasswordReadPermission(UserHandle.USER_ALL);
789 mStrongAuth.unregisterStrongAuthTracker(tracker);
790 }
791
792 @Override
793 public void requireStrongAuth(int strongAuthReason, int userId) {
794 checkWritePermission(userId);
795 mStrongAuth.requireStrongAuth(strongAuthReason, userId);
796 }
797
Amith Yamasani52c489c2012-03-28 11:42:42 -0700798 private static final String[] VALID_SETTINGS = new String[] {
799 LockPatternUtils.LOCKOUT_PERMANENT_KEY,
800 LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
801 LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
802 LockPatternUtils.PASSWORD_TYPE_KEY,
803 LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
804 LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
805 LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
806 LockPatternUtils.LOCKSCREEN_OPTIONS,
807 LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
808 LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
809 LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
810 LockPatternUtils.PASSWORD_HISTORY_KEY,
811 Secure.LOCK_PATTERN_ENABLED,
812 Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
813 Secure.LOCK_PATTERN_VISIBLE,
814 Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
Jim Miller187ec582013-04-15 18:27:54 -0700815 };
816
Svetoslav Ganov6d2c0e52015-06-23 16:33:36 +0000817 // Reading these settings needs the contacts permission
818 private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] {
Jim Miller187ec582013-04-15 18:27:54 -0700819 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
820 Secure.LOCK_SCREEN_OWNER_INFO
821 };
Paul Lawrence945490c2014-03-27 16:37:28 +0000822
Adrian Roos001b00d2015-02-24 17:08:48 +0100823 // Reading these settings needs the same permission as checking the password
824 private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] {
825 LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
826 LockPatternUtils.PASSWORD_HISTORY_KEY,
Adrian Roos855fa302015-04-02 16:01:12 +0200827 LockPatternUtils.PASSWORD_TYPE_KEY,
Adrian Roos001b00d2015-02-24 17:08:48 +0100828 };
829
Amith Yamasani072543f2015-02-13 11:09:45 -0800830 private static final String[] SETTINGS_TO_BACKUP = new String[] {
831 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
832 Secure.LOCK_SCREEN_OWNER_INFO
833 };
834
Paul Lawrence945490c2014-03-27 16:37:28 +0000835 private IMountService getMountService() {
836 final IBinder service = ServiceManager.getService("mount");
837 if (service != null) {
838 return IMountService.Stub.asInterface(service);
839 }
840 return null;
841 }
Andres Morales8fa56652015-03-31 09:19:50 -0700842
Andres Morales301ea442015-04-17 09:15:47 -0700843 private class GateKeeperDiedRecipient implements IBinder.DeathRecipient {
844 @Override
845 public void binderDied() {
846 mGateKeeperService.asBinder().unlinkToDeath(this, 0);
847 mGateKeeperService = null;
848 }
849 }
850
851 private synchronized IGateKeeperService getGateKeeperService()
852 throws RemoteException {
Andres Morales8fa56652015-03-31 09:19:50 -0700853 if (mGateKeeperService != null) {
854 return mGateKeeperService;
855 }
856
857 final IBinder service =
858 ServiceManager.getService("android.service.gatekeeper.IGateKeeperService");
859 if (service != null) {
Andres Morales301ea442015-04-17 09:15:47 -0700860 service.linkToDeath(new GateKeeperDiedRecipient(), 0);
Andres Morales8fa56652015-03-31 09:19:50 -0700861 mGateKeeperService = IGateKeeperService.Stub.asInterface(service);
862 return mGateKeeperService;
863 }
864
865 Slog.e(TAG, "Unable to acquire GateKeeperService");
866 return null;
867 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700868}