1 /*
2  * Copyright (C) 2007 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 
17 package com.android.internal.widget;
18 
19 import android.Manifest;
20 import android.app.ActivityManagerNative;
21 import android.app.AlarmManager;
22 import android.app.admin.DevicePolicyManager;
23 import android.app.trust.TrustManager;
24 import android.appwidget.AppWidgetManager;
25 import android.content.ComponentName;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.pm.PackageManager;
30 import android.content.pm.UserInfo;
31 import android.os.AsyncTask;
32 import android.os.IBinder;
33 import android.os.RemoteException;
34 import android.os.ServiceManager;
35 import android.os.SystemClock;
36 import android.os.SystemProperties;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.os.storage.IMountService;
40 import android.os.storage.StorageManager;
41 import android.provider.Settings;
42 import android.telecom.TelecomManager;
43 import android.text.TextUtils;
44 import android.util.Log;
45 import android.view.IWindowManager;
46 import android.view.View;
47 import android.widget.Button;
48 
49 import com.android.internal.R;
50 import com.google.android.collect.Lists;
51 
52 import java.security.MessageDigest;
53 import java.security.NoSuchAlgorithmException;
54 import java.security.SecureRandom;
55 import java.util.ArrayList;
56 import java.util.Collection;
57 import java.util.List;
58 
59 /**
60  * Utilities for the lock pattern and its settings.
61  */
62 public class LockPatternUtils {
63 
64     private static final String TAG = "LockPatternUtils";
65     private static final boolean DEBUG = false;
66 
67     /**
68      * The maximum number of incorrect attempts before the user is prevented
69      * from trying again for {@link #FAILED_ATTEMPT_TIMEOUT_MS}.
70      */
71     public static final int FAILED_ATTEMPTS_BEFORE_TIMEOUT = 5;
72 
73     /**
74      * The number of incorrect attempts before which we fall back on an alternative
75      * method of verifying the user, and resetting their lock pattern.
76      */
77     public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20;
78 
79     /**
80      * How long the user is prevented from trying again after entering the
81      * wrong pattern too many times.
82      */
83     public static final long FAILED_ATTEMPT_TIMEOUT_MS = 30000L;
84 
85     /**
86      * The interval of the countdown for showing progress of the lockout.
87      */
88     public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
89 
90 
91     /**
92      * This dictates when we start telling the user that continued failed attempts will wipe
93      * their device.
94      */
95     public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5;
96 
97     /**
98      * The minimum number of dots in a valid pattern.
99      */
100     public static final int MIN_LOCK_PATTERN_SIZE = 4;
101 
102     /**
103      * The minimum number of dots the user must include in a wrong pattern
104      * attempt for it to be counted against the counts that affect
105      * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET}
106      */
107     public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
108 
109     /**
110      * Tells the keyguard to show the user switcher when the keyguard is created.
111      */
112     public static final String KEYGUARD_SHOW_USER_SWITCHER = "showuserswitcher";
113 
114     /**
115      * Tells the keyguard to show the security challenge when the keyguard is created.
116      */
117     public static final String KEYGUARD_SHOW_SECURITY_CHALLENGE = "showsecuritychallenge";
118 
119     /**
120      * Tells the keyguard to show the widget with the specified id when the keyguard is created.
121      */
122     public static final String KEYGUARD_SHOW_APPWIDGET = "showappwidget";
123 
124     /**
125      * The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should
126      * be used
127      */
128     public static final int FLAG_BIOMETRIC_WEAK_LIVELINESS = 0x1;
129 
130     /**
131      * Pseudo-appwidget id we use to represent the default clock status widget
132      */
133     public static final int ID_DEFAULT_STATUS_WIDGET = -2;
134 
135     public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
136     public final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
137     public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
138     public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
139     public static final String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
140     public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
141     public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
142     public final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
143     public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
144             = "lockscreen.biometric_weak_fallback";
145     public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY
146             = "lockscreen.biometricweakeverchosen";
147     public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
148             = "lockscreen.power_button_instantly_locks";
149     public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled";
150 
151     public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
152 
153     private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO;
154     private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
155             Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
156 
157     private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
158 
159     // Maximum allowed number of repeated or ordered characters in a sequence before we'll
160     // consider it a complex PIN/password.
161     public static final int MAX_ALLOWED_SEQUENCE = 3;
162 
163     private final Context mContext;
164     private final ContentResolver mContentResolver;
165     private DevicePolicyManager mDevicePolicyManager;
166     private ILockSettings mLockSettingsService;
167 
168     private final boolean mMultiUserMode;
169 
170     // The current user is set by KeyguardViewMediator and shared by all LockPatternUtils.
171     private static volatile int sCurrentUserId = UserHandle.USER_NULL;
172 
getDevicePolicyManager()173     public DevicePolicyManager getDevicePolicyManager() {
174         if (mDevicePolicyManager == null) {
175             mDevicePolicyManager =
176                 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
177             if (mDevicePolicyManager == null) {
178                 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
179                         new IllegalStateException("Stack trace:"));
180             }
181         }
182         return mDevicePolicyManager;
183     }
184 
getTrustManager()185     private TrustManager getTrustManager() {
186         TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
187         if (trust == null) {
188             Log.e(TAG, "Can't get TrustManagerService: is it running?",
189                     new IllegalStateException("Stack trace:"));
190         }
191         return trust;
192     }
193 
LockPatternUtils(Context context)194     public LockPatternUtils(Context context) {
195         mContext = context;
196         mContentResolver = context.getContentResolver();
197 
198         // If this is being called by the system or by an application like keyguard that
199         // has permision INTERACT_ACROSS_USERS, then LockPatternUtils will operate in multi-user
200         // mode where calls are for the current user rather than the user of the calling process.
201         mMultiUserMode = context.checkCallingOrSelfPermission(
202             Manifest.permission.INTERACT_ACROSS_USERS_FULL) == PackageManager.PERMISSION_GRANTED;
203     }
204 
getLockSettings()205     private ILockSettings getLockSettings() {
206         if (mLockSettingsService == null) {
207             ILockSettings service = ILockSettings.Stub.asInterface(
208                     ServiceManager.getService("lock_settings"));
209             mLockSettingsService = service;
210         }
211         return mLockSettingsService;
212     }
213 
getRequestedMinimumPasswordLength()214     public int getRequestedMinimumPasswordLength() {
215         return getDevicePolicyManager().getPasswordMinimumLength(null, getCurrentOrCallingUserId());
216     }
217 
218     /**
219      * Gets the device policy password mode. If the mode is non-specific, returns
220      * MODE_PATTERN which allows the user to choose anything.
221      */
getRequestedPasswordQuality()222     public int getRequestedPasswordQuality() {
223         return getDevicePolicyManager().getPasswordQuality(null, getCurrentOrCallingUserId());
224     }
225 
getRequestedPasswordHistoryLength()226     public int getRequestedPasswordHistoryLength() {
227         return getDevicePolicyManager().getPasswordHistoryLength(null, getCurrentOrCallingUserId());
228     }
229 
getRequestedPasswordMinimumLetters()230     public int getRequestedPasswordMinimumLetters() {
231         return getDevicePolicyManager().getPasswordMinimumLetters(null,
232                 getCurrentOrCallingUserId());
233     }
234 
getRequestedPasswordMinimumUpperCase()235     public int getRequestedPasswordMinimumUpperCase() {
236         return getDevicePolicyManager().getPasswordMinimumUpperCase(null,
237                 getCurrentOrCallingUserId());
238     }
239 
getRequestedPasswordMinimumLowerCase()240     public int getRequestedPasswordMinimumLowerCase() {
241         return getDevicePolicyManager().getPasswordMinimumLowerCase(null,
242                 getCurrentOrCallingUserId());
243     }
244 
getRequestedPasswordMinimumNumeric()245     public int getRequestedPasswordMinimumNumeric() {
246         return getDevicePolicyManager().getPasswordMinimumNumeric(null,
247                 getCurrentOrCallingUserId());
248     }
249 
getRequestedPasswordMinimumSymbols()250     public int getRequestedPasswordMinimumSymbols() {
251         return getDevicePolicyManager().getPasswordMinimumSymbols(null,
252                 getCurrentOrCallingUserId());
253     }
254 
getRequestedPasswordMinimumNonLetter()255     public int getRequestedPasswordMinimumNonLetter() {
256         return getDevicePolicyManager().getPasswordMinimumNonLetter(null,
257                 getCurrentOrCallingUserId());
258     }
259 
reportFailedPasswordAttempt()260     public void reportFailedPasswordAttempt() {
261         int userId = getCurrentOrCallingUserId();
262         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
263         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
264         getTrustManager().reportRequireCredentialEntry(userId);
265     }
266 
reportSuccessfulPasswordAttempt()267     public void reportSuccessfulPasswordAttempt() {
268         getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId());
269         getTrustManager().reportUnlockAttempt(true /* authenticated */,
270                 getCurrentOrCallingUserId());
271     }
272 
setCurrentUser(int userId)273     public void setCurrentUser(int userId) {
274         sCurrentUserId = userId;
275     }
276 
getCurrentUser()277     public int getCurrentUser() {
278         if (sCurrentUserId != UserHandle.USER_NULL) {
279             // Someone is regularly updating using setCurrentUser() use that value.
280             return sCurrentUserId;
281         }
282         try {
283             return ActivityManagerNative.getDefault().getCurrentUser().id;
284         } catch (RemoteException re) {
285             return UserHandle.USER_OWNER;
286         }
287     }
288 
removeUser(int userId)289     public void removeUser(int userId) {
290         try {
291             getLockSettings().removeUser(userId);
292         } catch (RemoteException re) {
293             Log.e(TAG, "Couldn't remove lock settings for user " + userId);
294         }
295     }
296 
getCurrentOrCallingUserId()297     private int getCurrentOrCallingUserId() {
298         if (mMultiUserMode) {
299             // TODO: This is a little inefficient. See if all users of this are able to
300             // handle USER_CURRENT and pass that instead.
301             return getCurrentUser();
302         } else {
303             return UserHandle.getCallingUserId();
304         }
305     }
306 
307     /**
308      * Check to see if a pattern matches the saved pattern.  If no pattern exists,
309      * always returns true.
310      * @param pattern The pattern to check.
311      * @return Whether the pattern matches the stored one.
312      */
checkPattern(List<LockPatternView.Cell> pattern)313     public boolean checkPattern(List<LockPatternView.Cell> pattern) {
314         final int userId = getCurrentOrCallingUserId();
315         try {
316             return getLockSettings().checkPattern(patternToString(pattern), userId);
317         } catch (RemoteException re) {
318             return true;
319         }
320     }
321 
322     /**
323      * Check to see if a password matches the saved password.  If no password exists,
324      * always returns true.
325      * @param password The password to check.
326      * @return Whether the password matches the stored one.
327      */
checkPassword(String password)328     public boolean checkPassword(String password) {
329         final int userId = getCurrentOrCallingUserId();
330         try {
331             return getLockSettings().checkPassword(password, userId);
332         } catch (RemoteException re) {
333             return true;
334         }
335     }
336 
337     /**
338      * Check to see if vold already has the password.
339      * Note that this also clears vold's copy of the password.
340      * @return Whether the vold password matches or not.
341      */
checkVoldPassword()342     public boolean checkVoldPassword() {
343         final int userId = getCurrentOrCallingUserId();
344         try {
345             return getLockSettings().checkVoldPassword(userId);
346         } catch (RemoteException re) {
347             return false;
348         }
349     }
350 
351     /**
352      * Check to see if a password matches any of the passwords stored in the
353      * password history.
354      *
355      * @param password The password to check.
356      * @return Whether the password matches any in the history.
357      */
checkPasswordHistory(String password)358     public boolean checkPasswordHistory(String password) {
359         String passwordHashString = new String(
360                 passwordToHash(password, getCurrentOrCallingUserId()));
361         String passwordHistory = getString(PASSWORD_HISTORY_KEY);
362         if (passwordHistory == null) {
363             return false;
364         }
365         // Password History may be too long...
366         int passwordHashLength = passwordHashString.length();
367         int passwordHistoryLength = getRequestedPasswordHistoryLength();
368         if(passwordHistoryLength == 0) {
369             return false;
370         }
371         int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength
372                 + passwordHistoryLength - 1;
373         if (passwordHistory.length() > neededPasswordHistoryLength) {
374             passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength);
375         }
376         return passwordHistory.contains(passwordHashString);
377     }
378 
379     /**
380      * Check to see if the user has stored a lock pattern.
381      * @return Whether a saved pattern exists.
382      */
savedPatternExists()383     public boolean savedPatternExists() {
384         return savedPatternExists(getCurrentOrCallingUserId());
385     }
386 
387     /**
388      * Check to see if the user has stored a lock pattern.
389      * @return Whether a saved pattern exists.
390      */
savedPatternExists(int userId)391     public boolean savedPatternExists(int userId) {
392         try {
393             return getLockSettings().havePattern(userId);
394         } catch (RemoteException re) {
395             return false;
396         }
397     }
398 
399     /**
400      * Check to see if the user has stored a lock pattern.
401      * @return Whether a saved pattern exists.
402      */
savedPasswordExists()403     public boolean savedPasswordExists() {
404         return savedPasswordExists(getCurrentOrCallingUserId());
405     }
406 
407      /**
408      * Check to see if the user has stored a lock pattern.
409      * @return Whether a saved pattern exists.
410      */
savedPasswordExists(int userId)411     public boolean savedPasswordExists(int userId) {
412         try {
413             return getLockSettings().havePassword(userId);
414         } catch (RemoteException re) {
415             return false;
416         }
417     }
418 
419     /**
420      * Return true if the user has ever chosen a pattern.  This is true even if the pattern is
421      * currently cleared.
422      *
423      * @return True if the user has ever chosen a pattern.
424      */
isPatternEverChosen()425     public boolean isPatternEverChosen() {
426         return getBoolean(PATTERN_EVER_CHOSEN_KEY, false);
427     }
428 
429     /**
430      * Return true if the user has ever chosen biometric weak.  This is true even if biometric
431      * weak is not current set.
432      *
433      * @return True if the user has ever chosen biometric weak.
434      */
isBiometricWeakEverChosen()435     public boolean isBiometricWeakEverChosen() {
436         return getBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, false);
437     }
438 
439     /**
440      * Used by device policy manager to validate the current password
441      * information it has.
442      */
getActivePasswordQuality()443     public int getActivePasswordQuality() {
444         int activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
445         // Note we don't want to use getKeyguardStoredPasswordQuality() because we want this to
446         // return biometric_weak if that is being used instead of the backup
447         int quality =
448                 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
449         switch (quality) {
450             case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
451                 if (isLockPatternEnabled()) {
452                     activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
453                 }
454                 break;
455             case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
456                 if (isBiometricWeakInstalled()) {
457                     activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
458                 }
459                 break;
460             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
461                 if (isLockPasswordEnabled()) {
462                     activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
463                 }
464                 break;
465             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
466                 if (isLockPasswordEnabled()) {
467                     activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
468                 }
469                 break;
470             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
471                 if (isLockPasswordEnabled()) {
472                     activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
473                 }
474                 break;
475             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
476                 if (isLockPasswordEnabled()) {
477                     activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
478                 }
479                 break;
480             case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
481                 if (isLockPasswordEnabled()) {
482                     activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
483                 }
484                 break;
485         }
486 
487         return activePasswordQuality;
488     }
489 
clearLock(boolean isFallback)490     public void clearLock(boolean isFallback) {
491         clearLock(isFallback, getCurrentOrCallingUserId());
492     }
493 
494     /**
495      * Clear any lock pattern or password.
496      */
clearLock(boolean isFallback, int userHandle)497     public void clearLock(boolean isFallback, int userHandle) {
498         if(!isFallback) deleteGallery(userHandle);
499         saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, isFallback,
500                 userHandle);
501         setLockPatternEnabled(false, userHandle);
502         saveLockPattern(null, isFallback, userHandle);
503         setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
504         setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
505                 userHandle);
506         onAfterChangingPassword(userHandle);
507     }
508 
509     /**
510      * Disable showing lock screen at all when the DevicePolicyManager allows it.
511      * This is only meaningful if pattern, pin or password are not set.
512      *
513      * @param disable Disables lock screen when true
514      */
setLockScreenDisabled(boolean disable)515     public void setLockScreenDisabled(boolean disable) {
516         setLong(DISABLE_LOCKSCREEN_KEY, disable ? 1 : 0);
517     }
518 
519     /**
520      * Determine if LockScreen can be disabled. This is used, for example, to tell if we should
521      * show LockScreen or go straight to the home screen.
522      *
523      * @return true if lock screen is can be disabled
524      */
isLockScreenDisabled()525     public boolean isLockScreenDisabled() {
526         if (!isSecure() && getLong(DISABLE_LOCKSCREEN_KEY, 0) != 0) {
527             // Check if the number of switchable users forces the lockscreen.
528             final List<UserInfo> users = UserManager.get(mContext).getUsers(true);
529             final int userCount = users.size();
530             int switchableUsers = 0;
531             for (int i = 0; i < userCount; i++) {
532                 if (users.get(i).supportsSwitchTo()) {
533                     switchableUsers++;
534                 }
535             }
536             return switchableUsers < 2;
537         }
538         return false;
539     }
540 
541     /**
542      * Calls back SetupFaceLock to delete the temporary gallery file
543      */
deleteTempGallery()544     public void deleteTempGallery() {
545         Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY");
546         intent.putExtra("deleteTempGallery", true);
547         mContext.sendBroadcast(intent);
548     }
549 
550     /**
551      * Calls back SetupFaceLock to delete the gallery file when the lock type is changed
552     */
deleteGallery(int userId)553     void deleteGallery(int userId) {
554         if(usingBiometricWeak(userId)) {
555             Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY");
556             intent.putExtra("deleteGallery", true);
557             mContext.sendBroadcastAsUser(intent, new UserHandle(userId));
558         }
559     }
560 
561     /**
562      * Save a lock pattern.
563      * @param pattern The new pattern to save.
564      */
saveLockPattern(List<LockPatternView.Cell> pattern)565     public void saveLockPattern(List<LockPatternView.Cell> pattern) {
566         this.saveLockPattern(pattern, false);
567     }
568 
569     /**
570      * Save a lock pattern.
571      * @param pattern The new pattern to save.
572      */
saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback)573     public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) {
574         this.saveLockPattern(pattern, isFallback, getCurrentOrCallingUserId());
575     }
576 
577     /**
578      * Save a lock pattern.
579      * @param pattern The new pattern to save.
580      * @param isFallback Specifies if this is a fallback to biometric weak
581      * @param userId the user whose pattern is to be saved.
582      */
saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback, int userId)583     public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback,
584             int userId) {
585         try {
586             getLockSettings().setLockPattern(patternToString(pattern), userId);
587             DevicePolicyManager dpm = getDevicePolicyManager();
588             if (pattern != null) {
589                 // Update the device encryption password.
590                 if (userId == UserHandle.USER_OWNER
591                         && LockPatternUtils.isDeviceEncryptionEnabled()) {
592                     final boolean required = isCredentialRequiredToDecrypt(true);
593                     if (!required) {
594                         clearEncryptionPassword();
595                     } else {
596                         String stringPattern = patternToString(pattern);
597                         updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
598                     }
599                 }
600 
601                 setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
602                 if (!isFallback) {
603                     deleteGallery(userId);
604                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
605                     dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
606                             pattern.size(), 0, 0, 0, 0, 0, 0, userId);
607                 } else {
608                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, userId);
609                     setLong(PASSWORD_TYPE_ALTERNATE_KEY,
610                             DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
611                     finishBiometricWeak(userId);
612                     dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
613                             0, 0, 0, 0, 0, 0, 0, userId);
614                 }
615             } else {
616                 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
617                         0, 0, 0, 0, 0, userId);
618             }
619             onAfterChangingPassword(userId);
620         } catch (RemoteException re) {
621             Log.e(TAG, "Couldn't save lock pattern " + re);
622         }
623     }
624 
updateCryptoUserInfo()625     private void updateCryptoUserInfo() {
626         int userId = getCurrentOrCallingUserId();
627         if (userId != UserHandle.USER_OWNER) {
628             return;
629         }
630 
631         final String ownerInfo = isOwnerInfoEnabled() ? getOwnerInfo(userId) : "";
632 
633         IBinder service = ServiceManager.getService("mount");
634         if (service == null) {
635             Log.e(TAG, "Could not find the mount service to update the user info");
636             return;
637         }
638 
639         IMountService mountService = IMountService.Stub.asInterface(service);
640         try {
641             Log.d(TAG, "Setting owner info");
642             mountService.setField(StorageManager.OWNER_INFO_KEY, ownerInfo);
643         } catch (RemoteException e) {
644             Log.e(TAG, "Error changing user info", e);
645         }
646     }
647 
setOwnerInfo(String info, int userId)648     public void setOwnerInfo(String info, int userId) {
649         setString(LOCK_SCREEN_OWNER_INFO, info, userId);
650         updateCryptoUserInfo();
651     }
652 
setOwnerInfoEnabled(boolean enabled)653     public void setOwnerInfoEnabled(boolean enabled) {
654         setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled);
655         updateCryptoUserInfo();
656     }
657 
getOwnerInfo(int userId)658     public String getOwnerInfo(int userId) {
659         return getString(LOCK_SCREEN_OWNER_INFO);
660     }
661 
isOwnerInfoEnabled()662     public boolean isOwnerInfoEnabled() {
663         return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false);
664     }
665 
666     /**
667      * Compute the password quality from the given password string.
668      */
computePasswordQuality(String password)669     static public int computePasswordQuality(String password) {
670         boolean hasDigit = false;
671         boolean hasNonDigit = false;
672         final int len = password.length();
673         for (int i = 0; i < len; i++) {
674             if (Character.isDigit(password.charAt(i))) {
675                 hasDigit = true;
676             } else {
677                 hasNonDigit = true;
678             }
679         }
680 
681         if (hasNonDigit && hasDigit) {
682             return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
683         }
684         if (hasNonDigit) {
685             return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
686         }
687         if (hasDigit) {
688             return maxLengthSequence(password) > MAX_ALLOWED_SEQUENCE
689                     ? DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
690                     : DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
691         }
692         return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
693     }
694 
categoryChar(char c)695     private static int categoryChar(char c) {
696         if ('a' <= c && c <= 'z') return 0;
697         if ('A' <= c && c <= 'Z') return 1;
698         if ('0' <= c && c <= '9') return 2;
699         return 3;
700     }
701 
maxDiffCategory(int category)702     private static int maxDiffCategory(int category) {
703         if (category == 0 || category == 1) return 1;
704         else if (category == 2) return 10;
705         return 0;
706     }
707 
708     /*
709      * Returns the maximum length of a sequential characters.  A sequence is defined as
710      * monotonically increasing characters with a constant interval or the same character repeated.
711      *
712      * For example:
713      * maxLengthSequence("1234") == 4
714      * maxLengthSequence("1234abc") == 4
715      * maxLengthSequence("aabc") == 3
716      * maxLengthSequence("qwertyuio") == 1
717      * maxLengthSequence("@ABC") == 3
718      * maxLengthSequence(";;;;") == 4 (anything that repeats)
719      * maxLengthSequence(":;<=>") == 1  (ordered, but not composed of alphas or digits)
720      *
721      * @param string the pass
722      * @return the number of sequential letters or digits
723      */
maxLengthSequence(String string)724     public static int maxLengthSequence(String string) {
725         if (string.length() == 0) return 0;
726         char previousChar = string.charAt(0);
727         int category = categoryChar(previousChar); //current category of the sequence
728         int diff = 0; //difference between two consecutive characters
729         boolean hasDiff = false; //if we are currently targeting a sequence
730         int maxLength = 0; //maximum length of a sequence already found
731         int startSequence = 0; //where the current sequence started
732         for (int current = 1; current < string.length(); current++) {
733             char currentChar = string.charAt(current);
734             int categoryCurrent = categoryChar(currentChar);
735             int currentDiff = (int) currentChar - (int) previousChar;
736             if (categoryCurrent != category || Math.abs(currentDiff) > maxDiffCategory(category)) {
737                 maxLength = Math.max(maxLength, current - startSequence);
738                 startSequence = current;
739                 hasDiff = false;
740                 category = categoryCurrent;
741             }
742             else {
743                 if(hasDiff && currentDiff != diff) {
744                     maxLength = Math.max(maxLength, current - startSequence);
745                     startSequence = current - 1;
746                 }
747                 diff = currentDiff;
748                 hasDiff = true;
749             }
750             previousChar = currentChar;
751         }
752         maxLength = Math.max(maxLength, string.length() - startSequence);
753         return maxLength;
754     }
755 
756     /** Update the encryption password if it is enabled **/
updateEncryptionPassword(final int type, final String password)757     private void updateEncryptionPassword(final int type, final String password) {
758         if (!isDeviceEncryptionEnabled()) {
759             return;
760         }
761         final IBinder service = ServiceManager.getService("mount");
762         if (service == null) {
763             Log.e(TAG, "Could not find the mount service to update the encryption password");
764             return;
765         }
766 
767         new AsyncTask<Void, Void, Void>() {
768             @Override
769             protected Void doInBackground(Void... dummy) {
770                 IMountService mountService = IMountService.Stub.asInterface(service);
771                 try {
772                     mountService.changeEncryptionPassword(type, password);
773                 } catch (RemoteException e) {
774                     Log.e(TAG, "Error changing encryption password", e);
775                 }
776                 return null;
777             }
778         }.execute();
779     }
780 
781     /**
782      * Save a lock password.  Does not ensure that the password is as good
783      * as the requested mode, but will adjust the mode to be as good as the
784      * pattern.
785      * @param password The password to save
786      * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
787      */
saveLockPassword(String password, int quality)788     public void saveLockPassword(String password, int quality) {
789         this.saveLockPassword(password, quality, false, getCurrentOrCallingUserId());
790     }
791 
792     /**
793      * Save a lock password.  Does not ensure that the password is as good
794      * as the requested mode, but will adjust the mode to be as good as the
795      * pattern.
796      * @param password The password to save
797      * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
798      * @param isFallback Specifies if this is a fallback to biometric weak
799      */
saveLockPassword(String password, int quality, boolean isFallback)800     public void saveLockPassword(String password, int quality, boolean isFallback) {
801         saveLockPassword(password, quality, isFallback, getCurrentOrCallingUserId());
802     }
803 
804     /**
805      * Save a lock password.  Does not ensure that the password is as good
806      * as the requested mode, but will adjust the mode to be as good as the
807      * pattern.
808      * @param password The password to save
809      * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
810      * @param isFallback Specifies if this is a fallback to biometric weak
811      * @param userHandle The userId of the user to change the password for
812      */
saveLockPassword(String password, int quality, boolean isFallback, int userHandle)813     public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) {
814         try {
815             DevicePolicyManager dpm = getDevicePolicyManager();
816             if (!TextUtils.isEmpty(password)) {
817                 getLockSettings().setLockPassword(password, userHandle);
818                 int computedQuality = computePasswordQuality(password);
819 
820                 // Update the device encryption password.
821                 if (userHandle == UserHandle.USER_OWNER
822                         && LockPatternUtils.isDeviceEncryptionEnabled()) {
823                     if (!isCredentialRequiredToDecrypt(true)) {
824                         clearEncryptionPassword();
825                     } else {
826                         boolean numeric = computedQuality
827                                 == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
828                         boolean numericComplex = computedQuality
829                                 == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
830                         int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
831                                 : StorageManager.CRYPT_TYPE_PASSWORD;
832                         updateEncryptionPassword(type, password);
833                     }
834                 }
835 
836                 if (!isFallback) {
837                     deleteGallery(userHandle);
838                     setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
839                     if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
840                         int letters = 0;
841                         int uppercase = 0;
842                         int lowercase = 0;
843                         int numbers = 0;
844                         int symbols = 0;
845                         int nonletter = 0;
846                         for (int i = 0; i < password.length(); i++) {
847                             char c = password.charAt(i);
848                             if (c >= 'A' && c <= 'Z') {
849                                 letters++;
850                                 uppercase++;
851                             } else if (c >= 'a' && c <= 'z') {
852                                 letters++;
853                                 lowercase++;
854                             } else if (c >= '0' && c <= '9') {
855                                 numbers++;
856                                 nonletter++;
857                             } else {
858                                 symbols++;
859                                 nonletter++;
860                             }
861                         }
862                         dpm.setActivePasswordState(Math.max(quality, computedQuality),
863                                 password.length(), letters, uppercase, lowercase,
864                                 numbers, symbols, nonletter, userHandle);
865                     } else {
866                         // The password is not anything.
867                         dpm.setActivePasswordState(
868                                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
869                                 0, 0, 0, 0, 0, 0, 0, userHandle);
870                     }
871                 } else {
872                     // Case where it's a fallback for biometric weak
873                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
874                             userHandle);
875                     setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality),
876                             userHandle);
877                     finishBiometricWeak(userHandle);
878                     dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
879                             0, 0, 0, 0, 0, 0, 0, userHandle);
880                 }
881                 // Add the password to the password history. We assume all
882                 // password hashes have the same length for simplicity of implementation.
883                 String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
884                 if (passwordHistory == null) {
885                     passwordHistory = "";
886                 }
887                 int passwordHistoryLength = getRequestedPasswordHistoryLength();
888                 if (passwordHistoryLength == 0) {
889                     passwordHistory = "";
890                 } else {
891                     byte[] hash = passwordToHash(password, userHandle);
892                     passwordHistory = new String(hash) + "," + passwordHistory;
893                     // Cut it to contain passwordHistoryLength hashes
894                     // and passwordHistoryLength -1 commas.
895                     passwordHistory = passwordHistory.substring(0, Math.min(hash.length
896                             * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
897                             .length()));
898                 }
899                 setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
900             } else {
901                 // Empty password
902                 getLockSettings().setLockPassword(null, userHandle);
903                 if (userHandle == UserHandle.USER_OWNER) {
904                     // Set the encryption password to default.
905                     updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
906                 }
907 
908                 dpm.setActivePasswordState(
909                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0,
910                         userHandle);
911             }
912             onAfterChangingPassword(userHandle);
913         } catch (RemoteException re) {
914             // Cant do much
915             Log.e(TAG, "Unable to save lock password " + re);
916         }
917     }
918 
919     /**
920      * Gets whether the device is encrypted.
921      *
922      * @return Whether the device is encrypted.
923      */
isDeviceEncrypted()924     public static boolean isDeviceEncrypted() {
925         IMountService mountService = IMountService.Stub.asInterface(
926                 ServiceManager.getService("mount"));
927         try {
928             return mountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE
929                     && mountService.getPasswordType() != StorageManager.CRYPT_TYPE_DEFAULT;
930         } catch (RemoteException re) {
931             Log.e(TAG, "Error getting encryption state", re);
932         }
933         return true;
934     }
935 
936     /**
937      * Determine if the device supports encryption, even if it's set to default. This
938      * differs from isDeviceEncrypted() in that it returns true even if the device is
939      * encrypted with the default password.
940      * @return true if device encryption is enabled
941      */
isDeviceEncryptionEnabled()942     public static boolean isDeviceEncryptionEnabled() {
943         final String status = SystemProperties.get("ro.crypto.state", "unsupported");
944         return "encrypted".equalsIgnoreCase(status);
945     }
946 
947     /**
948      * Clears the encryption password.
949      */
clearEncryptionPassword()950     public void clearEncryptionPassword() {
951         updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
952     }
953 
954     /**
955      * Retrieves the quality mode we're in.
956      * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
957      *
958      * @return stored password quality
959      */
getKeyguardStoredPasswordQuality()960     public int getKeyguardStoredPasswordQuality() {
961         return getKeyguardStoredPasswordQuality(getCurrentOrCallingUserId());
962     }
963 
964     /**
965      * Retrieves the quality mode for {@param userHandle}.
966      * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
967      *
968      * @return stored password quality
969      */
getKeyguardStoredPasswordQuality(int userHandle)970     public int getKeyguardStoredPasswordQuality(int userHandle) {
971         int quality = (int) getLong(PASSWORD_TYPE_KEY,
972                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
973         // If the user has chosen to use weak biometric sensor, then return the backup locking
974         // method and treat biometric as a special case.
975         if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
976             quality = (int) getLong(PASSWORD_TYPE_ALTERNATE_KEY,
977                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
978         }
979         return quality;
980     }
981 
982     /**
983      * @return true if the lockscreen method is set to biometric weak
984      */
usingBiometricWeak()985     public boolean usingBiometricWeak() {
986         return usingBiometricWeak(getCurrentOrCallingUserId());
987     }
988 
989     /**
990      * @return true if the lockscreen method is set to biometric weak
991      */
usingBiometricWeak(int userId)992     public boolean usingBiometricWeak(int userId) {
993         int quality = (int) getLong(
994                 PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
995         return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
996     }
997 
998     /**
999      * Deserialize a pattern.
1000      * @param string The pattern serialized with {@link #patternToString}
1001      * @return The pattern.
1002      */
stringToPattern(String string)1003     public static List<LockPatternView.Cell> stringToPattern(String string) {
1004         List<LockPatternView.Cell> result = Lists.newArrayList();
1005 
1006         final byte[] bytes = string.getBytes();
1007         for (int i = 0; i < bytes.length; i++) {
1008             byte b = bytes[i];
1009             result.add(LockPatternView.Cell.of(b / 3, b % 3));
1010         }
1011         return result;
1012     }
1013 
1014     /**
1015      * Serialize a pattern.
1016      * @param pattern The pattern.
1017      * @return The pattern in string form.
1018      */
patternToString(List<LockPatternView.Cell> pattern)1019     public static String patternToString(List<LockPatternView.Cell> pattern) {
1020         if (pattern == null) {
1021             return "";
1022         }
1023         final int patternSize = pattern.size();
1024 
1025         byte[] res = new byte[patternSize];
1026         for (int i = 0; i < patternSize; i++) {
1027             LockPatternView.Cell cell = pattern.get(i);
1028             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
1029         }
1030         return new String(res);
1031     }
1032 
1033     /*
1034      * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
1035      * at least a second level of protection. First level is that the file
1036      * is in a location only readable by the system process.
1037      * @param pattern the gesture pattern.
1038      * @return the hash of the pattern in a byte array.
1039      */
patternToHash(List<LockPatternView.Cell> pattern)1040     public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
1041         if (pattern == null) {
1042             return null;
1043         }
1044 
1045         final int patternSize = pattern.size();
1046         byte[] res = new byte[patternSize];
1047         for (int i = 0; i < patternSize; i++) {
1048             LockPatternView.Cell cell = pattern.get(i);
1049             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
1050         }
1051         try {
1052             MessageDigest md = MessageDigest.getInstance("SHA-1");
1053             byte[] hash = md.digest(res);
1054             return hash;
1055         } catch (NoSuchAlgorithmException nsa) {
1056             return res;
1057         }
1058     }
1059 
getSalt(int userId)1060     private String getSalt(int userId) {
1061         long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);
1062         if (salt == 0) {
1063             try {
1064                 salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
1065                 setLong(LOCK_PASSWORD_SALT_KEY, salt, userId);
1066                 Log.v(TAG, "Initialized lock password salt for user: " + userId);
1067             } catch (NoSuchAlgorithmException e) {
1068                 // Throw an exception rather than storing a password we'll never be able to recover
1069                 throw new IllegalStateException("Couldn't get SecureRandom number", e);
1070             }
1071         }
1072         return Long.toHexString(salt);
1073     }
1074 
1075     /*
1076      * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
1077      * Not the most secure, but it is at least a second level of protection. First level is that
1078      * the file is in a location only readable by the system process.
1079      * @param password the gesture pattern.
1080      * @return the hash of the pattern in a byte array.
1081      */
passwordToHash(String password, int userId)1082     public byte[] passwordToHash(String password, int userId) {
1083         if (password == null) {
1084             return null;
1085         }
1086         String algo = null;
1087         byte[] hashed = null;
1088         try {
1089             byte[] saltedPassword = (password + getSalt(userId)).getBytes();
1090             byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
1091             byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
1092             hashed = (toHex(sha1) + toHex(md5)).getBytes();
1093         } catch (NoSuchAlgorithmException e) {
1094             Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo);
1095         }
1096         return hashed;
1097     }
1098 
toHex(byte[] ary)1099     private static String toHex(byte[] ary) {
1100         final String hex = "0123456789ABCDEF";
1101         String ret = "";
1102         for (int i = 0; i < ary.length; i++) {
1103             ret += hex.charAt((ary[i] >> 4) & 0xf);
1104             ret += hex.charAt(ary[i] & 0xf);
1105         }
1106         return ret;
1107     }
1108 
1109     /**
1110      * @return Whether the lock password is enabled, or if it is set as a backup for biometric weak
1111      */
isLockPasswordEnabled()1112     public boolean isLockPasswordEnabled() {
1113         long mode = getLong(PASSWORD_TYPE_KEY, 0);
1114         long backupMode = getLong(PASSWORD_TYPE_ALTERNATE_KEY, 0);
1115         final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
1116                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
1117                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
1118                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1119                 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
1120         final boolean backupEnabled = backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
1121                 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
1122                 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
1123                 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1124                 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
1125 
1126         return savedPasswordExists() && (passwordEnabled ||
1127                 (usingBiometricWeak() && backupEnabled));
1128     }
1129 
1130     /**
1131      * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak
1132      */
isLockPatternEnabled()1133     public boolean isLockPatternEnabled() {
1134         return isLockPatternEnabled(getCurrentOrCallingUserId());
1135     }
1136 
1137     /**
1138      * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak
1139      */
isLockPatternEnabled(int userId)1140     public boolean isLockPatternEnabled(int userId) {
1141         final boolean backupEnabled =
1142                 getLong(PASSWORD_TYPE_ALTERNATE_KEY,
1143                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId)
1144                                 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
1145 
1146         return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false, userId)
1147                 && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
1148                         userId) == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
1149                         || (usingBiometricWeak(userId) && backupEnabled));
1150     }
1151 
1152     /**
1153      * @return Whether biometric weak lock is installed and that the front facing camera exists
1154      */
isBiometricWeakInstalled()1155     public boolean isBiometricWeakInstalled() {
1156         // Check that it's installed
1157         PackageManager pm = mContext.getPackageManager();
1158         try {
1159             pm.getPackageInfo("com.android.facelock", PackageManager.GET_ACTIVITIES);
1160         } catch (PackageManager.NameNotFoundException e) {
1161             return false;
1162         }
1163 
1164         // Check that the camera is enabled
1165         if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
1166             return false;
1167         }
1168         if (getDevicePolicyManager().getCameraDisabled(null, getCurrentOrCallingUserId())) {
1169             return false;
1170         }
1171 
1172         // TODO: If we decide not to proceed with Face Unlock as a trustlet, this must be changed
1173         // back to returning true.  If we become certain that Face Unlock will be a trustlet, this
1174         // entire function and a lot of other code can be removed.
1175         if (DEBUG) Log.d(TAG, "Forcing isBiometricWeakInstalled() to return false to disable it");
1176         return false;
1177     }
1178 
1179     /**
1180      * Set whether biometric weak liveliness is enabled.
1181      */
setBiometricWeakLivelinessEnabled(boolean enabled)1182     public void setBiometricWeakLivelinessEnabled(boolean enabled) {
1183         long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L);
1184         long newFlag;
1185         if (enabled) {
1186             newFlag = currentFlag | FLAG_BIOMETRIC_WEAK_LIVELINESS;
1187         } else {
1188             newFlag = currentFlag & ~FLAG_BIOMETRIC_WEAK_LIVELINESS;
1189         }
1190         setLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, newFlag);
1191     }
1192 
1193     /**
1194      * @return Whether the biometric weak liveliness is enabled.
1195      */
isBiometricWeakLivelinessEnabled()1196     public boolean isBiometricWeakLivelinessEnabled() {
1197         long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L);
1198         return ((currentFlag & FLAG_BIOMETRIC_WEAK_LIVELINESS) != 0);
1199     }
1200 
1201     /**
1202      * Set whether the lock pattern is enabled.
1203      */
setLockPatternEnabled(boolean enabled)1204     public void setLockPatternEnabled(boolean enabled) {
1205         setLockPatternEnabled(enabled, getCurrentOrCallingUserId());
1206     }
1207 
1208     /**
1209      * Set whether the lock pattern is enabled.
1210      */
setLockPatternEnabled(boolean enabled, int userHandle)1211     public void setLockPatternEnabled(boolean enabled, int userHandle) {
1212         setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, enabled, userHandle);
1213     }
1214 
1215     /**
1216      * @return Whether the visible pattern is enabled.
1217      */
isVisiblePatternEnabled()1218     public boolean isVisiblePatternEnabled() {
1219         return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false);
1220     }
1221 
1222     /**
1223      * Set whether the visible pattern is enabled.
1224      */
setVisiblePatternEnabled(boolean enabled)1225     public void setVisiblePatternEnabled(boolean enabled) {
1226         setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled);
1227 
1228         // Update for crypto if owner
1229         int userId = getCurrentOrCallingUserId();
1230         if (userId != UserHandle.USER_OWNER) {
1231             return;
1232         }
1233 
1234         IBinder service = ServiceManager.getService("mount");
1235         if (service == null) {
1236             Log.e(TAG, "Could not find the mount service to update the user info");
1237             return;
1238         }
1239 
1240         IMountService mountService = IMountService.Stub.asInterface(service);
1241         try {
1242             mountService.setField(StorageManager.PATTERN_VISIBLE_KEY, enabled ? "1" : "0");
1243         } catch (RemoteException e) {
1244             Log.e(TAG, "Error changing pattern visible state", e);
1245         }
1246     }
1247 
1248     /**
1249      * @return Whether tactile feedback for the pattern is enabled.
1250      */
isTactileFeedbackEnabled()1251     public boolean isTactileFeedbackEnabled() {
1252         return Settings.System.getIntForUser(mContentResolver,
1253                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
1254     }
1255 
1256     /**
1257      * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
1258      * pattern until the deadline has passed.
1259      * @return the chosen deadline.
1260      */
setLockoutAttemptDeadline()1261     public long setLockoutAttemptDeadline() {
1262         final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS;
1263         setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline);
1264         return deadline;
1265     }
1266 
1267     /**
1268      * @return The elapsed time in millis in the future when the user is allowed to
1269      *   attempt to enter his/her lock pattern, or 0 if the user is welcome to
1270      *   enter a pattern.
1271      */
getLockoutAttemptDeadline()1272     public long getLockoutAttemptDeadline() {
1273         final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L);
1274         final long now = SystemClock.elapsedRealtime();
1275         if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) {
1276             return 0L;
1277         }
1278         return deadline;
1279     }
1280 
1281     /**
1282      * @return Whether the user is permanently locked out until they verify their
1283      *   credentials.  Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed
1284      *   attempts.
1285      */
isPermanentlyLocked()1286     public boolean isPermanentlyLocked() {
1287         return getBoolean(LOCKOUT_PERMANENT_KEY, false);
1288     }
1289 
1290     /**
1291      * Set the state of whether the device is permanently locked, meaning the user
1292      * must authenticate via other means.
1293      *
1294      * @param locked Whether the user is permanently locked out until they verify their
1295      *   credentials.  Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed
1296      *   attempts.
1297      */
setPermanentlyLocked(boolean locked)1298     public void setPermanentlyLocked(boolean locked) {
1299         setBoolean(LOCKOUT_PERMANENT_KEY, locked);
1300     }
1301 
isEmergencyCallCapable()1302     public boolean isEmergencyCallCapable() {
1303         return mContext.getResources().getBoolean(
1304                 com.android.internal.R.bool.config_voice_capable);
1305     }
1306 
isPukUnlockScreenEnable()1307     public boolean isPukUnlockScreenEnable() {
1308         return mContext.getResources().getBoolean(
1309                 com.android.internal.R.bool.config_enable_puk_unlock_screen);
1310     }
1311 
isEmergencyCallEnabledWhileSimLocked()1312     public boolean isEmergencyCallEnabledWhileSimLocked() {
1313         return mContext.getResources().getBoolean(
1314                 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
1315     }
1316 
1317     /**
1318      * @return A formatted string of the next alarm (for showing on the lock screen),
1319      *   or null if there is no next alarm.
1320      */
getNextAlarm()1321     public AlarmManager.AlarmClockInfo getNextAlarm() {
1322         AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
1323         return alarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
1324     }
1325 
getBoolean(String secureSettingKey, boolean defaultValue, int userId)1326     private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
1327         try {
1328             return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
1329         } catch (RemoteException re) {
1330             return defaultValue;
1331         }
1332     }
1333 
getBoolean(String secureSettingKey, boolean defaultValue)1334     private boolean getBoolean(String secureSettingKey, boolean defaultValue) {
1335         return getBoolean(secureSettingKey, defaultValue, getCurrentOrCallingUserId());
1336     }
1337 
setBoolean(String secureSettingKey, boolean enabled, int userId)1338     private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
1339         try {
1340             getLockSettings().setBoolean(secureSettingKey, enabled, userId);
1341         } catch (RemoteException re) {
1342             // What can we do?
1343             Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
1344         }
1345     }
1346 
setBoolean(String secureSettingKey, boolean enabled)1347     private void setBoolean(String secureSettingKey, boolean enabled) {
1348         setBoolean(secureSettingKey, enabled, getCurrentOrCallingUserId());
1349     }
1350 
getAppWidgets()1351     public int[] getAppWidgets() {
1352         return getAppWidgets(UserHandle.USER_CURRENT);
1353     }
1354 
getAppWidgets(int userId)1355     private int[] getAppWidgets(int userId) {
1356         String appWidgetIdString = Settings.Secure.getStringForUser(
1357                 mContentResolver, Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS, userId);
1358         String delims = ",";
1359         if (appWidgetIdString != null && appWidgetIdString.length() > 0) {
1360             String[] appWidgetStringIds = appWidgetIdString.split(delims);
1361             int[] appWidgetIds = new int[appWidgetStringIds.length];
1362             for (int i = 0; i < appWidgetStringIds.length; i++) {
1363                 String appWidget = appWidgetStringIds[i];
1364                 try {
1365                     appWidgetIds[i] = Integer.decode(appWidget);
1366                 } catch (NumberFormatException e) {
1367                     Log.d(TAG, "Error when parsing widget id " + appWidget);
1368                     return null;
1369                 }
1370             }
1371             return appWidgetIds;
1372         }
1373         return new int[0];
1374     }
1375 
combineStrings(int[] list, String separator)1376     private static String combineStrings(int[] list, String separator) {
1377         int listLength = list.length;
1378 
1379         switch (listLength) {
1380             case 0: {
1381                 return "";
1382             }
1383             case 1: {
1384                 return Integer.toString(list[0]);
1385             }
1386         }
1387 
1388         int strLength = 0;
1389         int separatorLength = separator.length();
1390 
1391         String[] stringList = new String[list.length];
1392         for (int i = 0; i < listLength; i++) {
1393             stringList[i] = Integer.toString(list[i]);
1394             strLength += stringList[i].length();
1395             if (i < listLength - 1) {
1396                 strLength += separatorLength;
1397             }
1398         }
1399 
1400         StringBuilder sb = new StringBuilder(strLength);
1401 
1402         for (int i = 0; i < listLength; i++) {
1403             sb.append(list[i]);
1404             if (i < listLength - 1) {
1405                 sb.append(separator);
1406             }
1407         }
1408 
1409         return sb.toString();
1410     }
1411 
1412     // appwidget used when appwidgets are disabled (we make an exception for
1413     // default clock widget)
writeFallbackAppWidgetId(int appWidgetId)1414     public void writeFallbackAppWidgetId(int appWidgetId) {
1415         Settings.Secure.putIntForUser(mContentResolver,
1416                 Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID,
1417                 appWidgetId,
1418                 UserHandle.USER_CURRENT);
1419     }
1420 
1421     // appwidget used when appwidgets are disabled (we make an exception for
1422     // default clock widget)
getFallbackAppWidgetId()1423     public int getFallbackAppWidgetId() {
1424         return Settings.Secure.getIntForUser(
1425                 mContentResolver,
1426                 Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID,
1427                 AppWidgetManager.INVALID_APPWIDGET_ID,
1428                 UserHandle.USER_CURRENT);
1429     }
1430 
writeAppWidgets(int[] appWidgetIds)1431     private void writeAppWidgets(int[] appWidgetIds) {
1432         Settings.Secure.putStringForUser(mContentResolver,
1433                         Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS,
1434                         combineStrings(appWidgetIds, ","),
1435                         UserHandle.USER_CURRENT);
1436     }
1437 
1438     // TODO: log an error if this returns false
addAppWidget(int widgetId, int index)1439     public boolean addAppWidget(int widgetId, int index) {
1440         int[] widgets = getAppWidgets();
1441         if (widgets == null) {
1442             return false;
1443         }
1444         if (index < 0 || index > widgets.length) {
1445             return false;
1446         }
1447         int[] newWidgets = new int[widgets.length + 1];
1448         for (int i = 0, j = 0; i < newWidgets.length; i++) {
1449             if (index == i) {
1450                 newWidgets[i] = widgetId;
1451                 i++;
1452             }
1453             if (i < newWidgets.length) {
1454                 newWidgets[i] = widgets[j];
1455                 j++;
1456             }
1457         }
1458         writeAppWidgets(newWidgets);
1459         return true;
1460     }
1461 
removeAppWidget(int widgetId)1462     public boolean removeAppWidget(int widgetId) {
1463         int[] widgets = getAppWidgets();
1464 
1465         if (widgets.length == 0) {
1466             return false;
1467         }
1468 
1469         int[] newWidgets = new int[widgets.length - 1];
1470         for (int i = 0, j = 0; i < widgets.length; i++) {
1471             if (widgets[i] == widgetId) {
1472                 // continue...
1473             } else if (j >= newWidgets.length) {
1474                 // we couldn't find the widget
1475                 return false;
1476             } else {
1477                 newWidgets[j] = widgets[i];
1478                 j++;
1479             }
1480         }
1481         writeAppWidgets(newWidgets);
1482         return true;
1483     }
1484 
getLong(String secureSettingKey, long defaultValue, int userHandle)1485     private long getLong(String secureSettingKey, long defaultValue, int userHandle) {
1486         try {
1487             return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle);
1488         } catch (RemoteException re) {
1489             return defaultValue;
1490         }
1491     }
1492 
getLong(String secureSettingKey, long defaultValue)1493     private long getLong(String secureSettingKey, long defaultValue) {
1494         try {
1495             return getLockSettings().getLong(secureSettingKey, defaultValue,
1496                     getCurrentOrCallingUserId());
1497         } catch (RemoteException re) {
1498             return defaultValue;
1499         }
1500     }
1501 
setLong(String secureSettingKey, long value)1502     private void setLong(String secureSettingKey, long value) {
1503         setLong(secureSettingKey, value, getCurrentOrCallingUserId());
1504     }
1505 
setLong(String secureSettingKey, long value, int userHandle)1506     private void setLong(String secureSettingKey, long value, int userHandle) {
1507         try {
1508             getLockSettings().setLong(secureSettingKey, value, userHandle);
1509         } catch (RemoteException re) {
1510             // What can we do?
1511             Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
1512         }
1513     }
1514 
getString(String secureSettingKey)1515     private String getString(String secureSettingKey) {
1516         return getString(secureSettingKey, getCurrentOrCallingUserId());
1517     }
1518 
getString(String secureSettingKey, int userHandle)1519     private String getString(String secureSettingKey, int userHandle) {
1520         try {
1521             return getLockSettings().getString(secureSettingKey, null, userHandle);
1522         } catch (RemoteException re) {
1523             return null;
1524         }
1525     }
1526 
setString(String secureSettingKey, String value, int userHandle)1527     private void setString(String secureSettingKey, String value, int userHandle) {
1528         try {
1529             getLockSettings().setString(secureSettingKey, value, userHandle);
1530         } catch (RemoteException re) {
1531             // What can we do?
1532             Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
1533         }
1534     }
1535 
isSecure()1536     public boolean isSecure() {
1537         return isSecure(getCurrentOrCallingUserId());
1538     }
1539 
isSecure(int userId)1540     public boolean isSecure(int userId) {
1541         long mode = getKeyguardStoredPasswordQuality(userId);
1542         final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
1543         final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
1544                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
1545                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
1546                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1547                 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
1548         final boolean secure =
1549                 isPattern && isLockPatternEnabled(userId) && savedPatternExists(userId)
1550                 || isPassword && savedPasswordExists(userId);
1551         return secure;
1552     }
1553 
1554     /**
1555      * Sets the emergency button visibility based on isEmergencyCallCapable().
1556      *
1557      * If the emergency button is visible, sets the text on the emergency button
1558      * to indicate what action will be taken.
1559      *
1560      * If there's currently a call in progress, the button will take them to the call
1561      * @param button The button to update
1562      * @param shown Indicates whether the given screen wants the emergency button to show at all
1563      * @param showIcon Indicates whether to show a phone icon for the button.
1564      */
updateEmergencyCallButtonState(Button button, boolean shown, boolean showIcon)1565     public void updateEmergencyCallButtonState(Button button, boolean shown, boolean showIcon) {
1566         if (isEmergencyCallCapable() && shown) {
1567             button.setVisibility(View.VISIBLE);
1568         } else {
1569             button.setVisibility(View.GONE);
1570             return;
1571         }
1572 
1573         int textId;
1574         if (isInCall()) {
1575             // show "return to call" text and show phone icon
1576             textId = R.string.lockscreen_return_to_call;
1577             int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
1578             button.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0);
1579         } else {
1580             textId = R.string.lockscreen_emergency_call;
1581             int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0;
1582             button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0);
1583         }
1584         button.setText(textId);
1585     }
1586 
1587     /**
1588      * Resumes a call in progress. Typically launched from the EmergencyCall button
1589      * on various lockscreens.
1590      */
resumeCall()1591     public void resumeCall() {
1592         getTelecommManager().showInCallScreen(false);
1593     }
1594 
1595     /**
1596      * @return {@code true} if there is a call currently in progress, {@code false} otherwise.
1597      */
isInCall()1598     public boolean isInCall() {
1599         return getTelecommManager().isInCall();
1600     }
1601 
getTelecommManager()1602     private TelecomManager getTelecommManager() {
1603         return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
1604     }
1605 
finishBiometricWeak(int userId)1606     private void finishBiometricWeak(int userId) {
1607         setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true, userId);
1608 
1609         // Launch intent to show final screen, this also
1610         // moves the temporary gallery to the actual gallery
1611         Intent intent = new Intent();
1612         intent.setClassName("com.android.facelock",
1613                 "com.android.facelock.SetupEndScreen");
1614         mContext.startActivityAsUser(intent, new UserHandle(userId));
1615     }
1616 
setPowerButtonInstantlyLocks(boolean enabled)1617     public void setPowerButtonInstantlyLocks(boolean enabled) {
1618         setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled);
1619     }
1620 
getPowerButtonInstantlyLocks()1621     public boolean getPowerButtonInstantlyLocks() {
1622         return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true);
1623     }
1624 
isSafeModeEnabled()1625     public static boolean isSafeModeEnabled() {
1626         try {
1627             return IWindowManager.Stub.asInterface(
1628                     ServiceManager.getService("window")).isSafeModeEnabled();
1629         } catch (RemoteException e) {
1630             // Shouldn't happen!
1631         }
1632         return false;
1633     }
1634 
1635     /**
1636      * Determine whether the user has selected any non-system widgets in keyguard
1637      *
1638      * @return true if widgets have been selected
1639      */
hasWidgetsEnabledInKeyguard(int userid)1640     public boolean hasWidgetsEnabledInKeyguard(int userid) {
1641         int widgets[] = getAppWidgets(userid);
1642         for (int i = 0; i < widgets.length; i++) {
1643             if (widgets[i] > 0) {
1644                 return true;
1645             }
1646         }
1647         return false;
1648     }
1649 
getWidgetsEnabled()1650     public boolean getWidgetsEnabled() {
1651         return getWidgetsEnabled(getCurrentOrCallingUserId());
1652     }
1653 
getWidgetsEnabled(int userId)1654     public boolean getWidgetsEnabled(int userId) {
1655         return getBoolean(LOCKSCREEN_WIDGETS_ENABLED, false, userId);
1656     }
1657 
setWidgetsEnabled(boolean enabled)1658     public void setWidgetsEnabled(boolean enabled) {
1659         setWidgetsEnabled(enabled, getCurrentOrCallingUserId());
1660     }
1661 
setWidgetsEnabled(boolean enabled, int userId)1662     public void setWidgetsEnabled(boolean enabled, int userId) {
1663         setBoolean(LOCKSCREEN_WIDGETS_ENABLED, enabled, userId);
1664     }
1665 
setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents)1666     public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents) {
1667         setEnabledTrustAgents(activeTrustAgents, getCurrentOrCallingUserId());
1668     }
1669 
getEnabledTrustAgents()1670     public List<ComponentName> getEnabledTrustAgents() {
1671         return getEnabledTrustAgents(getCurrentOrCallingUserId());
1672     }
1673 
setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId)1674     public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
1675         StringBuilder sb = new StringBuilder();
1676         for (ComponentName cn : activeTrustAgents) {
1677             if (sb.length() > 0) {
1678                 sb.append(',');
1679             }
1680             sb.append(cn.flattenToShortString());
1681         }
1682         setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
1683         getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId());
1684     }
1685 
getEnabledTrustAgents(int userId)1686     public List<ComponentName> getEnabledTrustAgents(int userId) {
1687         String serialized = getString(ENABLED_TRUST_AGENTS, userId);
1688         if (TextUtils.isEmpty(serialized)) {
1689             return null;
1690         }
1691         String[] split = serialized.split(",");
1692         ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
1693         for (String s : split) {
1694             if (!TextUtils.isEmpty(s)) {
1695                 activeTrustAgents.add(ComponentName.unflattenFromString(s));
1696             }
1697         }
1698         return activeTrustAgents;
1699     }
1700 
1701     /**
1702      * @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
1703      */
requireCredentialEntry(int userId)1704     public void requireCredentialEntry(int userId) {
1705         getTrustManager().reportRequireCredentialEntry(userId);
1706     }
1707 
onAfterChangingPassword(int userHandle)1708     private void onAfterChangingPassword(int userHandle) {
1709         getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
1710     }
1711 
isCredentialRequiredToDecrypt(boolean defaultValue)1712     public boolean isCredentialRequiredToDecrypt(boolean defaultValue) {
1713         final int value = Settings.Global.getInt(mContentResolver,
1714                 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, -1);
1715         return value == -1 ? defaultValue : (value != 0);
1716     }
1717 
setCredentialRequiredToDecrypt(boolean required)1718     public void setCredentialRequiredToDecrypt(boolean required) {
1719         if (getCurrentUser() != UserHandle.USER_OWNER) {
1720             Log.w(TAG, "Only device owner may call setCredentialRequiredForDecrypt()");
1721             return;
1722         }
1723         Settings.Global.putInt(mContext.getContentResolver(),
1724                 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0);
1725     }
1726 }
1727