/** * Save a lock pattern. * * @param pattern The new pattern to save. * @param isFallback Specifies if this is a fallback to biometric weak */ public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) { // Compute the hash final byte[] hash = LockPatternUtils.patternToHash(pattern); try { // Write the hash to file RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "rw"); // Truncate the file if pattern is null, to clear the lock if (pattern == null) { raf.setLength(0); } else { raf.write(hash, 0, hash.length); } raf.close(); DevicePolicyManager dpm = getDevicePolicyManager(); KeyStore keyStore = KeyStore.getInstance(); if (pattern != null) { keyStore.password(patternToString(pattern)); setBoolean(PATTERN_EVER_CHOSEN_KEY, true); if (!isFallback) { deleteGallery(); setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern.size(), 0, 0, 0, 0, 0, 0); } else { setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); finishBiometricWeak(); dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, 0, 0, 0, 0, 0, 0, 0); } } else { if (keyStore.isEmpty()) { keyStore.reset(); } dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0); } } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings // provider Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename); } catch (IOException ioe) { // Cant do much Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename); } }
/** * Save a lock password. Does not ensure that the password is as good as the requested mode, but * will adjust the mode to be as good as the pattern. * * @param password The password to save * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} * @param isFallback Specifies if this is a fallback to biometric weak */ public void saveLockPassword(String password, int quality, boolean isFallback) { // Compute the hash final byte[] hash = passwordToHash(password); try { // Write the hash to file RandomAccessFile raf = new RandomAccessFile(sLockPasswordFilename, "rw"); // Truncate the file if pattern is null, to clear the lock if (password == null) { raf.setLength(0); } else { raf.write(hash, 0, hash.length); } raf.close(); DevicePolicyManager dpm = getDevicePolicyManager(); KeyStore keyStore = KeyStore.getInstance(); if (password != null) { // Update the encryption password. updateEncryptionPassword(password); // Update the keystore password keyStore.password(password); int computedQuality = computePasswordQuality(password); if (!isFallback) { deleteGallery(); setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality)); if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { int letters = 0; int uppercase = 0; int lowercase = 0; int numbers = 0; int symbols = 0; int nonletter = 0; for (int i = 0; i < password.length(); i++) { char c = password.charAt(i); if (c >= 'A' && c <= 'Z') { letters++; uppercase++; } else if (c >= 'a' && c <= 'z') { letters++; lowercase++; } else if (c >= '0' && c <= '9') { numbers++; nonletter++; } else { symbols++; nonletter++; } } dpm.setActivePasswordState( Math.max(quality, computedQuality), password.length(), letters, uppercase, lowercase, numbers, symbols, nonletter); } else { // The password is not anything. dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0); } } else { // Case where it's a fallback for biometric weak setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality)); finishBiometricWeak(); dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, 0, 0, 0, 0, 0, 0, 0); } // Add the password to the password history. We assume all // password // hashes have the same length for simplicity of implementation. String passwordHistory = getString(PASSWORD_HISTORY_KEY); if (passwordHistory == null) { passwordHistory = new String(); } int passwordHistoryLength = getRequestedPasswordHistoryLength(); if (passwordHistoryLength == 0) { passwordHistory = ""; } else { passwordHistory = new String(hash) + "," + passwordHistory; // Cut it to contain passwordHistoryLength hashes // and passwordHistoryLength -1 commas. passwordHistory = passwordHistory.substring( 0, Math.min( hash.length * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory.length())); } setString(PASSWORD_HISTORY_KEY, passwordHistory); } else { // Conditionally reset the keystore if empty. If // non-empty, we are just switching key guard type if (keyStore.isEmpty()) { keyStore.reset(); } dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0); } } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings provider Log.e(TAG, "Unable to save lock pattern to " + sLockPasswordFilename); } catch (IOException ioe) { // Cant do much Log.e(TAG, "Unable to save lock pattern to " + sLockPasswordFilename); } }