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
17package com.android.internal.widget;
18
19import android.annotation.IntDef;
20import android.annotation.Nullable;
21import android.app.admin.DevicePolicyManager;
22import android.app.admin.PasswordMetrics;
23import android.app.trust.IStrongAuthTracker;
24import android.app.trust.TrustManager;
25import android.content.ComponentName;
26import android.content.ContentResolver;
27import android.content.Context;
28import android.content.pm.UserInfo;
29import android.os.AsyncTask;
30import android.os.Handler;
31import android.os.IBinder;
32import android.os.Looper;
33import android.os.Message;
34import android.os.RemoteException;
35import android.os.ServiceManager;
36import android.os.SystemClock;
37import android.os.UserHandle;
38import android.os.UserManager;
39import android.os.storage.IStorageManager;
40import android.os.storage.StorageManager;
41import android.provider.Settings;
42import android.text.TextUtils;
43import android.util.Log;
44import android.util.SparseIntArray;
45
46import com.android.internal.annotations.VisibleForTesting;
47import com.google.android.collect.Lists;
48
49import libcore.util.HexEncoding;
50
51import java.lang.annotation.Retention;
52import java.lang.annotation.RetentionPolicy;
53import java.nio.charset.StandardCharsets;
54import java.security.MessageDigest;
55import java.security.NoSuchAlgorithmException;
56import java.security.SecureRandom;
57import java.util.ArrayList;
58import java.util.Collection;
59import java.util.List;
60
61/**
62 * Utilities for the lock pattern and its settings.
63 */
64public class LockPatternUtils {
65
66    private static final String TAG = "LockPatternUtils";
67    private static final boolean DEBUG = false;
68
69    /**
70     * The key to identify when the lock pattern enabled flag is being accessed for legacy reasons.
71     */
72    public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled";
73
74    /**
75     * The number of incorrect attempts before which we fall back on an alternative
76     * method of verifying the user, and resetting their lock pattern.
77     */
78    public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20;
79
80    /**
81     * The interval of the countdown for showing progress of the lockout.
82     */
83    public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
84
85
86    /**
87     * This dictates when we start telling the user that continued failed attempts will wipe
88     * their device.
89     */
90    public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5;
91
92    /**
93     * The minimum number of dots in a valid pattern.
94     */
95    public static final int MIN_LOCK_PATTERN_SIZE = 4;
96
97    /**
98     * The minimum size of a valid password.
99     */
100    public static final int MIN_LOCK_PASSWORD_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    public static final int CREDENTIAL_TYPE_NONE = -1;
110
111    public static final int CREDENTIAL_TYPE_PATTERN = 1;
112
113    public static final int CREDENTIAL_TYPE_PASSWORD = 2;
114
115    @Deprecated
116    public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
117    public final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
118    public final static String LOCKOUT_ATTEMPT_TIMEOUT_MS = "lockscreen.lockoutattempttimeoutmss";
119    public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
120    public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
121    @Deprecated
122    public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
123    public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
124    public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
125    public final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
126    @Deprecated
127    public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
128            = "lockscreen.biometric_weak_fallback";
129    @Deprecated
130    public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY
131            = "lockscreen.biometricweakeverchosen";
132    public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
133            = "lockscreen.power_button_instantly_locks";
134    @Deprecated
135    public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled";
136
137    public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
138
139    private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO;
140    private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
141            Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
142
143    private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info";
144
145    private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
146    private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged";
147
148    public static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
149    public static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
150    public static final String SYNTHETIC_PASSWORD_KEY_PREFIX = "synthetic_password_";
151
152    public static final String SYNTHETIC_PASSWORD_HANDLE_KEY = "sp-handle";
153    public static final String SYNTHETIC_PASSWORD_ENABLED_KEY = "enable-sp";
154
155    private final Context mContext;
156    private final ContentResolver mContentResolver;
157    private DevicePolicyManager mDevicePolicyManager;
158    private ILockSettings mLockSettingsService;
159    private UserManager mUserManager;
160    private final Handler mHandler;
161
162    /**
163     * Use {@link TrustManager#isTrustUsuallyManaged(int)}.
164     *
165     * This returns the lazily-peristed value and should only be used by TrustManagerService.
166     */
167    public boolean isTrustUsuallyManaged(int userId) {
168        if (!(mLockSettingsService instanceof ILockSettings.Stub)) {
169            throw new IllegalStateException("May only be called by TrustManagerService. "
170                    + "Use TrustManager.isTrustUsuallyManaged()");
171        }
172        try {
173            return getLockSettings().getBoolean(IS_TRUST_USUALLY_MANAGED, false, userId);
174        } catch (RemoteException e) {
175            return false;
176        }
177    }
178
179    public void setTrustUsuallyManaged(boolean managed, int userId) {
180        try {
181            getLockSettings().setBoolean(IS_TRUST_USUALLY_MANAGED, managed, userId);
182        } catch (RemoteException e) {
183            // System dead.
184        }
185    }
186
187    public void userPresent(int userId) {
188        try {
189            getLockSettings().userPresent(userId);
190        } catch (RemoteException e) {
191            throw e.rethrowFromSystemServer();
192        }
193    }
194
195    public static final class RequestThrottledException extends Exception {
196        private int mTimeoutMs;
197        public RequestThrottledException(int timeoutMs) {
198            mTimeoutMs = timeoutMs;
199        }
200
201        /**
202         * @return The amount of time in ms before another request may
203         * be executed
204         */
205        public int getTimeoutMs() {
206            return mTimeoutMs;
207        }
208
209    }
210
211    public DevicePolicyManager getDevicePolicyManager() {
212        if (mDevicePolicyManager == null) {
213            mDevicePolicyManager =
214                (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
215            if (mDevicePolicyManager == null) {
216                Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
217                        new IllegalStateException("Stack trace:"));
218            }
219        }
220        return mDevicePolicyManager;
221    }
222
223    private UserManager getUserManager() {
224        if (mUserManager == null) {
225            mUserManager = UserManager.get(mContext);
226        }
227        return mUserManager;
228    }
229
230    private TrustManager getTrustManager() {
231        TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
232        if (trust == null) {
233            Log.e(TAG, "Can't get TrustManagerService: is it running?",
234                    new IllegalStateException("Stack trace:"));
235        }
236        return trust;
237    }
238
239    public LockPatternUtils(Context context) {
240        mContext = context;
241        mContentResolver = context.getContentResolver();
242
243        Looper looper = Looper.myLooper();
244        mHandler = looper != null ? new Handler(looper) : null;
245    }
246
247    @VisibleForTesting
248    public ILockSettings getLockSettings() {
249        if (mLockSettingsService == null) {
250            ILockSettings service = ILockSettings.Stub.asInterface(
251                    ServiceManager.getService("lock_settings"));
252            mLockSettingsService = service;
253        }
254        return mLockSettingsService;
255    }
256
257    public int getRequestedMinimumPasswordLength(int userId) {
258        return getDevicePolicyManager().getPasswordMinimumLength(null, userId);
259    }
260
261    /**
262     * Gets the device policy password mode. If the mode is non-specific, returns
263     * MODE_PATTERN which allows the user to choose anything.
264     */
265    public int getRequestedPasswordQuality(int userId) {
266        return getDevicePolicyManager().getPasswordQuality(null, userId);
267    }
268
269    private int getRequestedPasswordHistoryLength(int userId) {
270        return getDevicePolicyManager().getPasswordHistoryLength(null, userId);
271    }
272
273    public int getRequestedPasswordMinimumLetters(int userId) {
274        return getDevicePolicyManager().getPasswordMinimumLetters(null, userId);
275    }
276
277    public int getRequestedPasswordMinimumUpperCase(int userId) {
278        return getDevicePolicyManager().getPasswordMinimumUpperCase(null, userId);
279    }
280
281    public int getRequestedPasswordMinimumLowerCase(int userId) {
282        return getDevicePolicyManager().getPasswordMinimumLowerCase(null, userId);
283    }
284
285    public int getRequestedPasswordMinimumNumeric(int userId) {
286        return getDevicePolicyManager().getPasswordMinimumNumeric(null, userId);
287    }
288
289    public int getRequestedPasswordMinimumSymbols(int userId) {
290        return getDevicePolicyManager().getPasswordMinimumSymbols(null, userId);
291    }
292
293    public int getRequestedPasswordMinimumNonLetter(int userId) {
294        return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId);
295    }
296
297    public void reportFailedPasswordAttempt(int userId) {
298        getDevicePolicyManager().reportFailedPasswordAttempt(userId);
299        getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
300    }
301
302    public void reportSuccessfulPasswordAttempt(int userId) {
303        getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId);
304        getTrustManager().reportUnlockAttempt(true /* authenticated */, userId);
305    }
306
307    public void reportPasswordLockout(int timeoutMs, int userId) {
308        getTrustManager().reportUnlockLockout(timeoutMs, userId);
309    }
310
311    public int getCurrentFailedPasswordAttempts(int userId) {
312        return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId);
313    }
314
315    public int getMaximumFailedPasswordsForWipe(int userId) {
316        return getDevicePolicyManager().getMaximumFailedPasswordsForWipe(
317                null /* componentName */, userId);
318    }
319
320    private byte[] verifyCredential(String credential, int type, long challenge, int userId)
321            throws RequestThrottledException {
322        try {
323            VerifyCredentialResponse response = getLockSettings().verifyCredential(credential,
324                    type, challenge, userId);
325            if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
326                return response.getPayload();
327            } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
328                throw new RequestThrottledException(response.getTimeout());
329            } else {
330                return null;
331            }
332        } catch (RemoteException re) {
333            return null;
334        }
335    }
336
337    private boolean checkCredential(String credential, int type, int userId,
338            @Nullable CheckCredentialProgressCallback progressCallback)
339            throws RequestThrottledException {
340        try {
341            VerifyCredentialResponse response = getLockSettings().checkCredential(credential, type,
342                    userId, wrapCallback(progressCallback));
343
344            if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
345                return true;
346            } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
347                throw new RequestThrottledException(response.getTimeout());
348            } else {
349                return false;
350            }
351        } catch (RemoteException re) {
352            return false;
353        }
354    }
355
356    /**
357     * Check to see if a pattern matches the saved pattern.
358     * If pattern matches, return an opaque attestation that the challenge
359     * was verified.
360     *
361     * @param pattern The pattern to check.
362     * @param challenge The challenge to verify against the pattern
363     * @return the attestation that the challenge was verified, or null.
364     */
365    public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)
366            throws RequestThrottledException {
367        throwIfCalledOnMainThread();
368        return verifyCredential(patternToString(pattern), CREDENTIAL_TYPE_PATTERN, challenge,
369                userId);
370    }
371
372    /**
373     * Check to see if a pattern matches the saved pattern.  If no pattern exists,
374     * always returns true.
375     * @param pattern The pattern to check.
376     * @return Whether the pattern matches the stored one.
377     */
378    public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId)
379            throws RequestThrottledException {
380        return checkPattern(pattern, userId, null /* progressCallback */);
381    }
382
383    /**
384     * Check to see if a pattern matches the saved pattern.  If no pattern exists,
385     * always returns true.
386     * @param pattern The pattern to check.
387     * @return Whether the pattern matches the stored one.
388     */
389    public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId,
390            @Nullable CheckCredentialProgressCallback progressCallback)
391            throws RequestThrottledException {
392        throwIfCalledOnMainThread();
393        return checkCredential(patternToString(pattern), CREDENTIAL_TYPE_PATTERN, userId,
394                progressCallback);
395    }
396
397    /**
398     * Check to see if a password matches the saved password.
399     * If password matches, return an opaque attestation that the challenge
400     * was verified.
401     *
402     * @param password The password to check.
403     * @param challenge The challenge to verify against the password
404     * @return the attestation that the challenge was verified, or null.
405     */
406    public byte[] verifyPassword(String password, long challenge, int userId)
407            throws RequestThrottledException {
408        throwIfCalledOnMainThread();
409        return verifyCredential(password, CREDENTIAL_TYPE_PASSWORD, challenge, userId);
410    }
411
412
413    /**
414     * Check to see if a password matches the saved password.
415     * If password matches, return an opaque attestation that the challenge
416     * was verified.
417     *
418     * @param password The password to check.
419     * @param challenge The challenge to verify against the password
420     * @return the attestation that the challenge was verified, or null.
421     */
422    public byte[] verifyTiedProfileChallenge(String password, boolean isPattern, long challenge,
423            int userId) throws RequestThrottledException {
424        throwIfCalledOnMainThread();
425        try {
426            VerifyCredentialResponse response =
427                    getLockSettings().verifyTiedProfileChallenge(password,
428                            isPattern ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_PASSWORD, challenge,
429                            userId);
430
431            if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
432                return response.getPayload();
433            } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
434                throw new RequestThrottledException(response.getTimeout());
435            } else {
436                return null;
437            }
438        } catch (RemoteException re) {
439            return null;
440        }
441    }
442
443    /**
444     * Check to see if a password matches the saved password.  If no password exists,
445     * always returns true.
446     * @param password The password to check.
447     * @return Whether the password matches the stored one.
448     */
449    public boolean checkPassword(String password, int userId) throws RequestThrottledException {
450        return checkPassword(password, userId, null /* progressCallback */);
451    }
452
453    /**
454     * Check to see if a password matches the saved password.  If no password exists,
455     * always returns true.
456     * @param password The password to check.
457     * @return Whether the password matches the stored one.
458     */
459    public boolean checkPassword(String password, int userId,
460            @Nullable CheckCredentialProgressCallback progressCallback)
461            throws RequestThrottledException {
462        throwIfCalledOnMainThread();
463        return checkCredential(password, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback);
464    }
465
466    /**
467     * Check to see if vold already has the password.
468     * Note that this also clears vold's copy of the password.
469     * @return Whether the vold password matches or not.
470     */
471    public boolean checkVoldPassword(int userId) {
472        try {
473            return getLockSettings().checkVoldPassword(userId);
474        } catch (RemoteException re) {
475            return false;
476        }
477    }
478
479    /**
480     * Check to see if a password matches any of the passwords stored in the
481     * password history.
482     *
483     * @param password The password to check.
484     * @return Whether the password matches any in the history.
485     */
486    public boolean checkPasswordHistory(String password, int userId) {
487        String passwordHashString = new String(
488                passwordToHash(password, userId), StandardCharsets.UTF_8);
489        String passwordHistory = getString(PASSWORD_HISTORY_KEY, userId);
490        if (passwordHistory == null) {
491            return false;
492        }
493        // Password History may be too long...
494        int passwordHashLength = passwordHashString.length();
495        int passwordHistoryLength = getRequestedPasswordHistoryLength(userId);
496        if(passwordHistoryLength == 0) {
497            return false;
498        }
499        int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength
500                + passwordHistoryLength - 1;
501        if (passwordHistory.length() > neededPasswordHistoryLength) {
502            passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength);
503        }
504        return passwordHistory.contains(passwordHashString);
505    }
506
507    /**
508     * Check to see if the user has stored a lock pattern.
509     * @return Whether a saved pattern exists.
510     */
511    private boolean savedPatternExists(int userId) {
512        try {
513            return getLockSettings().havePattern(userId);
514        } catch (RemoteException re) {
515            return false;
516        }
517    }
518
519    /**
520     * Check to see if the user has stored a lock pattern.
521     * @return Whether a saved pattern exists.
522     */
523    private boolean savedPasswordExists(int userId) {
524        try {
525            return getLockSettings().havePassword(userId);
526        } catch (RemoteException re) {
527            return false;
528        }
529    }
530
531    /**
532     * Return true if the user has ever chosen a pattern.  This is true even if the pattern is
533     * currently cleared.
534     *
535     * @return True if the user has ever chosen a pattern.
536     */
537    public boolean isPatternEverChosen(int userId) {
538        return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, userId);
539    }
540
541    /**
542     * Used by device policy manager to validate the current password
543     * information it has.
544     */
545    public int getActivePasswordQuality(int userId) {
546        int quality = getKeyguardStoredPasswordQuality(userId);
547
548        if (isLockPasswordEnabled(quality, userId)) {
549            // Quality is a password and a password exists. Return the quality.
550            return quality;
551        }
552
553        if (isLockPatternEnabled(quality, userId)) {
554            // Quality is a pattern and a pattern exists. Return the quality.
555            return quality;
556        }
557
558        return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
559    }
560
561    /**
562     * Use it to reset keystore without wiping work profile
563     */
564    public void resetKeyStore(int userId) {
565        try {
566            getLockSettings().resetKeyStore(userId);
567        } catch (RemoteException e) {
568            // It should not happen
569            Log.e(TAG, "Couldn't reset keystore " + e);
570        }
571    }
572
573    /**
574     * Clear any lock pattern or password.
575     */
576    public void clearLock(String savedCredential, int userHandle) {
577        setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
578
579        try{
580            getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, savedCredential,
581                    userHandle);
582        } catch (RemoteException e) {
583            // well, we tried...
584        }
585
586        if (userHandle == UserHandle.USER_SYSTEM) {
587            // Set the encryption password to default.
588            updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
589            setCredentialRequiredToDecrypt(false);
590        }
591
592        onAfterChangingPassword(userHandle);
593    }
594
595    /**
596     * Disable showing lock screen at all for a given user.
597     * This is only meaningful if pattern, pin or password are not set.
598     *
599     * @param disable Disables lock screen when true
600     * @param userId User ID of the user this has effect on
601     */
602    public void setLockScreenDisabled(boolean disable, int userId) {
603        setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId);
604    }
605
606    /**
607     * Determine if LockScreen is disabled for the current user. This is used to decide whether
608     * LockScreen is shown after reboot or after screen timeout / short press on power.
609     *
610     * @return true if lock screen is disabled
611     */
612    public boolean isLockScreenDisabled(int userId) {
613        if (isSecure(userId)) {
614            return false;
615        }
616        boolean disabledByDefault = mContext.getResources().getBoolean(
617                com.android.internal.R.bool.config_disableLockscreenByDefault);
618        boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM;
619        return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId)
620                || (disabledByDefault && !isSystemUser);
621    }
622
623    /**
624     * Save a lock pattern.
625     * @param pattern The new pattern to save.
626     * @param userId the user whose pattern is to be saved.
627     */
628    public void saveLockPattern(List<LockPatternView.Cell> pattern, int userId) {
629        this.saveLockPattern(pattern, null, userId);
630    }
631    /**
632     * Save a lock pattern.
633     * @param pattern The new pattern to save.
634     * @param savedPattern The previously saved pattern, converted to String format
635     * @param userId the user whose pattern is to be saved.
636     */
637    public void saveLockPattern(List<LockPatternView.Cell> pattern, String savedPattern, int userId) {
638        try {
639            if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
640                throw new IllegalArgumentException("pattern must not be null and at least "
641                        + MIN_LOCK_PATTERN_SIZE + " dots long.");
642            }
643
644            setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
645            getLockSettings().setLockCredential(patternToString(pattern), CREDENTIAL_TYPE_PATTERN,
646                    savedPattern, userId);
647
648            // Update the device encryption password.
649            if (userId == UserHandle.USER_SYSTEM
650                    && LockPatternUtils.isDeviceEncryptionEnabled()) {
651                if (!shouldEncryptWithCredentials(true)) {
652                    clearEncryptionPassword();
653                } else {
654                    String stringPattern = patternToString(pattern);
655                    updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
656                }
657            }
658
659            setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
660            onAfterChangingPassword(userId);
661        } catch (RemoteException re) {
662            Log.e(TAG, "Couldn't save lock pattern " + re);
663        }
664    }
665
666    private void updateCryptoUserInfo(int userId) {
667        if (userId != UserHandle.USER_SYSTEM) {
668            return;
669        }
670
671        final String ownerInfo = isOwnerInfoEnabled(userId) ? getOwnerInfo(userId) : "";
672
673        IBinder service = ServiceManager.getService("mount");
674        if (service == null) {
675            Log.e(TAG, "Could not find the mount service to update the user info");
676            return;
677        }
678
679        IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
680        try {
681            Log.d(TAG, "Setting owner info");
682            storageManager.setField(StorageManager.OWNER_INFO_KEY, ownerInfo);
683        } catch (RemoteException e) {
684            Log.e(TAG, "Error changing user info", e);
685        }
686    }
687
688    public void setOwnerInfo(String info, int userId) {
689        setString(LOCK_SCREEN_OWNER_INFO, info, userId);
690        updateCryptoUserInfo(userId);
691    }
692
693    public void setOwnerInfoEnabled(boolean enabled, int userId) {
694        setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId);
695        updateCryptoUserInfo(userId);
696    }
697
698    public String getOwnerInfo(int userId) {
699        return getString(LOCK_SCREEN_OWNER_INFO, userId);
700    }
701
702    public boolean isOwnerInfoEnabled(int userId) {
703        return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false, userId);
704    }
705
706    /**
707     * Sets the device owner information. If the information is {@code null} or empty then the
708     * device owner info is cleared.
709     *
710     * @param info Device owner information which will be displayed instead of the user
711     * owner info.
712     */
713    public void setDeviceOwnerInfo(String info) {
714        if (info != null && info.isEmpty()) {
715            info = null;
716        }
717
718        setString(LOCK_SCREEN_DEVICE_OWNER_INFO, info, UserHandle.USER_SYSTEM);
719    }
720
721    public String getDeviceOwnerInfo() {
722        return getString(LOCK_SCREEN_DEVICE_OWNER_INFO, UserHandle.USER_SYSTEM);
723    }
724
725    public boolean isDeviceOwnerInfoEnabled() {
726        return getDeviceOwnerInfo() != null;
727    }
728
729    /** Update the encryption password if it is enabled **/
730    private void updateEncryptionPassword(final int type, final String password) {
731        if (!isDeviceEncryptionEnabled()) {
732            return;
733        }
734        final IBinder service = ServiceManager.getService("mount");
735        if (service == null) {
736            Log.e(TAG, "Could not find the mount service to update the encryption password");
737            return;
738        }
739
740        new AsyncTask<Void, Void, Void>() {
741            @Override
742            protected Void doInBackground(Void... dummy) {
743                IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
744                try {
745                    storageManager.changeEncryptionPassword(type, password);
746                } catch (RemoteException e) {
747                    Log.e(TAG, "Error changing encryption password", e);
748                }
749                return null;
750            }
751        }.execute();
752    }
753
754    /**
755     * Save a lock password.  Does not ensure that the password is as good
756     * as the requested mode, but will adjust the mode to be as good as the
757     * password.
758     * @param password The password to save
759     * @param savedPassword The previously saved lock password, or null if none
760     * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
761     * @param userHandle The userId of the user to change the password for
762     */
763    public void saveLockPassword(String password, String savedPassword, int quality,
764            int userHandle) {
765        try {
766            if (password == null || password.length() < MIN_LOCK_PASSWORD_SIZE) {
767                throw new IllegalArgumentException("password must not be null and at least "
768                        + "of length " + MIN_LOCK_PASSWORD_SIZE);
769            }
770
771            final int computedQuality = PasswordMetrics.computeForPassword(password).quality;
772            setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
773            getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
774                    userHandle);
775
776            updateEncryptionPasswordIfNeeded(password, computedQuality, userHandle);
777            updatePasswordHistory(password, userHandle);
778        } catch (RemoteException re) {
779            // Cant do much
780            Log.e(TAG, "Unable to save lock password " + re);
781        }
782    }
783
784    /**
785     * Update device encryption password if calling user is USER_SYSTEM and device supports
786     * encryption.
787     */
788    private void updateEncryptionPasswordIfNeeded(String password, int quality, int userHandle) {
789        // Update the device encryption password.
790        if (userHandle == UserHandle.USER_SYSTEM
791                && LockPatternUtils.isDeviceEncryptionEnabled()) {
792            if (!shouldEncryptWithCredentials(true)) {
793                clearEncryptionPassword();
794            } else {
795                boolean numeric = quality == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
796                boolean numericComplex = quality
797                        == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
798                int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
799                        : StorageManager.CRYPT_TYPE_PASSWORD;
800                updateEncryptionPassword(type, password);
801            }
802        }
803    }
804
805    private void updatePasswordHistory(String password, int userHandle) {
806
807        // Add the password to the password history. We assume all
808        // password hashes have the same length for simplicity of implementation.
809        String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
810        if (passwordHistory == null) {
811            passwordHistory = "";
812        }
813        int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle);
814        if (passwordHistoryLength == 0) {
815            passwordHistory = "";
816        } else {
817            byte[] hash = passwordToHash(password, userHandle);
818            passwordHistory = new String(hash, StandardCharsets.UTF_8) + "," + passwordHistory;
819            // Cut it to contain passwordHistoryLength hashes
820            // and passwordHistoryLength -1 commas.
821            passwordHistory = passwordHistory.substring(0, Math.min(hash.length
822                    * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
823                    .length()));
824        }
825        setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
826        onAfterChangingPassword(userHandle);
827    }
828
829    /**
830     * Determine if the device supports encryption, even if it's set to default. This
831     * differs from isDeviceEncrypted() in that it returns true even if the device is
832     * encrypted with the default password.
833     * @return true if device encryption is enabled
834     */
835    public static boolean isDeviceEncryptionEnabled() {
836        return StorageManager.isEncrypted();
837    }
838
839    /**
840     * Determine if the device is file encrypted
841     * @return true if device is file encrypted
842     */
843    public static boolean isFileEncryptionEnabled() {
844        return StorageManager.isFileEncryptedNativeOrEmulated();
845    }
846
847    /**
848     * Clears the encryption password.
849     */
850    public void clearEncryptionPassword() {
851        updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
852    }
853
854    /**
855     * Retrieves the quality mode for {@param userHandle}.
856     * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
857     *
858     * @return stored password quality
859     */
860    public int getKeyguardStoredPasswordQuality(int userHandle) {
861        return (int) getLong(PASSWORD_TYPE_KEY,
862                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
863    }
864
865    /**
866     * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
867     * for user handles that do not belong to a managed profile.
868     *
869     * @param userHandle Managed profile user id
870     * @param enabled True if separate challenge is enabled
871     * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is
872     *            true
873     */
874    public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
875            String managedUserPassword) {
876        UserInfo info = getUserManager().getUserInfo(userHandle);
877        if (info.isManagedProfile()) {
878            try {
879                getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
880                        managedUserPassword);
881                onAfterChangingPassword(userHandle);
882            } catch (RemoteException e) {
883                Log.e(TAG, "Couldn't update work profile challenge enabled");
884            }
885        }
886    }
887
888    /**
889     * Retrieves whether the Separate Profile Challenge is enabled for this {@param userHandle}.
890     */
891    public boolean isSeparateProfileChallengeEnabled(int userHandle) {
892        UserInfo info = getUserManager().getUserInfo(userHandle);
893        if (info == null || !info.isManagedProfile()) {
894            return false;
895        }
896        try {
897            return getLockSettings().getSeparateProfileChallengeEnabled(userHandle);
898        } catch (RemoteException e) {
899            Log.e(TAG, "Couldn't get separate profile challenge enabled");
900            // Default value is false
901            return false;
902        }
903    }
904
905    /**
906     * Retrieves whether the current DPM allows use of the Profile Challenge.
907     */
908    public boolean isSeparateProfileChallengeAllowed(int userHandle) {
909        UserInfo info = getUserManager().getUserInfo(userHandle);
910        if (info == null || !info.isManagedProfile()) {
911            return false;
912        }
913        return getDevicePolicyManager().isSeparateProfileChallengeAllowed(userHandle);
914    }
915
916    /**
917     * Retrieves whether the current profile and device locks can be unified.
918     */
919    public boolean isSeparateProfileChallengeAllowedToUnify(int userHandle) {
920        return getDevicePolicyManager().isProfileActivePasswordSufficientForParent(userHandle);
921    }
922
923    /**
924     * Deserialize a pattern.
925     * @param string The pattern serialized with {@link #patternToString}
926     * @return The pattern.
927     */
928    public static List<LockPatternView.Cell> stringToPattern(String string) {
929        if (string == null) {
930            return null;
931        }
932
933        List<LockPatternView.Cell> result = Lists.newArrayList();
934
935        final byte[] bytes = string.getBytes();
936        for (int i = 0; i < bytes.length; i++) {
937            byte b = (byte) (bytes[i] - '1');
938            result.add(LockPatternView.Cell.of(b / 3, b % 3));
939        }
940        return result;
941    }
942
943    /**
944     * Serialize a pattern.
945     * @param pattern The pattern.
946     * @return The pattern in string form.
947     */
948    public static String patternToString(List<LockPatternView.Cell> pattern) {
949        if (pattern == null) {
950            return "";
951        }
952        final int patternSize = pattern.size();
953
954        byte[] res = new byte[patternSize];
955        for (int i = 0; i < patternSize; i++) {
956            LockPatternView.Cell cell = pattern.get(i);
957            res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');
958        }
959        return new String(res);
960    }
961
962    public static String patternStringToBaseZero(String pattern) {
963        if (pattern == null) {
964            return "";
965        }
966        final int patternSize = pattern.length();
967
968        byte[] res = new byte[patternSize];
969        final byte[] bytes = pattern.getBytes();
970        for (int i = 0; i < patternSize; i++) {
971            res[i] = (byte) (bytes[i] - '1');
972        }
973        return new String(res);
974    }
975
976    /*
977     * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
978     * at least a second level of protection. First level is that the file
979     * is in a location only readable by the system process.
980     * @param pattern the gesture pattern.
981     * @return the hash of the pattern in a byte array.
982     */
983    public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
984        if (pattern == null) {
985            return null;
986        }
987
988        final int patternSize = pattern.size();
989        byte[] res = new byte[patternSize];
990        for (int i = 0; i < patternSize; i++) {
991            LockPatternView.Cell cell = pattern.get(i);
992            res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
993        }
994        try {
995            MessageDigest md = MessageDigest.getInstance("SHA-1");
996            byte[] hash = md.digest(res);
997            return hash;
998        } catch (NoSuchAlgorithmException nsa) {
999            return res;
1000        }
1001    }
1002
1003    private String getSalt(int userId) {
1004        long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);
1005        if (salt == 0) {
1006            try {
1007                salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
1008                setLong(LOCK_PASSWORD_SALT_KEY, salt, userId);
1009                Log.v(TAG, "Initialized lock password salt for user: " + userId);
1010            } catch (NoSuchAlgorithmException e) {
1011                // Throw an exception rather than storing a password we'll never be able to recover
1012                throw new IllegalStateException("Couldn't get SecureRandom number", e);
1013            }
1014        }
1015        return Long.toHexString(salt);
1016    }
1017
1018    /*
1019     * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
1020     * Not the most secure, but it is at least a second level of protection. First level is that
1021     * the file is in a location only readable by the system process.
1022     *
1023     * @param password the gesture pattern.
1024     *
1025     * @return the hash of the pattern in a byte array.
1026     */
1027    public byte[] passwordToHash(String password, int userId) {
1028        if (password == null) {
1029            return null;
1030        }
1031
1032        try {
1033            byte[] saltedPassword = (password + getSalt(userId)).getBytes();
1034            byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(saltedPassword);
1035            byte[] md5 = MessageDigest.getInstance("MD5").digest(saltedPassword);
1036
1037            byte[] combined = new byte[sha1.length + md5.length];
1038            System.arraycopy(sha1, 0, combined, 0, sha1.length);
1039            System.arraycopy(md5, 0, combined, sha1.length, md5.length);
1040
1041            final char[] hexEncoded = HexEncoding.encode(combined);
1042            return new String(hexEncoded).getBytes(StandardCharsets.UTF_8);
1043        } catch (NoSuchAlgorithmException e) {
1044            throw new AssertionError("Missing digest algorithm: ", e);
1045        }
1046    }
1047
1048    /**
1049     * @param userId the user for which to report the value
1050     * @return Whether the lock screen is secured.
1051     */
1052    public boolean isSecure(int userId) {
1053        int mode = getKeyguardStoredPasswordQuality(userId);
1054        return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId);
1055    }
1056
1057    public boolean isLockPasswordEnabled(int userId) {
1058        return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId);
1059    }
1060
1061    private boolean isLockPasswordEnabled(int mode, int userId) {
1062        final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
1063                || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
1064                || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
1065                || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1066                || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX
1067                || mode == DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
1068        return passwordEnabled && savedPasswordExists(userId);
1069    }
1070
1071    /**
1072     * @return Whether the lock pattern is enabled
1073     */
1074    public boolean isLockPatternEnabled(int userId) {
1075        return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId);
1076    }
1077
1078    @Deprecated
1079    public boolean isLegacyLockPatternEnabled(int userId) {
1080        // Note: this value should default to {@code true} to avoid any reset that might result.
1081        // We must use a special key to read this value, since it will by default return the value
1082        // based on the new logic.
1083        return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId);
1084    }
1085
1086    @Deprecated
1087    public void setLegacyLockPatternEnabled(int userId) {
1088        setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId);
1089    }
1090
1091    private boolean isLockPatternEnabled(int mode, int userId) {
1092        return mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
1093                && savedPatternExists(userId);
1094    }
1095
1096    /**
1097     * @return Whether the visible pattern is enabled.
1098     */
1099    public boolean isVisiblePatternEnabled(int userId) {
1100        return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId);
1101    }
1102
1103    /**
1104     * Set whether the visible pattern is enabled.
1105     */
1106    public void setVisiblePatternEnabled(boolean enabled, int userId) {
1107        setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled, userId);
1108
1109        // Update for crypto if owner
1110        if (userId != UserHandle.USER_SYSTEM) {
1111            return;
1112        }
1113
1114        IBinder service = ServiceManager.getService("mount");
1115        if (service == null) {
1116            Log.e(TAG, "Could not find the mount service to update the user info");
1117            return;
1118        }
1119
1120        IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
1121        try {
1122            storageManager.setField(StorageManager.PATTERN_VISIBLE_KEY, enabled ? "1" : "0");
1123        } catch (RemoteException e) {
1124            Log.e(TAG, "Error changing pattern visible state", e);
1125        }
1126    }
1127
1128    /**
1129     * Set whether the visible password is enabled for cryptkeeper screen.
1130     */
1131    public void setVisiblePasswordEnabled(boolean enabled, int userId) {
1132        // Update for crypto if owner
1133        if (userId != UserHandle.USER_SYSTEM) {
1134            return;
1135        }
1136
1137        IBinder service = ServiceManager.getService("mount");
1138        if (service == null) {
1139            Log.e(TAG, "Could not find the mount service to update the user info");
1140            return;
1141        }
1142
1143        IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
1144        try {
1145            storageManager.setField(StorageManager.PASSWORD_VISIBLE_KEY, enabled ? "1" : "0");
1146        } catch (RemoteException e) {
1147            Log.e(TAG, "Error changing password visible state", e);
1148        }
1149    }
1150
1151    /**
1152     * @return Whether tactile feedback for the pattern is enabled.
1153     */
1154    public boolean isTactileFeedbackEnabled() {
1155        return Settings.System.getIntForUser(mContentResolver,
1156                Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
1157    }
1158
1159    /**
1160     * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
1161     * pattern until the deadline has passed.
1162     * @return the chosen deadline.
1163     */
1164    public long setLockoutAttemptDeadline(int userId, int timeoutMs) {
1165        final long deadline = SystemClock.elapsedRealtime() + timeoutMs;
1166        setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
1167        setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, timeoutMs, userId);
1168        return deadline;
1169    }
1170
1171    /**
1172     * @return The elapsed time in millis in the future when the user is allowed to
1173     *   attempt to enter his/her lock pattern, or 0 if the user is welcome to
1174     *   enter a pattern.
1175     */
1176    public long getLockoutAttemptDeadline(int userId) {
1177        long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, userId);
1178        final long timeoutMs = getLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0L, userId);
1179        final long now = SystemClock.elapsedRealtime();
1180        if (deadline < now && deadline != 0) {
1181            // timeout expired
1182            setLong(LOCKOUT_ATTEMPT_DEADLINE, 0, userId);
1183            setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0, userId);
1184            return 0L;
1185        }
1186
1187        if (deadline > (now + timeoutMs)) {
1188            // device was rebooted, set new deadline
1189            deadline = now + timeoutMs;
1190            setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
1191        }
1192
1193        return deadline;
1194    }
1195
1196    private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
1197        try {
1198            return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
1199        } catch (RemoteException re) {
1200            return defaultValue;
1201        }
1202    }
1203
1204    private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
1205        try {
1206            getLockSettings().setBoolean(secureSettingKey, enabled, userId);
1207        } catch (RemoteException re) {
1208            // What can we do?
1209            Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
1210        }
1211    }
1212
1213    private long getLong(String secureSettingKey, long defaultValue, int userHandle) {
1214        try {
1215            return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle);
1216        } catch (RemoteException re) {
1217            return defaultValue;
1218        }
1219    }
1220
1221    private void setLong(String secureSettingKey, long value, int userHandle) {
1222        try {
1223            getLockSettings().setLong(secureSettingKey, value, userHandle);
1224        } catch (RemoteException re) {
1225            // What can we do?
1226            Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
1227        }
1228    }
1229
1230    private String getString(String secureSettingKey, int userHandle) {
1231        try {
1232            return getLockSettings().getString(secureSettingKey, null, userHandle);
1233        } catch (RemoteException re) {
1234            return null;
1235        }
1236    }
1237
1238    private void setString(String secureSettingKey, String value, int userHandle) {
1239        try {
1240            getLockSettings().setString(secureSettingKey, value, userHandle);
1241        } catch (RemoteException re) {
1242            // What can we do?
1243            Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
1244        }
1245    }
1246
1247    public void setPowerButtonInstantlyLocks(boolean enabled, int userId) {
1248        setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId);
1249    }
1250
1251    public boolean getPowerButtonInstantlyLocks(int userId) {
1252        return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId);
1253    }
1254
1255    public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
1256        StringBuilder sb = new StringBuilder();
1257        for (ComponentName cn : activeTrustAgents) {
1258            if (sb.length() > 0) {
1259                sb.append(',');
1260            }
1261            sb.append(cn.flattenToShortString());
1262        }
1263        setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
1264        getTrustManager().reportEnabledTrustAgentsChanged(userId);
1265    }
1266
1267    public List<ComponentName> getEnabledTrustAgents(int userId) {
1268        String serialized = getString(ENABLED_TRUST_AGENTS, userId);
1269        if (TextUtils.isEmpty(serialized)) {
1270            return null;
1271        }
1272        String[] split = serialized.split(",");
1273        ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
1274        for (String s : split) {
1275            if (!TextUtils.isEmpty(s)) {
1276                activeTrustAgents.add(ComponentName.unflattenFromString(s));
1277            }
1278        }
1279        return activeTrustAgents;
1280    }
1281
1282    /**
1283     * Disable trust until credentials have been entered for user {@param userId}.
1284     *
1285     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
1286     *
1287     * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
1288     */
1289    public void requireCredentialEntry(int userId) {
1290        requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
1291    }
1292
1293    /**
1294     * Requests strong authentication for user {@param userId}.
1295     *
1296     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
1297     *
1298     * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating
1299     *                         the reason for and the strength of the requested authentication.
1300     * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
1301     */
1302    public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason,
1303            int userId) {
1304        try {
1305            getLockSettings().requireStrongAuth(strongAuthReason, userId);
1306        } catch (RemoteException e) {
1307            Log.e(TAG, "Error while requesting strong auth: " + e);
1308        }
1309    }
1310
1311    private void onAfterChangingPassword(int userHandle) {
1312        getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
1313    }
1314
1315    public boolean isCredentialRequiredToDecrypt(boolean defaultValue) {
1316        final int value = Settings.Global.getInt(mContentResolver,
1317                Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, -1);
1318        return value == -1 ? defaultValue : (value != 0);
1319    }
1320
1321    public void setCredentialRequiredToDecrypt(boolean required) {
1322        if (!(getUserManager().isSystemUser() || getUserManager().isPrimaryUser())) {
1323            throw new IllegalStateException(
1324                    "Only the system or primary user may call setCredentialRequiredForDecrypt()");
1325        }
1326
1327        if (isDeviceEncryptionEnabled()){
1328            Settings.Global.putInt(mContext.getContentResolver(),
1329               Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0);
1330        }
1331    }
1332
1333    private boolean isDoNotAskCredentialsOnBootSet() {
1334        return getDevicePolicyManager().getDoNotAskCredentialsOnBoot();
1335    }
1336
1337    private boolean shouldEncryptWithCredentials(boolean defaultValue) {
1338        return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet();
1339    }
1340
1341    private void throwIfCalledOnMainThread() {
1342        if (Looper.getMainLooper().isCurrentThread()) {
1343            throw new IllegalStateException("should not be called from the main thread.");
1344        }
1345    }
1346
1347    public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
1348        try {
1349            getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
1350        } catch (RemoteException e) {
1351            throw new RuntimeException("Could not register StrongAuthTracker");
1352        }
1353    }
1354
1355    public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
1356        try {
1357            getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
1358        } catch (RemoteException e) {
1359            Log.e(TAG, "Could not unregister StrongAuthTracker", e);
1360        }
1361    }
1362
1363    /**
1364     * @see StrongAuthTracker#getStrongAuthForUser
1365     */
1366    public int getStrongAuthForUser(int userId) {
1367        try {
1368            return getLockSettings().getStrongAuthForUser(userId);
1369        } catch (RemoteException e) {
1370            Log.e(TAG, "Could not get StrongAuth", e);
1371            return StrongAuthTracker.getDefaultFlags(mContext);
1372        }
1373    }
1374
1375    /**
1376     * @see StrongAuthTracker#isTrustAllowedForUser
1377     */
1378    public boolean isTrustAllowedForUser(int userId) {
1379        return getStrongAuthForUser(userId) == StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
1380    }
1381
1382    /**
1383     * @see StrongAuthTracker#isFingerprintAllowedForUser
1384     */
1385    public boolean isFingerprintAllowedForUser(int userId) {
1386        return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_FINGERPRINT) == 0;
1387    }
1388
1389    private ICheckCredentialProgressCallback wrapCallback(
1390            final CheckCredentialProgressCallback callback) {
1391        if (callback == null) {
1392            return null;
1393        } else {
1394            if (mHandler == null) {
1395                throw new IllegalStateException("Must construct LockPatternUtils on a looper thread"
1396                        + " to use progress callbacks.");
1397            }
1398            return new ICheckCredentialProgressCallback.Stub() {
1399
1400                @Override
1401                public void onCredentialVerified() throws RemoteException {
1402                    mHandler.post(callback::onEarlyMatched);
1403                }
1404            };
1405        }
1406    }
1407
1408    /**
1409     * Create an escrow token for the current user, which can later be used to unlock FBE
1410     * or change user password.
1411     *
1412     * After adding, if the user currently has lockscreen password, he will need to perform a
1413     * confirm credential operation in order to activate the token for future use. If the user
1414     * has no secure lockscreen, then the token is activated immediately.
1415     *
1416     * @return a unique 64-bit token handle which is needed to refer to this token later.
1417     */
1418    public long addEscrowToken(byte[] token, int userId) {
1419        try {
1420            return getLockSettings().addEscrowToken(token, userId);
1421        } catch (RemoteException re) {
1422            return 0L;
1423        }
1424    }
1425
1426    /**
1427     * Remove an escrow token.
1428     * @return true if the given handle refers to a valid token previously returned from
1429     * {@link #addEscrowToken}, whether it's active or not. return false otherwise.
1430     */
1431    public boolean removeEscrowToken(long handle, int userId) {
1432        try {
1433            return getLockSettings().removeEscrowToken(handle, userId);
1434        } catch (RemoteException re) {
1435            return false;
1436        }
1437    }
1438
1439    /**
1440     * Check if the given escrow token is active or not. Only active token can be used to call
1441     * {@link #setLockCredentialWithToken} and {@link #unlockUserWithToken}
1442     */
1443    public boolean isEscrowTokenActive(long handle, int userId) {
1444        try {
1445            return getLockSettings().isEscrowTokenActive(handle, userId);
1446        } catch (RemoteException re) {
1447            return false;
1448        }
1449    }
1450
1451    public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
1452            byte[] token, int userId) {
1453        try {
1454            if (type != CREDENTIAL_TYPE_NONE) {
1455                if (TextUtils.isEmpty(credential) || credential.length() < MIN_LOCK_PASSWORD_SIZE) {
1456                    throw new IllegalArgumentException("password must not be null and at least "
1457                            + "of length " + MIN_LOCK_PASSWORD_SIZE);
1458                }
1459
1460                final int computedQuality = PasswordMetrics.computeForPassword(credential).quality;
1461                if (!getLockSettings().setLockCredentialWithToken(credential, type, tokenHandle,
1462                        token, userId)) {
1463                    return false;
1464                }
1465                setLong(PASSWORD_TYPE_KEY, Math.max(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
1466                        computedQuality), userId);
1467
1468                updateEncryptionPasswordIfNeeded(credential, computedQuality, userId);
1469                updatePasswordHistory(credential, userId);
1470            } else {
1471                if (!TextUtils.isEmpty(credential)) {
1472                    throw new IllegalArgumentException("password must be emtpy for NONE type");
1473                }
1474                if (!getLockSettings().setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE,
1475                        tokenHandle, token, userId)) {
1476                    return false;
1477                }
1478                setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
1479                        userId);
1480
1481                if (userId == UserHandle.USER_SYSTEM) {
1482                    // Set the encryption password to default.
1483                    updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
1484                    setCredentialRequiredToDecrypt(false);
1485                }
1486            }
1487            onAfterChangingPassword(userId);
1488            return true;
1489        } catch (RemoteException re) {
1490            Log.e(TAG, "Unable to save lock password ", re);
1491            re.rethrowFromSystemServer();
1492        }
1493        return false;
1494    }
1495
1496    public void unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
1497        try {
1498            getLockSettings().unlockUserWithToken(tokenHandle, token, userId);
1499        } catch (RemoteException re) {
1500            Log.e(TAG, "Unable to unlock user with token", re);
1501            re.rethrowFromSystemServer();
1502        }
1503    }
1504
1505
1506    /**
1507     * Callback to be notified about progress when checking credentials.
1508     */
1509    public interface CheckCredentialProgressCallback {
1510
1511        /**
1512         * Called as soon as possible when we know that the credentials match but the user hasn't
1513         * been fully unlocked.
1514         */
1515        void onEarlyMatched();
1516    }
1517
1518    /**
1519     * Tracks the global strong authentication state.
1520     */
1521    public static class StrongAuthTracker {
1522
1523        @IntDef(flag = true,
1524                value = { STRONG_AUTH_NOT_REQUIRED,
1525                        STRONG_AUTH_REQUIRED_AFTER_BOOT,
1526                        STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
1527                        SOME_AUTH_REQUIRED_AFTER_USER_REQUEST,
1528                        STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
1529                        STRONG_AUTH_REQUIRED_AFTER_TIMEOUT})
1530        @Retention(RetentionPolicy.SOURCE)
1531        public @interface StrongAuthFlags {}
1532
1533        /**
1534         * Strong authentication is not required.
1535         */
1536        public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;
1537
1538        /**
1539         * Strong authentication is required because the user has not authenticated since boot.
1540         */
1541        public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
1542
1543        /**
1544         * Strong authentication is required because a device admin has requested it.
1545         */
1546        public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
1547
1548        /**
1549         * Some authentication is required because the user has temporarily disabled trust.
1550         */
1551        public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
1552
1553        /**
1554         * Strong authentication is required because the user has been locked out after too many
1555         * attempts.
1556         */
1557        public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
1558
1559        /**
1560         * Strong authentication is required because it hasn't been used for a time required by
1561         * a device admin.
1562         */
1563        public static final int STRONG_AUTH_REQUIRED_AFTER_TIMEOUT = 0x10;
1564
1565        /**
1566         * Strong auth flags that do not prevent fingerprint from being accepted as auth.
1567         *
1568         * If any other flags are set, fingerprint is disabled.
1569         */
1570        private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED
1571                | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
1572
1573        private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
1574        private final H mHandler;
1575        private final int mDefaultStrongAuthFlags;
1576
1577        public StrongAuthTracker(Context context) {
1578            this(context, Looper.myLooper());
1579        }
1580
1581        /**
1582         * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged}
1583         *               will be scheduled.
1584         * @param context the current {@link Context}
1585         */
1586        public StrongAuthTracker(Context context, Looper looper) {
1587            mHandler = new H(looper);
1588            mDefaultStrongAuthFlags = getDefaultFlags(context);
1589        }
1590
1591        public static @StrongAuthFlags int getDefaultFlags(Context context) {
1592            boolean strongAuthRequired = context.getResources().getBoolean(
1593                    com.android.internal.R.bool.config_strongAuthRequiredOnBoot);
1594            return strongAuthRequired ? STRONG_AUTH_REQUIRED_AFTER_BOOT : STRONG_AUTH_NOT_REQUIRED;
1595        }
1596
1597        /**
1598         * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required,
1599         * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong
1600         * authentication is required.
1601         *
1602         * @param userId the user for whom the state is queried.
1603         */
1604        public @StrongAuthFlags int getStrongAuthForUser(int userId) {
1605            return mStrongAuthRequiredForUser.get(userId, mDefaultStrongAuthFlags);
1606        }
1607
1608        /**
1609         * @return true if unlocking with trust alone is allowed for {@param userId} by the current
1610         * strong authentication requirements.
1611         */
1612        public boolean isTrustAllowedForUser(int userId) {
1613            return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
1614        }
1615
1616        /**
1617         * @return true if unlocking with fingerprint alone is allowed for {@param userId} by the
1618         * current strong authentication requirements.
1619         */
1620        public boolean isFingerprintAllowedForUser(int userId) {
1621            return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
1622        }
1623
1624        /**
1625         * Called when the strong authentication requirements for {@param userId} changed.
1626         */
1627        public void onStrongAuthRequiredChanged(int userId) {
1628        }
1629
1630        protected void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
1631                int userId) {
1632            int oldValue = getStrongAuthForUser(userId);
1633            if (strongAuthFlags != oldValue) {
1634                if (strongAuthFlags == mDefaultStrongAuthFlags) {
1635                    mStrongAuthRequiredForUser.delete(userId);
1636                } else {
1637                    mStrongAuthRequiredForUser.put(userId, strongAuthFlags);
1638                }
1639                onStrongAuthRequiredChanged(userId);
1640            }
1641        }
1642
1643
1644        protected final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
1645            @Override
1646            public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
1647                    int userId) {
1648                mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
1649                        strongAuthFlags, userId).sendToTarget();
1650            }
1651        };
1652
1653        private class H extends Handler {
1654            static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
1655
1656            public H(Looper looper) {
1657                super(looper);
1658            }
1659
1660            @Override
1661            public void handleMessage(Message msg) {
1662                switch (msg.what) {
1663                    case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
1664                        handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
1665                        break;
1666                }
1667            }
1668        }
1669    }
1670
1671    public void enableSyntheticPassword() {
1672        setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1L, UserHandle.USER_SYSTEM);
1673    }
1674
1675    public boolean isSyntheticPasswordEnabled() {
1676        return getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM) != 0;
1677    }
1678}
1679