Merge "Refactor passwords/pins/patterns to byte[]"
diff --git a/core/java/android/app/admin/PasswordMetrics.java b/core/java/android/app/admin/PasswordMetrics.java
index e5df2c7..a6bf501 100644
--- a/core/java/android/app/admin/PasswordMetrics.java
+++ b/core/java/android/app/admin/PasswordMetrics.java
@@ -221,7 +221,10 @@
         }
     };
 
-    public static PasswordMetrics computeForPassword(@NonNull String password) {
+    /**
+     * Returns the {@code PasswordMetrics} for a given password
+     */
+    public static PasswordMetrics computeForPassword(@NonNull byte[] password) {
         // Analyse the characters used
         int letters = 0;
         int upperCase = 0;
@@ -229,9 +232,9 @@
         int numeric = 0;
         int symbols = 0;
         int nonLetter = 0;
-        final int length = password.length();
+        final int length = password.length;
         for (int i = 0; i < length; i++) {
-            switch (categoryChar(password.charAt(i))) {
+            switch (categoryChar((char) password[i])) {
                 case CHAR_LOWER_CASE:
                     letters++;
                     lowerCase++;
@@ -296,7 +299,7 @@
         return false;
     }
 
-    /*
+    /**
      * Returns the maximum length of a sequential characters. A sequence is defined as
      * monotonically increasing characters with a constant interval or the same character repeated.
      *
@@ -310,19 +313,19 @@
      * maxLengthSequence(";;;;") == 4 (anything that repeats)
      * maxLengthSequence(":;<=>") == 1  (ordered, but not composed of alphas or digits)
      *
-     * @param string the pass
+     * @param bytes the pass
      * @return the number of sequential letters or digits
      */
-    public static int maxLengthSequence(@NonNull String string) {
-        if (string.length() == 0) return 0;
-        char previousChar = string.charAt(0);
+    public static int maxLengthSequence(@NonNull byte[] bytes) {
+        if (bytes.length == 0) return 0;
+        char previousChar = (char) bytes[0];
         @CharacterCatagory int category = categoryChar(previousChar); //current sequence category
         int diff = 0; //difference between two consecutive characters
         boolean hasDiff = false; //if we are currently targeting a sequence
         int maxLength = 0; //maximum length of a sequence already found
         int startSequence = 0; //where the current sequence started
-        for (int current = 1; current < string.length(); current++) {
-            char currentChar = string.charAt(current);
+        for (int current = 1; current < bytes.length; current++) {
+            char currentChar = (char) bytes[current];
             @CharacterCatagory int categoryCurrent = categoryChar(currentChar);
             int currentDiff = (int) currentChar - (int) previousChar;
             if (categoryCurrent != category || Math.abs(currentDiff) > maxDiffCategory(category)) {
@@ -341,7 +344,7 @@
             }
             previousChar = currentChar;
         }
-        maxLength = Math.max(maxLength, string.length() - startSequence);
+        maxLength = Math.max(maxLength, bytes.length - startSequence);
         return maxLength;
     }
 
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 9a77802..1c5816c 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -36,17 +36,17 @@
     boolean getBoolean(in String key, in boolean defaultValue, in int userId);
     long getLong(in String key, in long defaultValue, in int userId);
     String getString(in String key, in String defaultValue, in int userId);
-    void setLockCredential(in String credential, int type, in String savedCredential, int requestedQuality, int userId);
+    void setLockCredential(in byte[] credential, int type, in byte[] savedCredential, int requestedQuality, int userId);
     void resetKeyStore(int userId);
-    VerifyCredentialResponse checkCredential(in String credential, int type, int userId,
+    VerifyCredentialResponse checkCredential(in byte[] credential, int type, int userId,
             in ICheckCredentialProgressCallback progressCallback);
-    VerifyCredentialResponse verifyCredential(in String credential, int type, long challenge, int userId);
-    VerifyCredentialResponse verifyTiedProfileChallenge(String credential, int type, long challenge, int userId);
+    VerifyCredentialResponse verifyCredential(in byte[] credential, int type, long challenge, int userId);
+    VerifyCredentialResponse verifyTiedProfileChallenge(in byte[] credential, int type, long challenge, int userId);
     boolean checkVoldPassword(int userId);
     boolean havePattern(int userId);
     boolean havePassword(int userId);
-    byte[] getHashFactor(String currentCredential, int userId);
-    void setSeparateProfileChallengeEnabled(int userId, boolean enabled, String managedUserPassword);
+    byte[] getHashFactor(in byte[] currentCredential, int userId);
+    void setSeparateProfileChallengeEnabled(int userId, boolean enabled, in byte[] managedUserPassword);
     boolean getSeparateProfileChallengeEnabled(int userId);
     void registerStrongAuthTracker(in IStrongAuthTracker tracker);
     void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index 586ece0..bda3b57 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -150,12 +150,33 @@
      * @param challenge The challenge to verify against the pattern.
      * @param userId The user to check against the pattern.
      * @param callback The callback to be invoked with the verification result.
+     *
+     * @deprecated Pass the password as a byte array.
      */
+    @Deprecated
     public static AsyncTask<?, ?, ?> verifyPassword(final LockPatternUtils utils,
             final String password,
             final long challenge,
             final int userId,
             final OnVerifyCallback callback) {
+        byte[] passwordBytes = password != null ? password.getBytes() : null;
+        return verifyPassword(utils, passwordBytes, challenge, userId, callback);
+    }
+
+    /**
+     * Verify a password asynchronously.
+     *
+     * @param utils The LockPatternUtils instance to use.
+     * @param password The password to check.
+     * @param challenge The challenge to verify against the pattern.
+     * @param userId The user to check against the pattern.
+     * @param callback The callback to be invoked with the verification result.
+     */
+    public static AsyncTask<?, ?, ?> verifyPassword(final LockPatternUtils utils,
+            final byte[] password,
+            final long challenge,
+            final int userId,
+            final OnVerifyCallback callback) {
         AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
             private int mThrottleTimeout;
 
@@ -188,7 +209,7 @@
      * @param callback The callback to be invoked with the verification result.
      */
     public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
-            final String password,
+            final byte[] password,
             final boolean isPattern,
             final long challenge,
             final int userId,
@@ -222,18 +243,36 @@
      * @param password The password to check.
      * @param userId The user to check against the pattern.
      * @param callback The callback to be invoked with the check result.
+     * @deprecated Pass passwords as byte[]
      */
+    @Deprecated
     public static AsyncTask<?, ?, ?> checkPassword(final LockPatternUtils utils,
             final String password,
             final int userId,
             final OnCheckCallback callback) {
+        byte[] passwordBytes = password != null ? password.getBytes() : null;
+        return checkPassword(utils, passwordBytes, userId, callback);
+    }
+
+    /**
+     * Checks a password asynchronously.
+     *
+     * @param utils The LockPatternUtils instance to use.
+     * @param passwordBytes The password to check.
+     * @param userId The user to check against the pattern.
+     * @param callback The callback to be invoked with the check result.
+     */
+    public static AsyncTask<?, ?, ?> checkPassword(final LockPatternUtils utils,
+            final byte[] passwordBytes,
+            final int userId,
+            final OnCheckCallback callback) {
         AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
             private int mThrottleTimeout;
 
             @Override
             protected Boolean doInBackground(Void... args) {
                 try {
-                    return utils.checkPassword(password, userId, callback::onEarlyMatched);
+                    return utils.checkPassword(passwordBytes, userId, callback::onEarlyMatched);
                 } catch (RequestThrottledException ex) {
                     mThrottleTimeout = ex.getTimeoutMs();
                     return false;
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 8d3c482..17ed2a0 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -67,6 +67,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.StringJoiner;
@@ -356,7 +357,7 @@
                 null /* componentName */, userId);
     }
 
-    private byte[] verifyCredential(String credential, int type, long challenge, int userId)
+    private byte[] verifyCredential(byte[] credential, int type, long challenge, int userId)
             throws RequestThrottledException {
         try {
             VerifyCredentialResponse response = getLockSettings().verifyCredential(credential,
@@ -373,7 +374,7 @@
         }
     }
 
-    private boolean checkCredential(String credential, int type, int userId,
+    private boolean checkCredential(byte[] credential, int type, int userId,
             @Nullable CheckCredentialProgressCallback progressCallback)
             throws RequestThrottledException {
         try {
@@ -404,7 +405,7 @@
     public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)
             throws RequestThrottledException {
         throwIfCalledOnMainThread();
-        return verifyCredential(patternToString(pattern), CREDENTIAL_TYPE_PATTERN, challenge,
+        return verifyCredential(patternToByteArray(pattern), CREDENTIAL_TYPE_PATTERN, challenge,
                 userId);
     }
 
@@ -429,7 +430,7 @@
             @Nullable CheckCredentialProgressCallback progressCallback)
             throws RequestThrottledException {
         throwIfCalledOnMainThread();
-        return checkCredential(patternToString(pattern), CREDENTIAL_TYPE_PATTERN, userId,
+        return checkCredential(patternToByteArray(pattern), CREDENTIAL_TYPE_PATTERN, userId,
                 progressCallback);
     }
 
@@ -442,7 +443,7 @@
      * @param challenge The challenge to verify against the password
      * @return the attestation that the challenge was verified, or null.
      */
-    public byte[] verifyPassword(String password, long challenge, int userId)
+    public byte[] verifyPassword(byte[] password, long challenge, int userId)
             throws RequestThrottledException {
         throwIfCalledOnMainThread();
         return verifyCredential(password, CREDENTIAL_TYPE_PASSWORD, challenge, userId);
@@ -458,7 +459,7 @@
      * @param challenge The challenge to verify against the password
      * @return the attestation that the challenge was verified, or null.
      */
-    public byte[] verifyTiedProfileChallenge(String password, boolean isPattern, long challenge,
+    public byte[] verifyTiedProfileChallenge(byte[] password, boolean isPattern, long challenge,
             int userId) throws RequestThrottledException {
         throwIfCalledOnMainThread();
         try {
@@ -480,22 +481,53 @@
     }
 
     /**
+     *
      * Check to see if a password matches the saved password.  If no password exists,
      * always returns true.
      * @param password The password to check.
      * @return Whether the password matches the stored one.
      */
     public boolean checkPassword(String password, int userId) throws RequestThrottledException {
+        byte[] passwordBytes = password != null ? password.getBytes() : null;
+        return checkPassword(passwordBytes, userId, null /* progressCallback */);
+    }
+
+
+    /**
+     *
+     * Check to see if a password matches the saved password.  If no password exists,
+     * always returns true.
+     * @param password The password to check.
+     * @return Whether the password matches the stored one.
+     */
+    public boolean checkPassword(byte[] password, int userId) throws RequestThrottledException {
         return checkPassword(password, userId, null /* progressCallback */);
     }
 
+    // TODO(b/120484642): This method is necessary for vendor/qcom code and is a hidden api
+    /* *
+     * Check to see if a password matches the saved password.  If no password exists,
+     * always returns true.
+     * @param password The password to check.
+     * @return Whether the password matches the stored one.
+     */
+    public boolean checkPassword(String password, int userId,
+            @Nullable CheckCredentialProgressCallback progressCallback)
+            throws RequestThrottledException {
+        byte[] passwordBytes = password != null ? password.getBytes() : null;
+        throwIfCalledOnMainThread();
+        return checkCredential(passwordBytes, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback);
+
+    }
+
     /**
      * Check to see if a password matches the saved password.  If no password exists,
      * always returns true.
      * @param password The password to check.
      * @return Whether the password matches the stored one.
      */
-    public boolean checkPassword(String password, int userId,
+
+    public boolean checkPassword(byte[] password, int userId,
             @Nullable CheckCredentialProgressCallback progressCallback)
             throws RequestThrottledException {
         throwIfCalledOnMainThread();
@@ -519,7 +551,7 @@
      * Returns the password history hash factor, needed to check new password against password
      * history with {@link #checkPasswordHistory(String, byte[], int)}
      */
-    public byte[] getPasswordHistoryHashFactor(String currentPassword, int userId) {
+    public byte[] getPasswordHistoryHashFactor(byte[] currentPassword, int userId) {
         try {
             return getLockSettings().getHashFactor(currentPassword, userId);
         } catch (RemoteException e) {
@@ -537,8 +569,8 @@
      *        {@link ILockSettings#getHashFactor}
      * @return Whether the password matches any in the history.
      */
-    public boolean checkPasswordHistory(String passwordToCheck, byte[] hashFactor, int userId) {
-        if (TextUtils.isEmpty(passwordToCheck)) {
+    public boolean checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId) {
+        if (passwordToCheck == null || passwordToCheck.length == 0) {
             Log.e(TAG, "checkPasswordHistory: empty password");
             return false;
         }
@@ -639,13 +671,13 @@
     /**
      * Clear any lock pattern or password.
      */
-    public void clearLock(String savedCredential, int userHandle) {
+    public void clearLock(byte[] savedCredential, int userHandle) {
         final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
         setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userHandle);
 
         try{
-            getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, savedCredential,
-                    PASSWORD_QUALITY_UNSPECIFIED, userHandle);
+            getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE,
+                    savedCredential, PASSWORD_QUALITY_UNSPECIFIED, userHandle);
         } catch (Exception e) {
             Log.e(TAG, "Failed to clear lock", e);
             setKeyguardStoredPasswordQuality(currentQuality, userHandle);
@@ -704,10 +736,11 @@
     /**
      * Save a lock pattern.
      * @param pattern The new pattern to save.
-     * @param savedPattern The previously saved pattern, converted to String format
+     * @param savedPattern The previously saved pattern, converted to byte[] format
      * @param userId the user whose pattern is to be saved.
      */
-    public void saveLockPattern(List<LockPatternView.Cell> pattern, String savedPattern, int userId) {
+    public void saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern,
+            int userId) {
         if (!hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
                     "This operation requires the lock screen feature.");
@@ -717,12 +750,12 @@
                     + MIN_LOCK_PATTERN_SIZE + " dots long.");
         }
 
-        final String stringPattern = patternToString(pattern);
+        final byte[] bytePattern = patternToByteArray(pattern);
         final int currentQuality = getKeyguardStoredPasswordQuality(userId);
         setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_SOMETHING, userId);
         try {
-            getLockSettings().setLockCredential(stringPattern, CREDENTIAL_TYPE_PATTERN,
-                    savedPattern, PASSWORD_QUALITY_SOMETHING, userId);
+            getLockSettings().setLockCredential(bytePattern, CREDENTIAL_TYPE_PATTERN, savedPattern,
+                    PASSWORD_QUALITY_SOMETHING, userId);
         } catch (Exception e) {
             Log.e(TAG, "Couldn't save lock pattern", e);
             setKeyguardStoredPasswordQuality(currentQuality, userId);
@@ -734,7 +767,7 @@
             if (!shouldEncryptWithCredentials(true)) {
                 clearEncryptionPassword();
             } else {
-                updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
+                updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, bytePattern);
             }
         }
 
@@ -806,7 +839,7 @@
     }
 
     /** Update the encryption password if it is enabled **/
-    private void updateEncryptionPassword(final int type, final String password) {
+    private void updateEncryptionPassword(final int type, final byte[] password) {
         if (!hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
                     "This operation requires the lock screen feature.");
@@ -825,7 +858,9 @@
             protected Void doInBackground(Void... dummy) {
                 IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
                 try {
-                    storageManager.changeEncryptionPassword(type, password);
+                    // TODO(b/120484642): This is a location where we still use a String for vold
+                    String passwordString = password != null ? new String(password) : null;
+                    storageManager.changeEncryptionPassword(type, passwordString);
                 } catch (RemoteException e) {
                     Log.e(TAG, "Error changing encryption password", e);
                 }
@@ -842,14 +877,34 @@
      * @param savedPassword The previously saved lock password, or null if none
      * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
      * @param userHandle The userId of the user to change the password for
+     *
+     * @deprecated Pass password as a byte array
      */
+    @Deprecated
     public void saveLockPassword(String password, String savedPassword, int requestedQuality,
             int userHandle) {
+        byte[] passwordBytes = password != null ? password.getBytes() : null;
+        byte[] savedPasswordBytes = savedPassword != null ? savedPassword.getBytes() : null;
+        saveLockPassword(passwordBytes, savedPasswordBytes, requestedQuality, userHandle);
+    }
+
+    /**
+     * 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
+     * password.
+     * @param password The password to save
+     * @param savedPassword The previously saved lock password, or null if none
+     * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(
+     *          android.content.ComponentName)}
+     * @param userHandle The userId of the user to change the password for
+     */
+    public void saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality,
+            int userHandle) {
         if (!hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
                     "This operation requires the lock screen feature.");
         }
-        if (password == null || password.length() < MIN_LOCK_PASSWORD_SIZE) {
+        if (password == null || password.length < MIN_LOCK_PASSWORD_SIZE) {
             throw new IllegalArgumentException("password must not be null and at least "
                     + "of length " + MIN_LOCK_PASSWORD_SIZE);
         }
@@ -864,8 +919,8 @@
                 computePasswordQuality(CREDENTIAL_TYPE_PASSWORD, password, requestedQuality),
                 userHandle);
         try {
-            getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD,
-                    savedPassword, requestedQuality, userHandle);
+            getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
+                    requestedQuality, userHandle);
         } catch (Exception e) {
             Log.e(TAG, "Unable to save lock password", e);
             setKeyguardStoredPasswordQuality(currentQuality, userHandle);
@@ -882,7 +937,7 @@
      * Update device encryption password if calling user is USER_SYSTEM and device supports
      * encryption.
      */
-    private void updateEncryptionPasswordIfNeeded(String password, int quality, int userHandle) {
+    private void updateEncryptionPasswordIfNeeded(byte[] password, int quality, int userHandle) {
         // Update the device encryption password.
         if (userHandle == UserHandle.USER_SYSTEM
                 && LockPatternUtils.isDeviceEncryptionEnabled()) {
@@ -902,8 +957,8 @@
      * Store the hash of the *current* password in the password history list, if device policy
      * enforces password history requirement.
      */
-    private void updatePasswordHistory(String password, int userHandle) {
-        if (TextUtils.isEmpty(password)) {
+    private void updatePasswordHistory(byte[] password, int userHandle) {
+        if (password == null || password.length == 0) {
             Log.e(TAG, "checkPasswordHistory: empty password");
             return;
         }
@@ -982,7 +1037,7 @@
      * if DevicePolicyManager has a stronger quality requirement. This value will be written
      * to PASSWORD_TYPE_KEY.
      */
-    private int computePasswordQuality(int type, String credential, int requestedQuality) {
+    private int computePasswordQuality(int type, byte[] credential, int requestedQuality) {
         final int quality;
         if (type == CREDENTIAL_TYPE_PASSWORD) {
             int computedQuality = PasswordMetrics.computeForPassword(credential).quality;
@@ -1005,7 +1060,7 @@
      *            true
      */
     public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
-            String managedUserPassword) {
+            byte[] managedUserPassword) {
         if (!isManagedProfile(userHandle)) {
             return;
         }
@@ -1069,15 +1124,28 @@
      * Deserialize a pattern.
      * @param string The pattern serialized with {@link #patternToString}
      * @return The pattern.
+     * @deprecated Pass patterns as byte[] and use byteArrayToPattern
      */
+    @Deprecated
     public static List<LockPatternView.Cell> stringToPattern(String string) {
         if (string == null) {
             return null;
         }
+        return byteArrayToPattern(string.getBytes());
+    }
+
+    /**
+     * Deserialize a pattern.
+     * @param  bytes The pattern serialized with {@link #patternToByteArray}
+     * @return The pattern.
+     */
+    public static List<LockPatternView.Cell> byteArrayToPattern(byte[] bytes) {
+        if (bytes == null) {
+            return null;
+        }
 
         List<LockPatternView.Cell> result = Lists.newArrayList();
 
-        final byte[] bytes = string.getBytes();
         for (int i = 0; i < bytes.length; i++) {
             byte b = (byte) (bytes[i] - '1');
             result.add(LockPatternView.Cell.of(b / 3, b % 3));
@@ -1089,10 +1157,22 @@
      * Serialize a pattern.
      * @param pattern The pattern.
      * @return The pattern in string form.
+     * @deprecated Use patternToByteArray instead.
      */
+    @Deprecated
     public static String patternToString(List<LockPatternView.Cell> pattern) {
+        return new String(patternToByteArray(pattern));
+    }
+
+
+    /**
+     * Serialize a pattern.
+     * @param pattern The pattern.
+     * @return The pattern in byte array form.
+     */
+    public static byte[] patternToByteArray(List<LockPatternView.Cell> pattern) {
         if (pattern == null) {
-            return "";
+            return new byte[0];
         }
         final int patternSize = pattern.size();
 
@@ -1101,21 +1181,24 @@
             LockPatternView.Cell cell = pattern.get(i);
             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');
         }
-        return new String(res);
+        return res;
     }
 
-    public static String patternStringToBaseZero(String pattern) {
-        if (pattern == null) {
-            return "";
+    /**
+     * Transform a pattern byte array to base zero form.
+     * @param bytes pattern byte array.
+     * @return The pattern in base zero form.
+     */
+    public static byte[] patternByteArrayToBaseZero(byte[] bytes) {
+        if (bytes == null) {
+            return new byte[0];
         }
-        final int patternSize = pattern.length();
-
+        final int patternSize = bytes.length;
         byte[] res = new byte[patternSize];
-        final byte[] bytes = pattern.getBytes();
         for (int i = 0; i < patternSize; i++) {
             res[i] = (byte) (bytes[i] - '1');
         }
-        return new String(res);
+        return res;
     }
 
     /*
@@ -1169,13 +1252,18 @@
      *
      * @return the hash of the pattern in a byte array.
      */
-    public String legacyPasswordToHash(String password, int userId) {
-        if (password == null) {
+    public String legacyPasswordToHash(byte[] password, int userId) {
+        if (password == null || password.length == 0) {
             return null;
         }
 
         try {
-            byte[] saltedPassword = (password + getSalt(userId)).getBytes();
+            // Previously the password was passed as a String with the following code:
+            // byte[] saltedPassword = (password + getSalt(userId)).getBytes();
+            // The code below creates the identical digest preimage using byte arrays:
+            byte[] salt = getSalt(userId).getBytes();
+            byte[] saltedPassword = Arrays.copyOf(password, password.length + salt.length);
+            System.arraycopy(salt, 0, saltedPassword, password.length, salt.length);
             byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(saltedPassword);
             byte[] md5 = MessageDigest.getInstance("MD5").digest(saltedPassword);
 
@@ -1184,6 +1272,7 @@
             System.arraycopy(md5, 0, combined, sha1.length, md5.length);
 
             final char[] hexEncoded = HexEncoding.encode(combined);
+            Arrays.fill(saltedPassword, (byte) 0);
             return new String(hexEncoded);
         } catch (NoSuchAlgorithmException e) {
             throw new AssertionError("Missing digest algorithm: ", e);
@@ -1193,14 +1282,19 @@
     /**
      * Hash the password for password history check purpose.
      */
-    private String passwordToHistoryHash(String passwordToHash, byte[] hashFactor, int userId) {
-        if (TextUtils.isEmpty(passwordToHash) || hashFactor == null) {
+    private String passwordToHistoryHash(byte[] passwordToHash, byte[] hashFactor, int userId) {
+        if (passwordToHash == null || passwordToHash.length == 0 || hashFactor == null) {
             return null;
         }
         try {
             MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
             sha256.update(hashFactor);
-            sha256.update((passwordToHash + getSalt(userId)).getBytes());
+            byte[] salt = getSalt(userId).getBytes();
+            byte[] saltedPassword = Arrays.copyOf(passwordToHash, passwordToHash.length
+                    + salt.length);
+            System.arraycopy(salt, 0, saltedPassword, passwordToHash.length, salt.length);
+            sha256.update(saltedPassword);
+            Arrays.fill(saltedPassword, (byte) 0);
             return new String(HexEncoding.encode(sha256.digest()));
         } catch (NoSuchAlgorithmException e) {
             throw new AssertionError("Missing digest algorithm: ", e);
@@ -1633,7 +1727,7 @@
      * @param userId The user who's lock credential to be changed
      * @return {@code true} if the operation is successful.
      */
-    public boolean setLockCredentialWithToken(String credential, int type, int requestedQuality,
+    public boolean setLockCredentialWithToken(byte[] credential, int type, int requestedQuality,
             long tokenHandle, byte[] token, int userId) {
         if (!hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
@@ -1641,13 +1735,13 @@
         }
         LockSettingsInternal localService = getLockSettingsInternal();
         if (type != CREDENTIAL_TYPE_NONE) {
-            if (TextUtils.isEmpty(credential) || credential.length() < MIN_LOCK_PASSWORD_SIZE) {
+            if (credential == null || credential.length < MIN_LOCK_PASSWORD_SIZE) {
                 throw new IllegalArgumentException("password must not be null and at least "
                         + "of length " + MIN_LOCK_PASSWORD_SIZE);
             }
             final int quality = computePasswordQuality(type, credential, requestedQuality);
-            if (!localService.setLockCredentialWithToken(credential, type, tokenHandle,
-                    token, quality, userId)) {
+            if (!localService.setLockCredentialWithToken(credential, type, tokenHandle, token,
+                    quality, userId)) {
                 return false;
             }
             setKeyguardStoredPasswordQuality(quality, userId);
@@ -1656,11 +1750,11 @@
             updatePasswordHistory(credential, userId);
             onAfterChangingPassword(userId);
         } else {
-            if (!TextUtils.isEmpty(credential)) {
+            if (!(credential == null || credential.length == 0)) {
                 throw new IllegalArgumentException("password must be emtpy for NONE type");
             }
-            if (!localService.setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE,
-                    tokenHandle, token, PASSWORD_QUALITY_UNSPECIFIED, userId)) {
+            if (!localService.setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE, tokenHandle,
+                    token, PASSWORD_QUALITY_UNSPECIFIED, userId)) {
                 return false;
             }
             setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userId);
@@ -1891,4 +1985,22 @@
         return FRP_CREDENTIAL_ENABLED && context.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableCredentialFactoryResetProtection);
     }
+
+    /**
+     * Converts a CharSequence to a byte array without requiring a toString(), which creates an
+     * additional copy.
+     *
+     * @param chars The CharSequence to convert
+     * @return A byte array representing the input
+     */
+    public static byte[] charSequenceToByteArray(CharSequence chars) {
+        if (chars == null) {
+            return null;
+        }
+        byte[] bytes = new byte[chars.length()];
+        for (int i = 0; i < chars.length(); i++) {
+            bytes[i] = (byte) chars.charAt(i);
+        }
+        return bytes;
+    }
 }
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 25a5a07..4b26990 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -1273,8 +1273,10 @@
     @Override
     protected Parcelable onSaveInstanceState() {
         Parcelable superState = super.onSaveInstanceState();
+        byte[] patternBytes = LockPatternUtils.patternToByteArray(mPattern);
+        String patternString = patternBytes != null ? new String(patternBytes) : null;
         return new SavedState(superState,
-                LockPatternUtils.patternToString(mPattern),
+                patternString,
                 mPatternDisplayMode.ordinal(),
                 mInputEnabled, mInStealthMode, mEnableHapticFeedback);
     }
diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java
index 9de9ef7..90397df 100644
--- a/core/java/com/android/internal/widget/LockSettingsInternal.java
+++ b/core/java/com/android/internal/widget/LockSettingsInternal.java
@@ -49,7 +49,11 @@
      */
     public abstract boolean isEscrowTokenActive(long handle, int userId);
 
-    public abstract boolean setLockCredentialWithToken(String credential, int type,
+    /**
+     * Set the lock credential.
+     * @return true if password is set.
+     */
+    public abstract boolean setLockCredentialWithToken(byte[] credential, int type,
             long tokenHandle, byte[] token, int requestedQuality, int userId);
 
     public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId);
diff --git a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
index 5731daa..4ae9494 100644
--- a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
+++ b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
@@ -99,7 +99,8 @@
 
     @Test
     public void testComputeForPassword_metrics() {
-        final PasswordMetrics metrics = PasswordMetrics.computeForPassword("6B~0z1Z3*8A");
+        final PasswordMetrics metrics =
+                PasswordMetrics.computeForPassword("6B~0z1Z3*8A".getBytes());
         assertEquals(11, metrics.length);
         assertEquals(4, metrics.letters);
         assertEquals(3, metrics.upperCase);
@@ -112,32 +113,32 @@
     @Test
     public void testComputeForPassword_quality() {
         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
-                PasswordMetrics.computeForPassword("a1").quality);
+                PasswordMetrics.computeForPassword("a1".getBytes()).quality);
         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
-                PasswordMetrics.computeForPassword("a").quality);
+                PasswordMetrics.computeForPassword("a".getBytes()).quality);
         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
-                PasswordMetrics.computeForPassword("*~&%$").quality);
+                PasswordMetrics.computeForPassword("*~&%$".getBytes()).quality);
         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX,
-                PasswordMetrics.computeForPassword("1").quality);
+                PasswordMetrics.computeForPassword("1".getBytes()).quality);
         // contains a long sequence so isn't complex
         assertEquals(PASSWORD_QUALITY_NUMERIC,
-                PasswordMetrics.computeForPassword("1234").quality);
+                PasswordMetrics.computeForPassword("1234".getBytes()).quality);
         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
-                PasswordMetrics.computeForPassword("").quality);
+                PasswordMetrics.computeForPassword("".getBytes()).quality);
     }
 
     @Test
     public void testMaxLengthSequence() {
-        assertEquals(4, PasswordMetrics.maxLengthSequence("1234"));
-        assertEquals(5, PasswordMetrics.maxLengthSequence("13579"));
-        assertEquals(4, PasswordMetrics.maxLengthSequence("1234abd"));
-        assertEquals(3, PasswordMetrics.maxLengthSequence("aabc"));
-        assertEquals(1, PasswordMetrics.maxLengthSequence("qwertyuio"));
-        assertEquals(3, PasswordMetrics.maxLengthSequence("@ABC"));
+        assertEquals(4, PasswordMetrics.maxLengthSequence("1234".getBytes()));
+        assertEquals(5, PasswordMetrics.maxLengthSequence("13579".getBytes()));
+        assertEquals(4, PasswordMetrics.maxLengthSequence("1234abd".getBytes()));
+        assertEquals(3, PasswordMetrics.maxLengthSequence("aabc".getBytes()));
+        assertEquals(1, PasswordMetrics.maxLengthSequence("qwertyuio".getBytes()));
+        assertEquals(3, PasswordMetrics.maxLengthSequence("@ABC".getBytes()));
         // anything that repeats
-        assertEquals(4, PasswordMetrics.maxLengthSequence(";;;;"));
+        assertEquals(4, PasswordMetrics.maxLengthSequence(";;;;".getBytes()));
         // ordered, but not composed of alphas or digits
-        assertEquals(1, PasswordMetrics.maxLengthSequence(":;<=>"));
+        assertEquals(1, PasswordMetrics.maxLengthSequence(":;<=>".getBytes()));
     }
 
     @Test
@@ -158,8 +159,8 @@
         assertNotEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
                 new PasswordMetrics(PASSWORD_QUALITY_COMPLEX, 4));
 
-        metrics0 = PasswordMetrics.computeForPassword("1234abcd,./");
-        metrics1 = PasswordMetrics.computeForPassword("1234abcd,./");
+        metrics0 = PasswordMetrics.computeForPassword("1234abcd,./".getBytes());
+        metrics1 = PasswordMetrics.computeForPassword("1234abcd,./".getBytes());
         assertEquals(metrics0, metrics1);
         metrics1.letters++;
         assertNotEquals(metrics0, metrics1);
@@ -197,7 +198,7 @@
     @Test
     public void testDetermineComplexity_none() {
         assertEquals(PASSWORD_COMPLEXITY_NONE,
-                PasswordMetrics.computeForPassword("").determineComplexity());
+                PasswordMetrics.computeForPassword("".getBytes()).determineComplexity());
     }
 
     @Test
@@ -209,61 +210,61 @@
     @Test
     public void testDetermineComplexity_lowNumeric() {
         assertEquals(PASSWORD_COMPLEXITY_LOW,
-                PasswordMetrics.computeForPassword("1234").determineComplexity());
+                PasswordMetrics.computeForPassword("1234".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_lowNumericComplex() {
         assertEquals(PASSWORD_COMPLEXITY_LOW,
-                PasswordMetrics.computeForPassword("124").determineComplexity());
+                PasswordMetrics.computeForPassword("124".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_lowAlphabetic() {
         assertEquals(PASSWORD_COMPLEXITY_LOW,
-                PasswordMetrics.computeForPassword("a!").determineComplexity());
+                PasswordMetrics.computeForPassword("a!".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_lowAlphanumeric() {
         assertEquals(PASSWORD_COMPLEXITY_LOW,
-                PasswordMetrics.computeForPassword("a!1").determineComplexity());
+                PasswordMetrics.computeForPassword("a!1".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_mediumNumericComplex() {
         assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
-                PasswordMetrics.computeForPassword("1238").determineComplexity());
+                PasswordMetrics.computeForPassword("1238".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_mediumAlphabetic() {
         assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
-                PasswordMetrics.computeForPassword("ab!c").determineComplexity());
+                PasswordMetrics.computeForPassword("ab!c".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_mediumAlphanumeric() {
         assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
-                PasswordMetrics.computeForPassword("ab!1").determineComplexity());
+                PasswordMetrics.computeForPassword("ab!1".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_highNumericComplex() {
         assertEquals(PASSWORD_COMPLEXITY_HIGH,
-                PasswordMetrics.computeForPassword("12389647!").determineComplexity());
+                PasswordMetrics.computeForPassword("12389647!".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_highAlphabetic() {
         assertEquals(PASSWORD_COMPLEXITY_HIGH,
-                PasswordMetrics.computeForPassword("alphabetic!").determineComplexity());
+                PasswordMetrics.computeForPassword("alphabetic!".getBytes()).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_highAlphanumeric() {
-        assertEquals(PASSWORD_COMPLEXITY_HIGH,
-                PasswordMetrics.computeForPassword("alphanumeric123!").determineComplexity());
+        assertEquals(PASSWORD_COMPLEXITY_HIGH, PasswordMetrics.computeForPassword(
+                "alphanumeric123!".getBytes()).determineComplexity());
     }
 
     @Test
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index a055950..4cb8d90 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -34,6 +34,8 @@
 import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
 
+import java.util.Arrays;
+
 /**
  * Base class for PIN and password unlock screens.
  */
@@ -124,18 +126,19 @@
     protected void verifyPasswordAndUnlock() {
         if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
 
-        final String entry = getPasswordText();
+        final byte[] entry = getPasswordText();
         setPasswordEntryInputEnabled(false);
         if (mPendingLockCheck != null) {
             mPendingLockCheck.cancel(false);
         }
 
         final int userId = KeyguardUpdateMonitor.getCurrentUser();
-        if (entry.length() <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
+        if (entry.length <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
             // to avoid accidental lockout, only count attempts that are long enough to be a
             // real password. This may require some tweaking.
             setPasswordEntryInputEnabled(true);
             onPasswordChecked(userId, false /* matched */, 0, false /* not valid - too short */);
+            Arrays.fill(entry, (byte) 0);
             return;
         }
 
@@ -157,6 +160,7 @@
                         }
                         onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
                                 true /* isValidPassword */);
+                        Arrays.fill(entry, (byte) 0);
                     }
 
                     @Override
@@ -171,6 +175,7 @@
                             onPasswordChecked(userId, false /* matched */, timeoutMs,
                                     true /* isValidPassword */);
                         }
+                        Arrays.fill(entry, (byte) 0);
                     }
 
                     @Override
@@ -181,6 +186,7 @@
                             LatencyTracker.getInstance(mContext).onActionEnd(
                                     ACTION_CHECK_CREDENTIAL_UNLOCKED);
                         }
+                        Arrays.fill(entry, (byte) 0);
                     }
                 });
     }
@@ -211,7 +217,7 @@
     }
 
     protected abstract void resetPasswordText(boolean animate, boolean announce);
-    protected abstract String getPasswordText();
+    protected abstract byte[] getPasswordText();
     protected abstract void setPasswordEntryEnabled(boolean enabled);
     protected abstract void setPasswordEntryInputEnabled(boolean enabled);
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 261f391..185edbf 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -241,8 +241,8 @@
     }
 
     @Override
-    protected String getPasswordText() {
-        return mPasswordEntry.getText().toString();
+    protected byte[] getPasswordText() {
+        return charSequenceToByteArray(mPasswordEntry.getText());
     }
 
     @Override
@@ -377,4 +377,18 @@
         return getContext().getString(
                 com.android.internal.R.string.keyguard_accessibility_password_unlock);
     }
+
+    /*
+     * This method avoids creating a new string when getting a byte array from EditView#getText().
+     */
+    private static byte[] charSequenceToByteArray(CharSequence chars) {
+        if (chars == null) {
+            return null;
+        }
+        byte[] bytes = new byte[chars.length()];
+        for (int i = 0; i < chars.length(); i++) {
+            bytes[i] = (byte) chars.charAt(i);
+        }
+        return bytes;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 3cc18dd..ecafc34 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -165,8 +165,8 @@
     }
 
     @Override
-    protected String getPasswordText() {
-        return mPasswordEntry.getText();
+    protected byte[] getPasswordText() {
+        return charSequenceToByteArray(mPasswordEntry.getText());
     }
 
     @Override
@@ -264,4 +264,18 @@
         return getContext().getString(
                 com.android.internal.R.string.keyguard_accessibility_pin_unlock);
     }
+
+    /*
+     * This method avoids creating a new string when getting a byte array from EditView#getText().
+     */
+    private static byte[] charSequenceToByteArray(CharSequence chars) {
+        if (chars == null) {
+            return null;
+        }
+        byte[] bytes = new byte[chars.length()];
+        for (int i = 0; i < chars.length(); i++) {
+            bytes[i] = (byte) chars.charAt(i);
+        }
+        return bytes;
+    }
 }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index d83eb08..ee968c8 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -123,7 +123,6 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.KeyStoreException;
@@ -277,7 +276,7 @@
      * @param managedUserPassword Managed profile original password (when it has separated lock).
      *            NULL when it does not have a separated lock before.
      */
-    public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) {
+    public void tieManagedProfileLockIfNecessary(int managedUserId, byte[] managedUserPassword) {
         if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
         // Only for managed profile
         if (!mUserManager.getUserInfo(managedUserId).isManagedProfile()) {
@@ -312,7 +311,12 @@
         byte[] randomLockSeed = new byte[] {};
         try {
             randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
-            String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
+            char[] newPasswordChars = HexEncoding.encode(randomLockSeed);
+            byte[] newPassword = new byte[newPasswordChars.length];
+            for (int i = 0; i < newPasswordChars.length; i++) {
+                newPassword[i] = (byte) newPasswordChars[i];
+            }
+            Arrays.fill(newPasswordChars, '\u0000');
             final int quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
             setLockCredentialInternal(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
                     managedUserPassword, quality, managedUserId);
@@ -321,6 +325,7 @@
             // password directly, so we always store a password.
             setLong(LockPatternUtils.PASSWORD_TYPE_KEY, quality, managedUserId);
             tieProfileLockToParent(managedUserId, newPassword);
+            Arrays.fill(newPassword, (byte) 0);
         } catch (NoSuchAlgorithmException | RemoteException e) {
             Slog.e(TAG, "Fail to tie managed profile", e);
             // Nothing client can do to fix this issue, so we do not throw exception out
@@ -618,7 +623,7 @@
 
             try {
                 final long handle = getSyntheticPasswordHandleLocked(userId);
-                final String noCredential = null;
+                final byte[] noCredential = null;
                 AuthenticationResult result =
                         mSpManager.unwrapPasswordBasedSyntheticPassword(
                                 getGateKeeperService(), handle, noCredential, userId, null);
@@ -956,7 +961,7 @@
 
     @Override
     public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
-            String managedUserPassword) {
+            byte[] managedUserPassword) {
         checkWritePermission(userId);
         if (!mLockPatternUtils.hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
@@ -969,8 +974,8 @@
     }
 
     @GuardedBy("mSeparateChallengeLock")
-    private void setSeparateProfileChallengeEnabledLocked(@UserIdInt int userId, boolean enabled,
-            String managedUserPassword) {
+    private void setSeparateProfileChallengeEnabledLocked(@UserIdInt int userId,
+            boolean enabled, byte[] managedUserPassword) {
         final boolean old = getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
         setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
         try {
@@ -1113,24 +1118,28 @@
         return mStorage.hasCredential(userId);
     }
 
-    private void setKeystorePassword(String password, int userHandle) {
+    private void setKeystorePassword(byte[] password, int userHandle) {
         final KeyStore ks = KeyStore.getInstance();
-        ks.onUserPasswordChanged(userHandle, password);
+        // TODO(b/120484642): Update keystore to accept byte[] passwords
+        String passwordString = password == null ? null : new String(password);
+        ks.onUserPasswordChanged(userHandle, passwordString);
     }
 
-    private void unlockKeystore(String password, int userHandle) {
+    private void unlockKeystore(byte[] password, int userHandle) {
         if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
+        // TODO(b/120484642): Update keystore to accept byte[] passwords
+        String passwordString = password == null ? null : new String(password);
         final KeyStore ks = KeyStore.getInstance();
-        ks.unlock(userHandle, password);
+        ks.unlock(userHandle, passwordString);
     }
 
     @VisibleForTesting
-    protected String getDecryptedPasswordForTiedProfile(int userId)
+    protected byte[] getDecryptedPasswordForTiedProfile(int userId)
             throws KeyStoreException, UnrecoverableKeyException,
             NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
             InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
             CertificateException, IOException {
-        if (DEBUG) Slog.v(TAG, "Get child profile decrytped key");
+        if (DEBUG) Slog.v(TAG, "Get child profile decrypted key");
         byte[] storedData = mStorage.readChildProfileLock(userId);
         if (storedData == null) {
             throw new FileNotFoundException("Child profile lock file not found");
@@ -1149,7 +1158,7 @@
 
         cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
         decryptionResult = cipher.doFinal(encryptedPassword);
-        return new String(decryptionResult, StandardCharsets.UTF_8);
+        return decryptionResult;
     }
 
     private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated)
@@ -1226,11 +1235,11 @@
                 && mUserManager.isUserRunning(userInfo.id);
     }
 
-    private Map<Integer, String> getDecryptedPasswordsForAllTiedProfiles(int userId) {
+    private Map<Integer, byte[]> getDecryptedPasswordsForAllTiedProfiles(int userId) {
         if (mUserManager.getUserInfo(userId).isManagedProfile()) {
             return null;
         }
-        Map<Integer, String> result = new ArrayMap<Integer, String>();
+        Map<Integer, byte[]> result = new ArrayMap<Integer, byte[]>();
         final List<UserInfo> profiles = mUserManager.getProfiles(userId);
         final int size = profiles.size();
         for (int i = 0; i < size; i++) {
@@ -1268,7 +1277,7 @@
      * terminates when the user is a managed profile.
      */
     private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
-            Map<Integer, String> profilePasswordMap) throws RemoteException {
+            Map<Integer, byte[]> profilePasswordMap) throws RemoteException {
         if (mUserManager.getUserInfo(userId).isManagedProfile()) {
             return;
         }
@@ -1317,9 +1326,10 @@
     // This method should be called by LockPatternUtil only, all internal methods in this class
     // should call setLockCredentialInternal.
     @Override
-    public void setLockCredential(String credential, int type, String savedCredential,
-            int requestedQuality, int userId)
+    public void setLockCredential(byte[] credential, int type,
+            byte[] savedCredential, int requestedQuality, int userId)
             throws RemoteException {
+
         if (!mLockPatternUtils.hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
                     "This operation requires secure lock screen feature");
@@ -1333,14 +1343,14 @@
         notifySeparateProfileChallengeChanged(userId);
     }
 
-    private void setLockCredentialInternal(String credential, int credentialType,
-            String savedCredential, int requestedQuality, int userId) throws RemoteException {
+    private void setLockCredentialInternal(byte[] credential, int credentialType,
+            byte[] savedCredential, int requestedQuality, int userId) throws RemoteException {
         // Normalize savedCredential and credential such that empty string is always represented
         // as null.
-        if (TextUtils.isEmpty(savedCredential)) {
+        if (savedCredential == null || savedCredential.length == 0) {
             savedCredential = null;
         }
-        if (TextUtils.isEmpty(credential)) {
+        if (credential == null || credential.length == 0) {
             credential = null;
         }
         synchronized (mSpManager) {
@@ -1409,7 +1419,7 @@
             mStorage.writeCredentialHash(willStore, userId);
             // push new secret and auth token to vold
             GateKeeperResponse gkResponse = getGateKeeperService()
-                    .verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
+                    .verifyChallenge(userId, 0, willStore.hash, credential);
             setUserKeyProtection(userId, credential, convertResponse(gkResponse));
             fixateNewestUserKeyAuth(userId);
             // Refresh the auth token
@@ -1429,9 +1439,8 @@
     }
 
     @VisibleForTesting
-    protected void tieProfileLockToParent(int userId, String password) {
+    protected void tieProfileLockToParent(int userId, byte[] password) {
         if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
-        byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8);
         byte[] encryptionResult;
         byte[] iv;
         try {
@@ -1465,7 +1474,7 @@
                         KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
                                 + KeyProperties.ENCRYPTION_PADDING_NONE);
                 cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
-                encryptionResult = cipher.doFinal(randomLockSeed);
+                encryptionResult = cipher.doFinal(password);
                 iv = cipher.getIV();
             } finally {
                 // The original key can now be discarded.
@@ -1490,17 +1499,11 @@
     }
 
     private byte[] enrollCredential(byte[] enrolledHandle,
-            String enrolledCredential, String toEnroll, int userId)
+            byte[] enrolledCredential, byte[] toEnroll, int userId)
             throws RemoteException {
         checkWritePermission(userId);
-        byte[] enrolledCredentialBytes = enrolledCredential == null
-                ? null
-                : enrolledCredential.getBytes();
-        byte[] toEnrollBytes = toEnroll == null
-                ? null
-                : toEnroll.getBytes();
         GateKeeperResponse response = getGateKeeperService().enroll(userId, enrolledHandle,
-                enrolledCredentialBytes, toEnrollBytes);
+                enrolledCredential, toEnroll);
 
         if (response == null) {
             return null;
@@ -1521,7 +1524,7 @@
         addUserKeyAuth(userId, null, key);
     }
 
-    private void setUserKeyProtection(int userId, String credential, VerifyCredentialResponse vcr)
+    private void setUserKeyProtection(int userId, byte[] credential, VerifyCredentialResponse vcr)
             throws RemoteException {
         if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId);
         if (vcr == null) {
@@ -1543,16 +1546,15 @@
         addUserKeyAuth(userId, null, null);
     }
 
-    private static byte[] secretFromCredential(String credential) throws RemoteException {
+    private static byte[] secretFromCredential(byte[] credential) throws RemoteException {
         try {
             MessageDigest digest = MessageDigest.getInstance("SHA-512");
             // Personalize the hash
-            byte[] personalization = "Android FBE credential hash"
-                    .getBytes(StandardCharsets.UTF_8);
+            byte[] personalization = "Android FBE credential hash".getBytes();
             // Pad it to the block size of the hash function
             personalization = Arrays.copyOf(personalization, 128);
             digest.update(personalization);
-            digest.update(credential.getBytes(StandardCharsets.UTF_8));
+            digest.update(credential);
             return digest.digest();
         } catch (NoSuchAlgorithmException e) {
             throw new RuntimeException("NoSuchAlgorithmException for SHA-512");
@@ -1588,7 +1590,7 @@
         checkWritePermission(userId);
         if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
         int managedUserId = -1;
-        String managedUserDecryptedPassword = null;
+        byte[] managedUserDecryptedPassword = null;
         final List<UserInfo> profiles = mUserManager.getProfiles(userId);
         for (UserInfo pi : profiles) {
             // Unlock managed profile with unified lock
@@ -1625,17 +1627,20 @@
                 tieProfileLockToParent(managedUserId, managedUserDecryptedPassword);
             }
         }
+        if (managedUserDecryptedPassword != null && managedUserDecryptedPassword.length > 0) {
+            Arrays.fill(managedUserDecryptedPassword, (byte) 0);
+        }
     }
 
     @Override
-    public VerifyCredentialResponse checkCredential(String credential, int type, int userId,
+    public VerifyCredentialResponse checkCredential(byte[] credential, int type, int userId,
             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
         checkPasswordReadPermission(userId);
         return doVerifyCredential(credential, type, false, 0, userId, progressCallback);
     }
 
     @Override
-    public VerifyCredentialResponse verifyCredential(String credential, int type, long challenge,
+    public VerifyCredentialResponse verifyCredential(byte[] credential, int type, long challenge,
             int userId) throws RemoteException {
         checkPasswordReadPermission(userId);
         return doVerifyCredential(credential, type, true, challenge, userId,
@@ -1646,10 +1651,10 @@
      * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero
      * format.
      */
-    private VerifyCredentialResponse doVerifyCredential(String credential, int credentialType,
+    private VerifyCredentialResponse doVerifyCredential(byte[] credential, int credentialType,
             boolean hasChallenge, long challenge, int userId,
             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
-        if (TextUtils.isEmpty(credential)) {
+        if (credential == null || credential.length == 0) {
             throw new IllegalArgumentException("Credential can't be null or empty");
         }
         if (userId == USER_FRP && Settings.Global.getInt(mContext.getContentResolver(),
@@ -1684,9 +1689,9 @@
         boolean shouldReEnrollBaseZero = storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN
                 && storedHash.isBaseZeroPattern;
 
-        String credentialToVerify;
+        byte[] credentialToVerify;
         if (shouldReEnrollBaseZero) {
-            credentialToVerify = LockPatternUtils.patternStringToBaseZero(credential);
+            credentialToVerify = LockPatternUtils.patternByteArrayToBaseZero(credential);
         } else {
             credentialToVerify = credential;
         }
@@ -1706,7 +1711,7 @@
     }
 
     @Override
-    public VerifyCredentialResponse verifyTiedProfileChallenge(String credential, int type,
+    public VerifyCredentialResponse verifyTiedProfileChallenge(byte[] credential, int type,
             long challenge, int userId) throws RemoteException {
         checkPasswordReadPermission(userId);
         if (!isManagedProfileWithUnifiedLock(userId)) {
@@ -1748,14 +1753,15 @@
      * hash to GK.
      */
     private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
-            String credential, boolean hasChallenge, long challenge,
+            byte[] credential, boolean hasChallenge, long challenge,
             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
-        if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) {
+        if ((storedHash == null || storedHash.hash.length == 0)
+                    && (credential == null || credential.length == 0)) {
             // don't need to pass empty credentials to GateKeeper
             return VerifyCredentialResponse.OK;
         }
 
-        if (storedHash == null || TextUtils.isEmpty(credential)) {
+        if (storedHash == null || credential == null || credential.length == 0) {
             return VerifyCredentialResponse.ERROR;
         }
 
@@ -1766,14 +1772,14 @@
         if (storedHash.version == CredentialHash.VERSION_LEGACY) {
             final byte[] hash;
             if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
-                hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(credential));
+                hash = LockPatternUtils.patternToHash(
+                        LockPatternUtils.byteArrayToPattern(credential));
             } else {
-                hash = mLockPatternUtils.legacyPasswordToHash(credential, userId)
-                        .getBytes(StandardCharsets.UTF_8);
+                hash = mLockPatternUtils.legacyPasswordToHash(credential, userId).getBytes();
             }
             if (Arrays.equals(hash, storedHash.hash)) {
                 if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
-                    unlockKeystore(LockPatternUtils.patternStringToBaseZero(credential), userId);
+                    unlockKeystore(LockPatternUtils.patternByteArrayToBaseZero(credential), userId);
                 } else {
                     unlockKeystore(credential, userId);
                 }
@@ -1804,7 +1810,7 @@
             }
         }
         GateKeeperResponse gateKeeperResponse = getGateKeeperService()
-                .verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
+                .verifyChallenge(userId, challenge, storedHash.hash, credential);
         VerifyCredentialResponse response = convertResponse(gateKeeperResponse);
         boolean shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
 
@@ -1863,7 +1869,7 @@
      * Call this method to notify DPMS regarding the latest password metric. This should be called
      * when the user is authenticating or when a new password is being set.
      */
-    private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) {
+    private void notifyActivePasswordMetricsAvailable(byte[] password, @UserIdInt int userId) {
         final PasswordMetrics metrics;
         if (password == null) {
             metrics = new PasswordMetrics();
@@ -1912,6 +1918,7 @@
         // service can't connect to vold, it restarts, and then the new instance
         // does successfully connect.
         final IStorageManager service = mInjector.getStorageManager();
+        // TODO(b/120484642): Update vold to return a password as a byte array
         String password;
         long identity = Binder.clearCallingIdentity();
         try {
@@ -1926,8 +1933,8 @@
 
         try {
             if (mLockPatternUtils.isLockPatternEnabled(userId)) {
-                if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, userId,
-                        null /* progressCallback */)
+                if (checkCredential(password.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+                        userId, null /* progressCallback */)
                                 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
                     return true;
                 }
@@ -1937,8 +1944,8 @@
 
         try {
             if (mLockPatternUtils.isLockPasswordEnabled(userId)) {
-                if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, userId,
-                        null /* progressCallback */)
+                if (checkCredential(password.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+                        userId, null /* progressCallback */)
                                 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
                     return true;
                 }
@@ -2323,7 +2330,7 @@
     @GuardedBy("mSpManager")
     @VisibleForTesting
     protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
-            String credential, int credentialType, int requestedQuality,
+            byte[] credential, int credentialType, int requestedQuality,
             int userId) throws RemoteException {
         Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
         final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(
@@ -2384,7 +2391,7 @@
         setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
     }
 
-    private VerifyCredentialResponse spBasedDoVerifyCredential(String userCredential, int
+    private VerifyCredentialResponse spBasedDoVerifyCredential(byte[] userCredential, int
             credentialType, boolean hasChallenge, long challenge, int userId,
             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
         if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId);
@@ -2483,12 +2490,12 @@
      * added back when new password is set in future.
      */
     @GuardedBy("mSpManager")
-    private long setLockCredentialWithAuthTokenLocked(String credential, int credentialType,
+    private long setLockCredentialWithAuthTokenLocked(byte[] credential, int credentialType,
             AuthenticationToken auth, int requestedQuality, int userId) throws RemoteException {
         if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId);
         long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
                 credential, credentialType, auth, requestedQuality, userId);
-        final Map<Integer, String> profilePasswords;
+        final Map<Integer, byte[]> profilePasswords;
         if (credential != null) {
             // // not needed by synchronizeUnifiedWorkChallengeForProfiles()
             profilePasswords = null;
@@ -2527,12 +2534,19 @@
         synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
 
         notifyActivePasswordMetricsAvailable(credential, userId);
+
+        if (profilePasswords != null) {
+            for (Map.Entry<Integer, byte[]> entry : profilePasswords.entrySet()) {
+                Arrays.fill(entry.getValue(), (byte) 0);
+            }
+        }
+
         return newHandle;
     }
 
     @GuardedBy("mSpManager")
-    private void spBasedSetLockCredentialInternalLocked(String credential, int credentialType,
-            String savedCredential, int requestedQuality, int userId) throws RemoteException {
+    private void spBasedSetLockCredentialInternalLocked(byte[] credential, int credentialType,
+            byte[] savedCredential, int requestedQuality, int userId) throws RemoteException {
         if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
         if (isManagedProfileWithUnifiedLock(userId)) {
             // get credential from keystore when managed profile has unified lock
@@ -2605,9 +2619,9 @@
      * If user is a managed profile with unified challenge, currentCredential is ignored.
      */
     @Override
-    public byte[] getHashFactor(String currentCredential, int userId) throws RemoteException {
+    public byte[] getHashFactor(byte[] currentCredential, int userId) throws RemoteException {
         checkPasswordReadPermission(userId);
-        if (TextUtils.isEmpty(currentCredential)) {
+        if (currentCredential == null || currentCredential.length == 0) {
             currentCredential = null;
         }
         if (isManagedProfileWithUnifiedLock(userId)) {
@@ -2701,7 +2715,7 @@
         }
     }
 
-    private boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
+    private boolean setLockCredentialWithToken(byte[] credential, int type, long tokenHandle,
             byte[] token, int requestedQuality, int userId) throws RemoteException {
         boolean result;
         synchronized (mSpManager) {
@@ -2721,7 +2735,7 @@
         return result;
     }
 
-    private boolean setLockCredentialWithTokenInternal(String credential, int type,
+    private boolean setLockCredentialWithTokenInternal(byte[] credential, int type,
             long tokenHandle, byte[] token, int requestedQuality, int userId) throws RemoteException {
         final AuthenticationResult result;
         synchronized (mSpManager) {
@@ -2948,8 +2962,8 @@
         }
 
         @Override
-        public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
-                byte[] token, int requestedQuality, int userId) {
+        public boolean setLockCredentialWithToken(byte[] credential, int type,
+                long tokenHandle, byte[] token, int requestedQuality, int userId) {
             if (!mLockPatternUtils.hasSecureLockScreen()) {
                 throw new UnsupportedOperationException(
                         "This operation requires secure lock screen feature.");
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index 6163077..ee22264 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -190,22 +190,30 @@
     }
 
     private void runSetPattern() {
-        mLockPatternUtils.saveLockPattern(stringToPattern(mNew), mOld, mCurrentUserId);
+        byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
+        mLockPatternUtils.saveLockPattern(stringToPattern(mNew), oldBytes, mCurrentUserId);
         getOutPrintWriter().println("Pattern set to '" + mNew + "'");
     }
 
     private void runSetPassword() {
-        mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_ALPHABETIC, mCurrentUserId);
+        byte[] newBytes = mNew != null ? mNew.getBytes() : null;
+        byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
+        mLockPatternUtils.saveLockPassword(newBytes, oldBytes, PASSWORD_QUALITY_ALPHABETIC,
+                mCurrentUserId);
         getOutPrintWriter().println("Password set to '" + mNew + "'");
     }
 
     private void runSetPin() {
-        mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_NUMERIC, mCurrentUserId);
+        byte[] newBytes = mNew != null ? mNew.getBytes() : null;
+        byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
+        mLockPatternUtils.saveLockPassword(newBytes, oldBytes, PASSWORD_QUALITY_NUMERIC,
+                mCurrentUserId);
         getOutPrintWriter().println("Pin set to '" + mNew + "'");
     }
 
     private void runClear() {
-        mLockPatternUtils.clearLock(mOld, mCurrentUserId);
+        byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
+        mLockPatternUtils.clearLock(oldBytes, mCurrentUserId);
         getOutPrintWriter().println("Lock credential cleared");
     }
 
@@ -232,7 +240,8 @@
             try {
                 final boolean result;
                 if (havePassword) {
-                    result = mLockPatternUtils.checkPassword(mOld, mCurrentUserId);
+                    byte[] passwordBytes = mOld != null ? mOld.getBytes() : null;
+                    result = mLockPatternUtils.checkPassword(passwordBytes, mCurrentUserId);
                 } else {
                     result = mLockPatternUtils.checkPattern(stringToPattern(mOld), mCurrentUserId);
                 }
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 0e195bc..ea39dff 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -97,7 +97,7 @@
     private static final String WEAVER_SLOT_NAME = "weaver";
 
     public static final long DEFAULT_HANDLE = 0L;
-    private static final String DEFAULT_PASSWORD = "default-password";
+    private static final byte[] DEFAULT_PASSWORD = "default-password".getBytes();
 
     private static final byte WEAVER_VERSION = 1;
     private static final int INVALID_WEAVER_SLOT = -1;
@@ -165,7 +165,7 @@
             }
         }
 
-        public String deriveKeyStorePassword() {
+        public byte[] deriveKeyStorePassword() {
             return bytesToHex(derivePassword(PERSONALIZATION_KEY_STORE_PASSWORD));
         }
 
@@ -454,11 +454,11 @@
      *
      */
     public AuthenticationToken newSyntheticPasswordAndSid(IGateKeeperService gatekeeper,
-            byte[] hash, String credential, int userId) throws RemoteException {
+            byte[] hash, byte[] credential, int userId) throws RemoteException {
         AuthenticationToken result = AuthenticationToken.create();
         GateKeeperResponse response;
         if (hash != null) {
-            response = gatekeeper.enroll(userId, hash, credential.getBytes(),
+            response = gatekeeper.enroll(userId, hash, credential,
                     result.deriveGkPassword());
             if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
                 Log.w(TAG, "Fail to migrate SID, assuming no SID, user " + userId);
@@ -616,7 +616,7 @@
      * @see #clearSidForUser
      */
     public long createPasswordBasedSyntheticPassword(IGateKeeperService gatekeeper,
-            String credential, int credentialType, AuthenticationToken authToken,
+            byte[] credential, int credentialType, AuthenticationToken authToken,
             int requestedQuality, int userId)
                     throws RemoteException {
         if (credential == null || credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
@@ -670,7 +670,7 @@
     }
 
     public VerifyCredentialResponse verifyFrpCredential(IGateKeeperService gatekeeper,
-            String userCredential, int credentialType,
+            byte[] userCredential, int credentialType,
             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
         PersistentData persistentData = mStorage.readPersistentDataBlock();
         if (persistentData.type == PersistentData.TYPE_SP) {
@@ -839,7 +839,7 @@
      * unknown. Caller might choose to validate it by examining AuthenticationResult.credentialType
      */
     public AuthenticationResult unwrapPasswordBasedSyntheticPassword(IGateKeeperService gatekeeper,
-            long handle, String credential, int userId,
+            long handle, byte[] credential, int userId,
             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
         if (credential == null) {
             credential = DEFAULT_PASSWORD;
@@ -1152,7 +1152,7 @@
         return String.format("%s%x", LockPatternUtils.SYNTHETIC_PASSWORD_KEY_PREFIX, handle);
     }
 
-    private byte[] computePasswordToken(String password, PasswordData data) {
+    private byte[] computePasswordToken(byte[] password, PasswordData data) {
         return scrypt(password, data.salt, 1 << data.scryptN, 1 << data.scryptR, 1 << data.scryptP,
                 PASSWORD_TOKEN_LENGTH);
     }
@@ -1173,8 +1173,8 @@
         return nativeSidFromPasswordHandle(handle);
     }
 
-    protected byte[] scrypt(String password, byte[] salt, int N, int r, int p, int outLen) {
-        return new Scrypt().scrypt(password.getBytes(), salt, N, r, p, outLen);
+    protected byte[] scrypt(byte[] password, byte[] salt, int n, int r, int p, int outLen) {
+        return new Scrypt().scrypt(password, salt, n, r, p, outLen);
     }
 
     native long nativeSidFromPasswordHandle(byte[] handle);
@@ -1195,17 +1195,17 @@
         return result;
     }
 
-    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
-    public static String bytesToHex(byte[] bytes) {
+    protected static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes();
+    private static byte[] bytesToHex(byte[] bytes) {
         if (bytes == null) {
-            return "null";
+            return "null".getBytes();
         }
-        char[] hexChars = new char[bytes.length * 2];
+        byte[] hexBytes = new byte[bytes.length * 2];
         for ( int j = 0; j < bytes.length; j++ ) {
             int v = bytes[j] & 0xFF;
-            hexChars[j * 2] = hexArray[v >>> 4];
-            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+            hexBytes[j * 2] = HEX_ARRAY[v >>> 4];
+            hexBytes[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
         }
-        return new String(hexChars);
+        return hexBytes;
     }
 }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index e7a71b9..5676da2 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -38,7 +38,6 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
@@ -51,6 +50,7 @@
 import java.security.cert.CertPath;
 import java.security.cert.CertificateException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -85,7 +85,7 @@
     private final RecoverableKeyStoreDb mRecoverableKeyStoreDb;
     private final int mUserId;
     private final int mCredentialType;
-    private final String mCredential;
+    private final byte[] mCredential;
     private final boolean mCredentialUpdated;
     private final PlatformKeyManager mPlatformKeyManager;
     private final RecoverySnapshotStorage mRecoverySnapshotStorage;
@@ -100,7 +100,7 @@
             RecoverySnapshotListenersStorage recoverySnapshotListenersStorage,
             int userId,
             int credentialType,
-            String credential,
+            byte[] credential,
             boolean credentialUpdated
     ) throws NoSuchAlgorithmException, KeyStoreException, InsecureUserException {
         return new KeySyncTask(
@@ -134,7 +134,7 @@
             RecoverySnapshotListenersStorage recoverySnapshotListenersStorage,
             int userId,
             int credentialType,
-            String credential,
+            byte[] credential,
             boolean credentialUpdated,
             PlatformKeyManager platformKeyManager,
             TestOnlyInsecureCertificateHelper testOnlyInsecureCertificateHelper,
@@ -450,7 +450,7 @@
      */
     @VisibleForTesting
     @KeyChainProtectionParams.LockScreenUiFormat static int getUiFormat(
-            int credentialType, String credential) {
+            int credentialType, byte[] credential) {
         if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
             return KeyChainProtectionParams.UI_FORMAT_PATTERN;
         } else if (isPin(credential)) {
@@ -475,13 +475,13 @@
      * Returns {@code true} if {@code credential} looks like a pin.
      */
     @VisibleForTesting
-    static boolean isPin(@Nullable String credential) {
+    static boolean isPin(@Nullable byte[] credential) {
         if (credential == null) {
             return false;
         }
-        int length = credential.length();
+        int length = credential.length;
         for (int i = 0; i < length; i++) {
-            if (!Character.isDigit(credential.charAt(i))) {
+            if (!Character.isDigit((char) credential[i])) {
                 return false;
             }
         }
@@ -494,8 +494,7 @@
      * @return The SHA-256 hash.
      */
     @VisibleForTesting
-    static byte[] hashCredentialsBySaltedSha256(byte[] salt, String credentials) {
-        byte[] credentialsBytes = credentials.getBytes(StandardCharsets.UTF_8);
+    static byte[] hashCredentialsBySaltedSha256(byte[] salt, byte[] credentialsBytes) {
         ByteBuffer byteBuffer = ByteBuffer.allocate(
                 salt.length + credentialsBytes.length + LENGTH_PREFIX_BYTES * 2);
         byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
@@ -506,17 +505,19 @@
         byte[] bytes = byteBuffer.array();
 
         try {
-            return MessageDigest.getInstance(LOCK_SCREEN_HASH_ALGORITHM).digest(bytes);
+            byte[] hash = MessageDigest.getInstance(LOCK_SCREEN_HASH_ALGORITHM).digest(bytes);
+            Arrays.fill(bytes, (byte) 0);
+            return hash;
         } catch (NoSuchAlgorithmException e) {
             // Impossible, SHA-256 must be supported on Android.
             throw new RuntimeException(e);
         }
     }
 
-    private byte[] hashCredentialsByScrypt(byte[] salt, String credentials) {
+    private byte[] hashCredentialsByScrypt(byte[] salt, byte[] credentials) {
         return mScrypt.scrypt(
-                credentials.getBytes(StandardCharsets.UTF_8), salt,
-                SCRYPT_PARAM_N, SCRYPT_PARAM_R, SCRYPT_PARAM_P, SCRYPT_PARAM_OUTLEN_BYTES);
+                credentials, salt, SCRYPT_PARAM_N, SCRYPT_PARAM_R, SCRYPT_PARAM_P,
+                SCRYPT_PARAM_OUTLEN_BYTES);
     }
 
     private static SecretKey generateRecoveryKey() throws NoSuchAlgorithmException {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index ed864c0..47b9c27 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -892,13 +892,13 @@
      * This function can only be used inside LockSettingsService.
      *
      * @param storedHashType from {@code CredentialHash}
-     * @param credential - unencrypted String. Password length should be at most 16 symbols {@code
-     *     mPasswordMaxLength}
+     * @param credential - unencrypted byte array. Password length should be at most 16 symbols
+     *     {@code mPasswordMaxLength}
      * @param userId for user who just unlocked the device.
      * @hide
      */
     public void lockScreenSecretAvailable(
-            int storedHashType, @NonNull String credential, int userId) {
+            int storedHashType, @NonNull byte[] credential, int userId) {
         // So as not to block the critical path unlocking the phone, defer to another thread.
         try {
             mExecutorService.execute(KeySyncTask.newInstance(
@@ -923,13 +923,13 @@
      * This function can only be used inside LockSettingsService.
      *
      * @param storedHashType from {@code CredentialHash}
-     * @param credential - unencrypted String
+     * @param credential - unencrypted byte array
      * @param userId for the user whose lock screen credentials were changed.
      * @hide
      */
     public void lockScreenSecretChanged(
             int storedHashType,
-            @Nullable String credential,
+            @Nullable byte[] credential,
             int userId) {
         // So as not to block the critical path unlocking the phone, defer to another thread.
         try {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
index 057429c..90a36723 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
@@ -87,10 +87,30 @@
                 || isTestOnlyCertificateAlias(rootCertificateAlias);
     }
 
-    public boolean doesCredentialSupportInsecureMode(int credentialType, String credential) {
-        return (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD)
-            && (credential != null)
-            && credential.startsWith(TrustedRootCertificates.INSECURE_PASSWORD_PREFIX);
+    /**
+     * Checks whether a password is in "Insecure mode"
+     * @param credentialType the type of credential, e.g. pattern and password
+     * @param credential the pattern or password
+     * @return true, if the credential is in "Insecure mode"
+     */
+    public boolean doesCredentialSupportInsecureMode(int credentialType, byte[] credential) {
+        if (credential == null) {
+            return false;
+        }
+        if (credentialType != LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {
+            return false;
+        }
+        byte[] insecurePasswordPrefixBytes =
+                TrustedRootCertificates.INSECURE_PASSWORD_PREFIX.getBytes();
+        if (credential.length < insecurePasswordPrefixBytes.length) {
+            return false;
+        }
+        for (int i = 0; i < insecurePasswordPrefixBytes.length; i++) {
+            if (credential[i] != insecurePasswordPrefixBytes[i]) {
+                return false;
+            }
+        }
+        return true;
     }
 
     public Map<String, Pair<SecretKey, byte[]>> keepOnlyWhitelistedInsecureKeys(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 3070488..f496e81 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5046,7 +5046,8 @@
             if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
                 quality = PASSWORD_QUALITY_UNSPECIFIED;
             }
-            final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
+            // TODO(b/120484642): remove getBytes() below
+            final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password.getBytes());
             final int realQuality = metrics.quality;
             if (realQuality < quality
                     && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
@@ -5133,16 +5134,22 @@
         try {
             if (token == null) {
                 if (!TextUtils.isEmpty(password)) {
-                    mLockPatternUtils.saveLockPassword(password, null, quality, userHandle);
+                    mLockPatternUtils.saveLockPassword(password.getBytes(), null, quality,
+                            userHandle);
                 } else {
                     mLockPatternUtils.clearLock(null, userHandle);
                 }
                 result = true;
             } else {
-                result = mLockPatternUtils.setLockCredentialWithToken(password,
-                        TextUtils.isEmpty(password) ? LockPatternUtils.CREDENTIAL_TYPE_NONE
-                                : LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                        quality, tokenHandle, token, userHandle);
+                if (!TextUtils.isEmpty(password)) {
+                    result = mLockPatternUtils.setLockCredentialWithToken(password.getBytes(),
+                            LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+                            quality, tokenHandle, token, userHandle);
+                } else {
+                    result = mLockPatternUtils.setLockCredentialWithToken(null,
+                            LockPatternUtils.CREDENTIAL_TYPE_NONE,
+                            quality, tokenHandle, token, userHandle);
+                }
             }
             boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
             if (requireEntry) {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index de782a5..4293247 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4167,7 +4167,7 @@
         assertTrue(dpm.isResetPasswordTokenActive(admin1));
 
         // test reset password with token
-        when(getServices().lockPatternUtils.setLockCredentialWithToken(eq(password),
+        when(getServices().lockPatternUtils.setLockCredentialWithToken(eq(password.getBytes()),
                 eq(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD),
                 eq(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC), eq(handle), eq(token),
                 eq(UserHandle.USER_SYSTEM)))
@@ -5214,7 +5214,7 @@
                 .thenReturn(DpmMockContext.CALLER_USER_HANDLE);
         dpms.mUserPasswordMetrics.put(
                 DpmMockContext.CALLER_USER_HANDLE,
-                PasswordMetrics.computeForPassword("asdf"));
+                PasswordMetrics.computeForPassword("asdf".getBytes()));
 
         assertEquals(PASSWORD_COMPLEXITY_MEDIUM, dpm.getPasswordComplexity());
     }
@@ -5231,10 +5231,10 @@
 
         dpms.mUserPasswordMetrics.put(
                 DpmMockContext.CALLER_USER_HANDLE,
-                PasswordMetrics.computeForPassword("asdf"));
+                PasswordMetrics.computeForPassword("asdf".getBytes()));
         dpms.mUserPasswordMetrics.put(
                 parentUser.id,
-                PasswordMetrics.computeForPassword("parentUser"));
+                PasswordMetrics.computeForPassword("parentUser".getBytes()));
 
         assertEquals(PASSWORD_COMPLEXITY_HIGH, dpm.getPasswordComplexity());
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
index d2caa0a..94d21dd 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
@@ -18,24 +18,22 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
-import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.server.testutils.TestUtils.assertExpectException;
 
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.os.RemoteException;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.VerifyCredentialResponse;
-import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
-
-import java.util.ArrayList;
 
 import org.mockito.ArgumentCaptor;
 
+import java.util.ArrayList;
+
 /**
  * Run the synthetic password tests with caching enabled.
  *
@@ -56,10 +54,10 @@
     }
 
     public void testSyntheticPasswordClearCredentialUntrusted() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordClearCredential-password";
-        final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword";
+        final byte[] password = "testSyntheticPasswordClearCredential-password".getBytes();
+        final byte[] newPassword = "testSyntheticPasswordClearCredential-newpassword".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         // clear password
         mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null,
@@ -67,45 +65,46 @@
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
 
         // set a new password
-        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+        mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                    .getResponseCode());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword,
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                        .getResponseCode());
         assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
     }
 
     public void testSyntheticPasswordChangeCredentialUntrusted() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordClearCredential-password";
-        final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword";
+        final byte[] password = "testSyntheticPasswordClearCredential-password".getBytes();
+        final byte[] newPassword = "testSyntheticPasswordClearCredential-newpassword".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         // Untrusted change password
-        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+        mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
 
         // Verify the password
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                    .getResponseCode());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword,
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
     }
 
     public void testUntrustedCredentialChangeMaintainsAuthSecret() throws RemoteException {
-        final String PASSWORD = "testUntrustedCredentialChangeMaintainsAuthSecret-password";
-        final String NEWPASSWORD = "testUntrustedCredentialChangeMaintainsAuthSecret-newpassword";
+        final byte[] password =
+                "testUntrustedCredentialChangeMaintainsAuthSecret-password".getBytes();
+        final byte[] newPassword =
+                "testUntrustedCredentialChangeMaintainsAuthSecret-newpassword".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         // Untrusted change password
-        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+        mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
 
         // Verify the password
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                    .getResponseCode());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword,
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                        .getResponseCode());
 
         // Ensure the same secret was passed each time
         ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
@@ -114,27 +113,29 @@
     }
 
     public void testUntrustedCredentialChangeBlockedIfSpNotCached() throws RemoteException {
-        final String PASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-password";
-        final String NEWPASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-newpassword";
+        final byte[] password =
+                "testUntrustedCredentialChangeBlockedIfSpNotCached-password".getBytes();
+        final byte[] newPassword =
+                "testUntrustedCredentialChangeBlockedIfSpNotCached-newpassword".getBytes();
 
         // Disable caching for this test
         enableSpCaching(false);
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         // Untrusted change password
         assertExpectException(IllegalStateException.class, /* messageRegex= */ null,
-                () -> mService.setLockCredential(
-                        NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                        null, PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID));
+                () -> mService.setLockCredential(newPassword,
+                        LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+                        PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID));
         assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
 
         // Verify the new password doesn't work but the old one still does
-        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(newPassword,
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                         .getResponseCode());
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                         .getResponseCode());
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index bf71318..f4632db 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -133,12 +133,12 @@
     }
 
     @Override
-    protected void tieProfileLockToParent(int userId, String password) {
-        mStorage.writeChildProfileLock(userId, password.getBytes());
+    protected void tieProfileLockToParent(int userId, byte[] password) {
+        mStorage.writeChildProfileLock(userId, password);
     }
 
     @Override
-    protected String getDecryptedPasswordForTiedProfile(int userId) throws FileNotFoundException,
+    protected byte[] getDecryptedPasswordForTiedProfile(int userId) throws FileNotFoundException,
             KeyPermanentlyInvalidatedException {
         byte[] storedData = mStorage.readChildProfileLock(userId);
         if (storedData == null) {
@@ -151,7 +151,7 @@
         } catch (RemoteException e) {
             // shouldn't happen.
         }
-        return new String(storedData);
+        return storedData;
     }
 
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 5124803..6e0ba3c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -84,8 +84,8 @@
         initializeStorageWithCredential(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid);
 
         try {
-            mService.setLockCredential("newpwd", CREDENTIAL_TYPE_PASSWORD, "badpwd",
-                    PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+            mService.setLockCredential("newpwd".getBytes(), CREDENTIAL_TYPE_PASSWORD,
+                    "badpwd".getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
             fail("Did not fail when enrolling using incorrect credential");
         } catch (RemoteException expected) {
             assertTrue(expected.getMessage().equals(FAILED_MESSAGE));
@@ -96,7 +96,7 @@
     public void testClearPasswordPrimaryUser() throws RemoteException {
         final String PASSWORD = "password";
         initializeStorageWithCredential(PRIMARY_USER_ID, PASSWORD, CREDENTIAL_TYPE_PASSWORD, 1234);
-        mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, PASSWORD,
+        mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, PASSWORD.getBytes(),
                 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
         assertFalse(mService.havePassword(PRIMARY_USER_ID));
         assertFalse(mService.havePattern(PRIMARY_USER_ID));
@@ -106,7 +106,8 @@
     public void testManagedProfileUnifiedChallenge() throws RemoteException {
         final String firstUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-1";
         final String secondUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-2";
-        mService.setLockCredential(firstUnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+        mService.setLockCredential(firstUnifiedPassword.getBytes(),
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
                 null, PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
         final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
@@ -125,8 +126,8 @@
         mGateKeeperService.clearAuthToken(TURNED_OFF_PROFILE_USER_ID);
         // verify credential
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                firstUnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                .getResponseCode());
+                firstUnifiedPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
+                PRIMARY_USER_ID).getResponseCode());
 
         // Verify that we have a new auth token for the profile
         assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
@@ -141,15 +142,16 @@
          */
         mStorageManager.setIgnoreBadUnlock(true);
         // Change primary password and verify that profile SID remains
-        mService.setLockCredential(secondUnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                firstUnifiedPassword, PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+        mService.setLockCredential(secondUnifiedPassword.getBytes(),
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+                firstUnifiedPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         mStorageManager.setIgnoreBadUnlock(false);
         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
         assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID));
 
         // Clear unified challenge
         mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
-                secondUnifiedPassword, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+                secondUnifiedPassword.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
         assertEquals(0, mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID));
@@ -158,14 +160,16 @@
     public void testManagedProfileSeparateChallenge() throws RemoteException {
         final String primaryPassword = "testManagedProfileSeparateChallenge-primary";
         final String profilePassword = "testManagedProfileSeparateChallenge-profile";
-        mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+        mService.setLockCredential(primaryPassword.getBytes(),
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID);
         /* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new
          * credential as part of verifyCredential() before the new credential is committed in
          * StorageManager. So we relax the check in our mock StorageManager to allow that.
          */
         mStorageManager.setIgnoreBadUnlock(true);
-        mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+        mService.setLockCredential(profilePassword.getBytes(),
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_COMPLEX, MANAGED_PROFILE_USER_ID);
         mStorageManager.setIgnoreBadUnlock(false);
 
@@ -179,31 +183,32 @@
         mGateKeeperService.clearAuthToken(MANAGED_PROFILE_USER_ID);
         // verify primary credential
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                .getResponseCode());
+                primaryPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
+                PRIMARY_USER_ID).getResponseCode());
         assertNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
 
         // verify profile credential
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
+                profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
                 MANAGED_PROFILE_USER_ID).getResponseCode());
         assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
 
         // Change primary credential and make sure we don't affect profile
         mStorageManager.setIgnoreBadUnlock(true);
-        mService.setLockCredential("pwd", LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                primaryPassword, PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+        mService.setLockCredential("pwd".getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+                primaryPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         mStorageManager.setIgnoreBadUnlock(false);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
+                profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
                 MANAGED_PROFILE_USER_ID).getResponseCode());
         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
     }
 
     private void testCreateCredential(int userId, String credential, int type, int quality)
             throws RemoteException {
-        mService.setLockCredential(credential, type, null, quality, userId);
+        mService.setLockCredential(credential.getBytes(), type, null, quality,
+                userId);
         assertVerifyCredentials(userId, credential, type, -1);
     }
 
@@ -212,7 +217,8 @@
         mHasSecureLockScreen = false;
 
         try {
-            mService.setLockCredential(credential, type, null, quality, userId);
+            mService.setLockCredential(credential.getBytes(), type, null, quality,
+                    userId);
             fail("An exception should have been thrown.");
         } catch (UnsupportedOperationException e) {
             // Success - the exception was expected.
@@ -226,15 +232,16 @@
             String oldCredential, int oldType, int quality) throws RemoteException {
         final long sid = 1234;
         initializeStorageWithCredential(userId, oldCredential, oldType, sid);
-        mService.setLockCredential(newCredential, newType, oldCredential, quality, userId);
+        mService.setLockCredential(newCredential.getBytes(), newType, oldCredential.getBytes(),
+                quality, userId);
         assertVerifyCredentials(userId, newCredential, newType, sid);
     }
 
     private void assertVerifyCredentials(int userId, String credential, int type, long sid)
             throws RemoteException{
         final long challenge = 54321;
-        VerifyCredentialResponse response = mService.verifyCredential(credential, type, challenge,
-                userId);
+        VerifyCredentialResponse response = mService.verifyCredential(credential.getBytes(),
+                type, challenge, userId);
 
         assertEquals(GateKeeperResponse.RESPONSE_OK, response.getResponseCode());
         if (sid != -1) assertEquals(sid, mGateKeeperService.getSecureUserId(userId));
@@ -253,18 +260,19 @@
             incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
         }
         // check for bad type
-        assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(credential,
-                incorrectType, challenge, userId).getResponseCode());
+        assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(
+                credential.getBytes(), incorrectType, challenge, userId).getResponseCode());
         // check for bad credential
-        assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential("0" + credential,
-                type, challenge, userId).getResponseCode());
+        assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(
+                ("0" + credential).getBytes(), type, challenge, userId).getResponseCode());
     }
 
     private void initializeStorageWithCredential(int userId, String credential, int type, long sid)
             throws RemoteException {
+        byte[] credentialBytes = credential == null ? null : credential.getBytes();
         byte[] oldHash = new VerifyHandle(credential.getBytes(), sid).toBytes();
         if (mService.shouldMigrateToSyntheticPasswordLocked(userId)) {
-            mService.initializeSyntheticPasswordLocked(oldHash, credential, type,
+            mService.initializeSyntheticPasswordLocked(oldHash, credentialBytes, type,
                     type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? PASSWORD_QUALITY_ALPHABETIC
                             : PASSWORD_QUALITY_SOMETHING, userId);
         } else {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
index 929c3b5..fcfc6d2 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
@@ -85,23 +85,24 @@
     public void testWrongPassword() throws Exception {
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
-        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkPassword("1234".getBytes(), mUserId)).thenReturn(false);
         assertEquals(-1, mCommand.exec(mBinder, in, out, err,
                 new String[] { "set-pin", "--old", "1234" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils, never()).saveLockPassword(any(), any(), anyInt(), anyInt());
+        verify(mLockPatternUtils, never()).saveLockPassword(any(byte[].class), any(byte[].class),
+                anyInt(), anyInt());
     }
 
     @Test
     public void testChangePin() throws Exception {
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
-        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkPassword("1234".getBytes(), mUserId)).thenReturn(true);
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "set-pin", "--old", "1234", "4321" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils).saveLockPassword("4321", "1234", PASSWORD_QUALITY_NUMERIC,
-                mUserId);
+        verify(mLockPatternUtils).saveLockPassword("4321".getBytes(), "1234".getBytes(),
+                PASSWORD_QUALITY_NUMERIC, mUserId);
     }
 
     @Test
@@ -118,12 +119,12 @@
     public void testChangePassword() throws Exception {
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
-        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkPassword("1234".getBytes(), mUserId)).thenReturn(true);
         assertEquals(0,  mCommand.exec(new Binder(), in, out, err,
                 new String[] { "set-password", "--old", "1234", "4321" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils).saveLockPassword("4321", "1234", PASSWORD_QUALITY_ALPHABETIC,
-                mUserId);
+        verify(mLockPatternUtils).saveLockPassword("4321".getBytes(), "1234".getBytes(),
+                PASSWORD_QUALITY_ALPHABETIC, mUserId);
     }
 
     @Test
@@ -144,7 +145,8 @@
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "set-pattern", "--old", "1234", "4321" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils).saveLockPattern(stringToPattern("4321"), "1234", mUserId);
+        verify(mLockPatternUtils).saveLockPattern(stringToPattern("4321"), "1234".getBytes(),
+                mUserId);
     }
 
     @Test
@@ -165,6 +167,6 @@
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "clear", "--old", "1234" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils).clearLock("1234", mUserId);
+        verify(mLockPatternUtils).clearLock("1234".getBytes(), mUserId);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java b/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java
index 6f68179..b9cb730 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java
@@ -93,9 +93,13 @@
     }
 
     @Override
-    protected byte[] scrypt(String password, byte[] salt, int N, int r, int p, int outLen) {
+    protected byte[] scrypt(byte[] password, byte[] salt, int n, int r, int p, int outLen) {
         try {
-            PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 10, outLen * 8);
+            char[] passwordChars = new char[password.length];
+            for (int i = 0; i < password.length; i++) {
+                passwordChars[i] = (char) password[i];
+            }
+            PBEKeySpec spec = new PBEKeySpec(passwordChars, salt, 10, outLen * 8);
             SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
             return f.generateSecret(spec).getEncoded();
         } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 89e155e..e6e020d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -65,22 +65,23 @@
 
     public void testPasswordBasedSyntheticPassword() throws RemoteException {
         final int USER_ID = 10;
-        final String PASSWORD = "user-password";
-        final String BADPASSWORD = "bad-password";
+        final byte[] password = "user-password".getBytes();
+        final byte[] badPassword = "bad-password".getBytes();
         MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage,
                 mGateKeeperService, mUserManager);
         AuthenticationToken authToken = manager.newSyntheticPasswordAndSid(mGateKeeperService, null,
                 null, USER_ID);
-        long handle = manager.createPasswordBasedSyntheticPassword(mGateKeeperService, PASSWORD,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, authToken, PASSWORD_QUALITY_ALPHABETIC,
-                USER_ID);
+        long handle = manager.createPasswordBasedSyntheticPassword(mGateKeeperService,
+                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, authToken,
+                PASSWORD_QUALITY_ALPHABETIC, USER_ID);
 
         AuthenticationResult result = manager.unwrapPasswordBasedSyntheticPassword(
-                mGateKeeperService, handle, PASSWORD, USER_ID, null);
-        assertEquals(result.authToken.deriveKeyStorePassword(), authToken.deriveKeyStorePassword());
+                mGateKeeperService, handle, password, USER_ID, null);
+        assertArrayEquals(result.authToken.deriveKeyStorePassword(),
+                authToken.deriveKeyStorePassword());
 
         result = manager.unwrapPasswordBasedSyntheticPassword(mGateKeeperService, handle,
-                BADPASSWORD, USER_ID, null);
+                badPassword, USER_ID, null);
         assertNull(result.authToken);
     }
 
@@ -97,30 +98,30 @@
     }
 
     public void testPasswordMigration() throws RemoteException {
-        final String PASSWORD = "testPasswordMigration-password";
+        final byte[] password = "testPasswordMigration-password".getBytes();
 
         disableSyntheticPassword();
-        mService.setLockCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+        mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
         enableSyntheticPassword();
         // Performs migration
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                     .getResponseCode());
         assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
 
         // SP-based verification
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertArrayNotEquals(primaryStorageKey,
                 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
-    protected void initializeCredentialUnderSP(String password, int userId) throws RemoteException {
+    protected void initializeCredentialUnderSP(byte[] password, int userId) throws RemoteException {
         enableSyntheticPassword();
         int quality = password != null ? PASSWORD_QUALITY_ALPHABETIC
                 : PASSWORD_QUALITY_UNSPECIFIED;
@@ -130,62 +131,64 @@
     }
 
     public void testSyntheticPasswordChangeCredential() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordChangeCredential-password";
-        final String NEWPASSWORD = "testSyntheticPasswordChangeCredential-newpassword";
+        final byte[] password = "testSyntheticPasswordChangeCredential-password".getBytes();
+        final byte[] newPassword = "testSyntheticPasswordChangeCredential-newpassword".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
-        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, PASSWORD,
+        mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
     }
 
     public void testSyntheticPasswordVerifyCredential() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordVerifyCredential-password";
-        final String BADPASSWORD = "testSyntheticPasswordVerifyCredential-badpassword";
+        final byte[] password = "testSyntheticPasswordVerifyCredential-password".getBytes();
+        final byte[] badPassword = "testSyntheticPasswordVerifyCredential-badpassword".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                         .getResponseCode());
 
         assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
-                BADPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                    .getResponseCode());
+                badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                        .getResponseCode());
     }
 
     public void testSyntheticPasswordClearCredential() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordClearCredential-password";
-        final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword";
+        final byte[] password = "testSyntheticPasswordClearCredential-password".getBytes();
+        final byte[] badPassword = "testSyntheticPasswordClearCredential-newpassword".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         // clear password
-        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, PASSWORD,
+        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
                 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
         assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
 
         // set a new password
-        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+        mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                    .getResponseCode());
+                badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                        .getResponseCode());
         assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
     }
 
     public void testSyntheticPasswordChangeCredentialKeepsAuthSecret() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordChangeCredentialKeepsAuthSecret-password";
-        final String NEWPASSWORD = "testSyntheticPasswordChangeCredentialKeepsAuthSecret-new";
+        final byte[] password =
+                "testSyntheticPasswordChangeCredentialKeepsAuthSecret-password".getBytes();
+        final byte[] badPassword =
+                "testSyntheticPasswordChangeCredentialKeepsAuthSecret-new".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
-        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, PASSWORD,
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
+        mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                         .getResponseCode());
 
         // Check the same secret was passed each time
@@ -195,24 +198,25 @@
     }
 
     public void testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-password";
-        final String NEWPASSWORD = "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-new";
+        final byte[] password =
+                "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-password".getBytes();
+        final byte[] newPassword =
+                "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-new".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         reset(mAuthSecretService);
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
     }
 
     public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException {
-        final String PASSWORD = "testSecondaryUserDoesNotPassAuthSecret-password";
-        final String NEWPASSWORD = "testSecondaryUserDoesNotPassAuthSecret-new";
+        final byte[] password = "testSecondaryUserDoesNotPassAuthSecret-password".getBytes();
 
-        initializeCredentialUnderSP(PASSWORD, SECONDARY_USER_ID);
+        initializeCredentialUnderSP(password, SECONDARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, SECONDARY_USER_ID)
+                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, SECONDARY_USER_ID)
                         .getResponseCode());
         verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
     }
@@ -228,8 +232,8 @@
     }
 
     public void testSyntheticPasswordAndCredentialDoesNotPassAuthSecret() throws RemoteException {
-        final String PASSWORD = "passwordForASyntheticPassword";
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        final byte[] password = "passwordForASyntheticPassword".getBytes();
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
 
         reset(mAuthSecretService);
         mService.onUnlockUser(PRIMARY_USER_ID);
@@ -238,9 +242,9 @@
     }
 
     public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException {
-        final String PASSWORD = "getASyntheticPassword";
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
-        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, PASSWORD,
+        final byte[] password = "getASyntheticPassword".getBytes();
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
+        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
                 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
 
         reset(mAuthSecretService);
@@ -250,7 +254,7 @@
     }
 
     public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
-        final String UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd";
+        final byte[] UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd".getBytes();
         disableSyntheticPassword();
         mService.setLockCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
@@ -284,8 +288,10 @@
     }
 
     public void testManagedProfileSeparateChallengeMigration() throws RemoteException {
-        final String primaryPassword = "testManagedProfileSeparateChallengeMigration-primary";
-        final String profilePassword = "testManagedProfileSeparateChallengeMigration-profile";
+        final byte[] primaryPassword =
+                "testManagedProfileSeparateChallengeMigration-primary".getBytes();
+        final byte[] profilePassword =
+                "testManagedProfileSeparateChallengeMigration-profile".getBytes();
         disableSyntheticPassword();
         mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
@@ -326,92 +332,92 @@
     }
 
     public void testTokenBasedResetPassword() throws RemoteException {
-        final String PASSWORD = "password";
-        final String PATTERN = "123654";
-        final String TOKEN = "some-high-entropy-secure-token";
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        final byte[] password = "password".getBytes();
+        final byte[] pattern = "123654".getBytes();
+        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
 
-        long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
+        mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
                 PRIMARY_USER_ID).getResponseCode();
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mLocalService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
-                handle, TOKEN.getBytes(), PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
+        mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+                handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
 
         // Verify DPM gets notified about new device lock
         mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
-        PasswordMetrics metric = PasswordMetrics.computeForPassword(PATTERN);
+        PasswordMetrics metric = PasswordMetrics.computeForPassword(pattern);
         metric.quality = PASSWORD_QUALITY_SOMETHING;
         verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID);
 
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
+                pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
                     .getResponseCode());
         assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
     public void testTokenBasedClearPassword() throws RemoteException {
-        final String PASSWORD = "password";
-        final String PATTERN = "123654";
-        final String TOKEN = "some-high-entropy-secure-token";
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        final byte[] password = "password".getBytes();
+        final byte[] pattern = "123654".getBytes();
+        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
 
-        long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+        mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
                 0, PRIMARY_USER_ID).getResponseCode();
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
         mLocalService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
-                handle, TOKEN.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
-        mLocalService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
-                handle, TOKEN.getBytes(), PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
+                handle, token, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+        mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+                handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
 
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
+                pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
     public void testTokenBasedResetPasswordAfterCredentialChanges() throws RemoteException {
-        final String PASSWORD = "password";
-        final String PATTERN = "123654";
-        final String NEWPASSWORD = "password";
-        final String TOKEN = "some-high-entropy-secure-token";
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        final byte[] password = "password".getBytes();
+        final byte[] pattern = "123654".getBytes();
+        final byte[] newPassword = "password".getBytes();
+        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
 
-        long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+        mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
                 0, PRIMARY_USER_ID).getResponseCode();
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mService.setLockCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, PASSWORD,
+        mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, password,
                 PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
 
-        mLocalService.setLockCredentialWithToken(NEWPASSWORD,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, TOKEN.getBytes(),
+        mLocalService.setLockCredentialWithToken(newPassword,
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
 
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                     .getResponseCode());
         assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
     public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration()
             throws RemoteException {
-        final String TOKEN = "some-high-entropy-secure-token";
+        final String token = "some-high-entropy-secure-token";
         enableSyntheticPassword();
-        long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+        long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID);
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
@@ -419,9 +425,9 @@
 
     public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration()
             throws RemoteException {
-        final String TOKEN = "some-high-entropy-secure-token";
+        final String token = "some-high-entropy-secure-token";
         initializeCredentialUnderSP(null, PRIMARY_USER_ID);
-        long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+        long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID);
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
@@ -429,38 +435,38 @@
 
     public void testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration()
             throws RemoteException {
-        final String TOKEN = "some-high-entropy-secure-token";
-        final String PASSWORD = "password";
+        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        final byte[] password = "password".getBytes();
         // Set up pre-SP user password
         disableSyntheticPassword();
-        mService.setLockCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+        mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         enableSyntheticPassword();
 
-        long handle = mLocalService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
+        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
         // Token not activated immediately since user password exists
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
         // Activate token (password gets migrated to SP at the same time)
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                     .getResponseCode());
         // Verify token is activated
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
     }
 
     public void testSetLockCredentialWithTokenFailsWithoutLockScreen() throws Exception {
-        final String password = "password";
-        final String pattern = "123654";
-        final String token = "some-high-entropy-secure-token";
+        final byte[] password = "password".getBytes();
+        final byte[] pattern = "123654".getBytes();
+        final byte[] token = "some-high-entropy-secure-token".getBytes();
 
         mHasSecureLockScreen = false;
         enableSyntheticPassword();
-        long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID);
+        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
         try {
             mLocalService.setLockCredentialWithToken(password,
-                    LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token.getBytes(),
+                    LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token,
                     PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
             fail("An exception should have been thrown.");
         } catch (UnsupportedOperationException e) {
@@ -470,7 +476,7 @@
 
         try {
             mLocalService.setLockCredentialWithToken(pattern,
-                    LockPatternUtils.CREDENTIAL_TYPE_PATTERN, handle, token.getBytes(),
+                    LockPatternUtils.CREDENTIAL_TYPE_PATTERN, handle, token,
                     PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
             fail("An exception should have been thrown.");
         } catch (UnsupportedOperationException e) {
@@ -480,14 +486,14 @@
     }
 
     public void testgetHashFactorPrimaryUser() throws RemoteException {
-        final String password = "password";
+        final byte[] password = "password".getBytes();
         mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         final byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
         assertNotNull(hashFactor);
 
-        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
-                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
+                password, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
         final byte[] newHashFactor = mService.getHashFactor(null, PRIMARY_USER_ID);
         assertNotNull(newHashFactor);
         // Hash factor should never change after password change/removal
@@ -495,16 +501,16 @@
     }
 
     public void testgetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
-        final String pattern = "1236";
-        mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, null,
-                PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
+        final byte[] pattern = "1236".getBytes();
+        mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+                null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
         assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
     }
 
     public void testgetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
-        final String primaryPassword = "primary";
-        final String profilePassword = "profile";
+        final byte[] primaryPassword = "primary".getBytes();
+        final byte[] profilePassword = "profile".getBytes();
         mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
         mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
@@ -557,7 +563,7 @@
     public void testGsiDisablesAuthSecret() throws RemoteException {
         mGsiService.setIsGsiRunning(true);
 
-        final String password = "testGsiDisablesAuthSecret-password";
+        final byte[] password = "testGsiDisablesAuthSecret-password".getBytes();
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index c2d4846..a992dd1 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -139,7 +139,7 @@
                 mSnapshotListenersStorage,
                 TEST_USER_ID,
                 TEST_CREDENTIAL_TYPE,
-                TEST_CREDENTIAL,
+                TEST_CREDENTIAL.getBytes(),
                 /*credentialUpdated=*/ false,
                 mPlatformKeyManager,
                 mTestOnlyInsecureCertificateHelper,
@@ -163,17 +163,17 @@
 
     @Test
     public void isPin_isTrueForNumericString() {
-        assertTrue(KeySyncTask.isPin("3298432574398654376547"));
+        assertTrue(KeySyncTask.isPin("3298432574398654376547".getBytes()));
     }
 
     @Test
     public void isPin_isFalseForStringContainingLetters() {
-        assertFalse(KeySyncTask.isPin("398i54369548654"));
+        assertFalse(KeySyncTask.isPin("398i54369548654".getBytes()));
     }
 
     @Test
     public void isPin_isFalseForStringContainingSymbols() {
-        assertFalse(KeySyncTask.isPin("-3987543643"));
+        assertFalse(KeySyncTask.isPin("-3987543643".getBytes()));
     }
 
     @Test
@@ -182,8 +182,8 @@
         byte[] salt = randomBytes(16);
 
         assertArrayEquals(
-                KeySyncTask.hashCredentialsBySaltedSha256(salt, credentials),
-                KeySyncTask.hashCredentialsBySaltedSha256(salt, credentials));
+                KeySyncTask.hashCredentialsBySaltedSha256(salt, credentials.getBytes()),
+                KeySyncTask.hashCredentialsBySaltedSha256(salt, credentials.getBytes()));
     }
 
     @Test
@@ -192,8 +192,8 @@
 
         assertFalse(
                 Arrays.equals(
-                    KeySyncTask.hashCredentialsBySaltedSha256(salt, "password1234"),
-                    KeySyncTask.hashCredentialsBySaltedSha256(salt, "password12345")));
+                    KeySyncTask.hashCredentialsBySaltedSha256(salt, "password1234".getBytes()),
+                    KeySyncTask.hashCredentialsBySaltedSha256(salt, "password12345".getBytes())));
     }
 
     @Test
@@ -202,34 +202,38 @@
 
         assertFalse(
                 Arrays.equals(
-                        KeySyncTask.hashCredentialsBySaltedSha256(randomBytes(64), credentials),
-                        KeySyncTask.hashCredentialsBySaltedSha256(randomBytes(64), credentials)));
+                        KeySyncTask.hashCredentialsBySaltedSha256(randomBytes(64),
+                                credentials.getBytes()),
+                        KeySyncTask.hashCredentialsBySaltedSha256(randomBytes(64),
+                                credentials.getBytes())));
     }
 
     @Test
     public void hashCredentialsBySaltedSha256_returnsDifferentHashEvenIfConcatIsSame() {
         assertFalse(
                 Arrays.equals(
-                        KeySyncTask.hashCredentialsBySaltedSha256(utf8Bytes("123"), "4567"),
-                        KeySyncTask.hashCredentialsBySaltedSha256(utf8Bytes("1234"), "567")));
+                        KeySyncTask.hashCredentialsBySaltedSha256(utf8Bytes("123"),
+                                "4567".getBytes()),
+                        KeySyncTask.hashCredentialsBySaltedSha256(utf8Bytes("1234"),
+                                "567".getBytes())));
     }
 
     @Test
     public void getUiFormat_returnsPinIfPin() {
         assertEquals(UI_FORMAT_PIN,
-                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD, "1234"));
+                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD, "1234".getBytes()));
     }
 
     @Test
     public void getUiFormat_returnsPasswordIfPassword() {
         assertEquals(UI_FORMAT_PASSWORD,
-                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD, "1234a"));
+                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD, "1234a".getBytes()));
     }
 
     @Test
     public void getUiFormat_returnsPatternIfPattern() {
         assertEquals(UI_FORMAT_PATTERN,
-                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PATTERN, "1234"));
+                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PATTERN, "1234".getBytes()));
 
     }
 
@@ -291,7 +295,7 @@
                 mSnapshotListenersStorage,
                 TEST_USER_ID,
                 CREDENTIAL_TYPE_PASSWORD,
-                /*credential=*/ password,
+                /*credential=*/ password.getBytes(),
                 /*credentialUpdated=*/ false,
                 mPlatformKeyManager,
                 mTestOnlyInsecureCertificateHelper,
@@ -332,7 +336,7 @@
                 mSnapshotListenersStorage,
                 TEST_USER_ID,
                 CREDENTIAL_TYPE_PATTERN,
-                /*credential=*/ pattern,
+                /*credential=*/ pattern.getBytes(),
                 /*credentialUpdated=*/ false,
                 mPlatformKeyManager,
                 mTestOnlyInsecureCertificateHelper,
@@ -366,7 +370,7 @@
                 mSnapshotListenersStorage,
                 TEST_USER_ID,
                 CREDENTIAL_TYPE_PASSWORD,
-                /*credential=*/ shortPassword,
+                /*credential=*/ shortPassword.getBytes(),
                 /*credentialUpdated=*/ false,
                 mPlatformKeyManager,
                 mTestOnlyInsecureCertificateHelper,
@@ -526,7 +530,7 @@
         verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
         byte[] lockScreenHash = KeySyncTask.hashCredentialsBySaltedSha256(
                 keyDerivationParams.getSalt(),
-                TEST_CREDENTIAL);
+                TEST_CREDENTIAL.getBytes());
         Long counterId = mRecoverableKeyStoreDb.getCounterId(TEST_USER_ID, TEST_RECOVERY_AGENT_UID);
         assertThat(counterId).isNotNull();
         byte[] recoveryKey = decryptThmEncryptedKey(
@@ -649,7 +653,7 @@
                 mSnapshotListenersStorage,
                 TEST_USER_ID,
                 CREDENTIAL_TYPE_PASSWORD,
-                password,
+                password.getBytes(),
                 /*credentialUpdated=*/ false,
                 mPlatformKeyManager,
                 mTestOnlyInsecureCertificateHelper,
@@ -680,7 +684,7 @@
                 mSnapshotListenersStorage,
                 TEST_USER_ID,
                 CREDENTIAL_TYPE_PASSWORD,
-                /*credential=*/ pin,
+                /*credential=*/ pin.getBytes(),
                 /*credentialUpdated=*/ false,
                 mPlatformKeyManager,
                 mTestOnlyInsecureCertificateHelper,
@@ -712,7 +716,7 @@
                 mSnapshotListenersStorage,
                 TEST_USER_ID,
                 CREDENTIAL_TYPE_PATTERN,
-                "12345",
+                "12345".getBytes(),
                 /*credentialUpdated=*/ false,
                 mPlatformKeyManager,
                 mTestOnlyInsecureCertificateHelper,
@@ -796,7 +800,7 @@
           mSnapshotListenersStorage,
           TEST_USER_ID,
           /*credentialType=*/ 3,
-          "12345",
+          "12345".getBytes(),
           /*credentialUpdated=*/ false,
           mPlatformKeyManager,
           mTestOnlyInsecureCertificateHelper,
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java
index 9b4c3be..6921bb2 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java
@@ -27,30 +27,30 @@
     @Test
     public void testDoesCredentailSupportInsecureMode_forNonWhitelistedPassword() throws Exception {
         assertThat(mHelper.doesCredentialSupportInsecureMode(
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, "secret12345")).isFalse();
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, "secret12345".getBytes())).isFalse();
         assertThat(mHelper.doesCredentialSupportInsecureMode(
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, "1234")).isFalse();
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, "1234".getBytes())).isFalse();
     }
 
     @Test
     public void testDoesCredentailSupportInsecureMode_forWhitelistedPassword() throws Exception {
         assertThat(mHelper.doesCredentialSupportInsecureMode(
                 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                TrustedRootCertificates.INSECURE_PASSWORD_PREFIX)).isTrue();
+                TrustedRootCertificates.INSECURE_PASSWORD_PREFIX.getBytes())).isTrue();
 
         assertThat(mHelper.doesCredentialSupportInsecureMode(
                 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + "12")).isTrue();
+                (TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + "12").getBytes())).isTrue();
     }
 
     @Test
     public void testDoesCredentailSupportInsecureMode_Pattern() throws Exception {
         assertThat(mHelper.doesCredentialSupportInsecureMode(
                 LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
-                TrustedRootCertificates.INSECURE_PASSWORD_PREFIX)).isFalse();
+                TrustedRootCertificates.INSECURE_PASSWORD_PREFIX.getBytes())).isFalse();
         assertThat(mHelper.doesCredentialSupportInsecureMode(
                 LockPatternUtils.CREDENTIAL_TYPE_NONE,
-                TrustedRootCertificates.INSECURE_PASSWORD_PREFIX)).isFalse();
+                TrustedRootCertificates.INSECURE_PASSWORD_PREFIX.getBytes())).isFalse();
     }
 
     @Test