Merge "AudioSystem: disable verbose volume logging"
diff --git a/api/current.txt b/api/current.txt
index 8ec2f5a..32747e7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26035,6 +26035,7 @@
   public static final class MediaSession2.Builder {
     ctor public MediaSession2.Builder(@NonNull android.content.Context);
     method @NonNull public android.media.MediaSession2 build();
+    method @NonNull public android.media.MediaSession2.Builder setExtras(@Nullable android.os.Bundle);
     method @NonNull public android.media.MediaSession2.Builder setId(@NonNull String);
     method @NonNull public android.media.MediaSession2.Builder setSessionActivity(@Nullable android.app.PendingIntent);
     method @NonNull public android.media.MediaSession2.Builder setSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaSession2.SessionCallback);
@@ -26397,6 +26398,7 @@
   public final class Session2Token implements android.os.Parcelable {
     ctor public Session2Token(@NonNull android.content.Context, @NonNull android.content.ComponentName);
     method public int describeContents();
+    method @Nullable public android.os.Bundle getExtras();
     method @NonNull public String getPackageName();
     method @Nullable public String getServiceName();
     method public int getType();
@@ -29356,7 +29358,7 @@
     method public android.os.ParcelFileDescriptor establish();
     method public android.net.VpnService.Builder setBlocking(boolean);
     method public android.net.VpnService.Builder setConfigureIntent(android.app.PendingIntent);
-    method public android.net.VpnService.Builder setHttpProxy(android.net.ProxyInfo);
+    method public android.net.VpnService.Builder setHttpProxy(@NonNull android.net.ProxyInfo);
     method public android.net.VpnService.Builder setMetered(boolean);
     method public android.net.VpnService.Builder setMtu(int);
     method public android.net.VpnService.Builder setSession(String);
@@ -51205,8 +51207,8 @@
     method public int getScaledHoverSlop();
     method public int getScaledMaximumDrawingCacheSize();
     method public int getScaledMaximumFlingVelocity();
-    method public int getScaledMinScalingSpan();
     method public int getScaledMinimumFlingVelocity();
+    method public int getScaledMinimumScalingSpan();
     method public int getScaledOverflingDistance();
     method public int getScaledOverscrollDistance();
     method public int getScaledPagingTouchSlop();
@@ -51980,16 +51982,16 @@
     method public boolean hasInsets();
     method public boolean hasStableInsets();
     method public boolean hasSystemWindowInsets();
-    method @NonNull public android.view.WindowInsets inset(int, int, int, int);
+    method @NonNull public android.view.WindowInsets inset(@IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
     method public boolean isConsumed();
     method public boolean isRound();
     method @Deprecated @NonNull public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
     method @Deprecated @NonNull public android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect);
   }
 
-  public static class WindowInsets.Builder {
+  public static final class WindowInsets.Builder {
     ctor public WindowInsets.Builder();
-    ctor public WindowInsets.Builder(android.view.WindowInsets);
+    ctor public WindowInsets.Builder(@NonNull android.view.WindowInsets);
     method @NonNull public android.view.WindowInsets build();
     method @NonNull public android.view.WindowInsets.Builder setDisplayCutout(@Nullable android.view.DisplayCutout);
     method @NonNull public android.view.WindowInsets.Builder setStableInsets(@NonNull android.graphics.Insets);
diff --git a/api/system-current.txt b/api/system-current.txt
index 17ea2e1..b5d9f3c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3455,6 +3455,7 @@
     method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
     method public void clearAudioServerStateCallback();
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioProductStrategies getAudioProductStrategies();
     method public boolean isAudioServerRunning();
     method public boolean isHdmiSystemAudioSupported();
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
@@ -3647,6 +3648,7 @@
     method @NonNull public android.media.AudioAttributes getAudioAttributesForProductStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
     method @Nullable public android.media.audiopolicy.AudioProductStrategy getById(int);
     method public int getLegacyStreamTypeForAudioAttributes(@NonNull android.media.AudioAttributes);
+    method @Nullable public android.media.audiopolicy.AudioProductStrategy getProductStrategyForAudioAttributes(@NonNull android.media.AudioAttributes);
     method public java.util.Iterator<android.media.audiopolicy.AudioProductStrategy> iterator();
     method public int size();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -4849,7 +4851,8 @@
     ctor public WifiScanner.ScanSettings();
     field public int band;
     field public android.net.wifi.WifiScanner.ChannelSpec[] channels;
-    field @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean ignoreLocationSettings;
+    field public boolean hideFromAppOps;
+    field public boolean ignoreLocationSettings;
     field public int maxPeriodInMs;
     field public int maxScansToCache;
     field public int numBssidsPerScan;
@@ -9239,7 +9242,7 @@
 
 package android.telephony.mbms.vendor {
 
-  public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface {
+  public class MbmsDownloadServiceBase extends android.os.Binder {
     ctor public MbmsDownloadServiceBase();
     method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
     method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
@@ -9272,7 +9275,7 @@
     method public void updateGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>);
   }
 
-  public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface {
+  public class MbmsStreamingServiceBase extends android.os.Binder {
     ctor public MbmsStreamingServiceBase();
     method public android.os.IBinder asBinder();
     method public void dispose(int) throws android.os.RemoteException;
diff --git a/api/test-current.txt b/api/test-current.txt
index f76cc71..1089761 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -684,7 +684,6 @@
     method public static int getWALAutoCheckpoint();
     method public static int getWALConnectionPoolSize();
     method public static String getWALSyncMode();
-    method public static boolean isCompatibilityWalSupported();
     method public static int releaseMemory();
   }
 
@@ -741,6 +740,13 @@
     field public static final android.os.Parcelable.Creator<android.hardware.display.AmbientBrightnessDayStats> CREATOR;
   }
 
+  public class AmbientDisplayConfiguration {
+    ctor public AmbientDisplayConfiguration(android.content.Context);
+    method public boolean alwaysOnAvailable();
+    method public boolean alwaysOnAvailableForUser(int);
+    method public boolean alwaysOnEnabled(int);
+  }
+
   public final class BrightnessChangeEvent implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -1991,6 +1997,7 @@
     field public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
     field public static final String CONTENT_CAPTURE_ENABLED = "content_capture_enabled";
     field public static final String DISABLED_PRINT_SERVICES = "disabled_print_services";
+    field public static final String DOZE_ALWAYS_ON = "doze_always_on";
     field @Deprecated public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
     field public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
     field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
@@ -2381,7 +2388,7 @@
 
 package android.telephony.mbms.vendor {
 
-  public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface {
+  public class MbmsDownloadServiceBase extends android.os.Binder {
     ctor public MbmsDownloadServiceBase();
     method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
     method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
@@ -2414,7 +2421,7 @@
     method public void updateGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>);
   }
 
-  public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface {
+  public class MbmsStreamingServiceBase extends android.os.Binder {
     ctor public MbmsStreamingServiceBase();
     method public android.os.IBinder asBinder();
     method public void dispose(int) throws android.os.RemoteException;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index de42398..1dd68df 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -285,7 +285,7 @@
         CategorySize category_size = 10028;
         ProcStats proc_stats = 10029;
         BatteryVoltage battery_voltage = 10030;
-        NumBiometricsEnrolled num_fingerprints_enrolled = 10031;
+        NumFingerprintsEnrolled num_fingerprints_enrolled = 10031;
         DiskIo disk_io = 10032;
         PowerProfile power_profile = 10033;
         ProcStatsPkgProc proc_stats_pkg_proc = 10034;
@@ -302,7 +302,7 @@
         BatteryCycleCount battery_cycle_count = 10045;
         DebugElapsedClock debug_elapsed_clock = 10046;
         DebugFailingElapsedClock debug_failing_elapsed_clock = 10047;
-        NumBiometricsEnrolled num_faces_enrolled = 10048;
+        NumFacesEnrolled num_faces_enrolled = 10048;
         RoleHolder role_holder = 10049;
         DangerousPermissionState dangerous_permission_state = 10050;
         TrainInfo train_info = 10051;
@@ -4127,15 +4127,27 @@
  *
  * Pulled from StatsCompanionService, which queries <Biometric>Manager.
  */
-message NumBiometricsEnrolled {
+message NumFingerprintsEnrolled {
     // The associated user. Eg: 0 for owners, 10+ for others.
     // Defined in android/os/UserHandle.java
     optional int32 user = 1;
     // Number of fingerprints registered to that user.
-    optional int32 num_enrolled = 2;
+    optional int32 num_fingerprints_enrolled = 2;
 }
 
 /**
+ * Pulls the number of faces for each user.
+ *
+ * Pulled from StatsCompanionService, which queries <Biometric>Manager.
+ */
+message NumFacesEnrolled {
+    // The associated user. Eg: 0 for owners, 10+ for others.
+    // Defined in android/os/UserHandle.java
+    optional int32 user = 1;
+    // Number of faces registered to that user.
+    optional int32 num_faces_enrolled = 2;
+}
+/**
  * A mapping of role holder -> role
  */
 message RoleHolder {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index dc8863a..de0f2bc 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2391,7 +2391,6 @@
                         mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
             }
         }
-        notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_STOP);
         mEnterAnimationComplete = false;
     }
 
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/android/database/sqlite/SQLiteCompatibilityWalFlags.java b/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
index 8ea1db2..a269072 100644
--- a/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
+++ b/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
@@ -40,8 +40,7 @@
     private static final String TAG = "SQLiteCompatibilityWalFlags";
 
     private static volatile boolean sInitialized;
-    private static volatile boolean sFlagsSet;
-    private static volatile boolean sCompatibilityWalSupported;
+    private static volatile boolean sLegacyCompatibilityWalEnabled;
     private static volatile String sWALSyncMode;
     private static volatile long sTruncateSize = -1;
     // This flag is used to avoid recursive initialization due to circular dependency on Settings
@@ -54,18 +53,9 @@
      * @hide
      */
     @VisibleForTesting
-    public static boolean areFlagsSet() {
+    public static boolean isLegacyCompatibilityWalEnabled() {
         initIfNeeded();
-        return sFlagsSet;
-    }
-
-    /**
-     * @hide
-     */
-    @VisibleForTesting
-    public static boolean isCompatibilityWalSupported() {
-        initIfNeeded();
-        return sCompatibilityWalSupported;
+        return sLegacyCompatibilityWalEnabled;
     }
 
     /**
@@ -74,6 +64,14 @@
     @VisibleForTesting
     public static String getWALSyncMode() {
         initIfNeeded();
+        // The configurable WAL sync mode should only ever be used if the legacy compatibility
+        // WAL is enabled. It should *not* have any effect if app developers explicitly turn on
+        // WAL for their database using setWriteAheadLoggingEnabled. Throwing an exception here
+        // adds an extra layer of checking that we never use it in the wrong place.
+        if (!sLegacyCompatibilityWalEnabled) {
+            throw new IllegalStateException("isLegacyCompatibilityWalEnabled() == false");
+        }
+
         return sWALSyncMode;
     }
 
@@ -131,13 +129,12 @@
             sInitialized = true;
             return;
         }
-        sCompatibilityWalSupported = parser.getBoolean("compatibility_wal_supported",
-                SQLiteGlobal.isCompatibilityWalSupported());
+        sLegacyCompatibilityWalEnabled = parser.getBoolean(
+                "legacy_compatibility_wal_enabled", false);
         sWALSyncMode = parser.getString("wal_syncmode", SQLiteGlobal.getWALSyncMode());
         sTruncateSize = parser.getInt("truncate_size", -1);
-        Log.i(TAG, "Read compatibility WAL flags: compatibility_wal_supported="
-                + sCompatibilityWalSupported + ", wal_syncmode=" + sWALSyncMode);
-        sFlagsSet = true;
+        Log.i(TAG, "Read compatibility WAL flags: legacy_compatibility_wal_enabled="
+                + sLegacyCompatibilityWalEnabled + ", wal_syncmode=" + sWALSyncMode);
         sInitialized = true;
     }
 
@@ -148,8 +145,7 @@
     @TestApi
     public static void reset() {
         sInitialized = false;
-        sFlagsSet = false;
-        sCompatibilityWalSupported = false;
+        sLegacyCompatibilityWalEnabled = false;
         sWALSyncMode = null;
     }
 }
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 3c8e236..3844794 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -300,12 +300,13 @@
                     (mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
             // Use compatibility WAL unless an app explicitly set journal/synchronous mode
             // or DISABLE_COMPATIBILITY_WAL flag is set
-            final boolean useCompatibilityWal = mConfiguration.useCompatibilityWal();
-            if (walEnabled || useCompatibilityWal) {
+            final boolean isCompatibilityWalEnabled =
+                    mConfiguration.isLegacyCompatibilityWalEnabled();
+            if (walEnabled || isCompatibilityWalEnabled) {
                 setJournalMode("WAL");
                 if (mConfiguration.syncMode != null) {
                     setSyncMode(mConfiguration.syncMode);
-                } else if (useCompatibilityWal && SQLiteCompatibilityWalFlags.areFlagsSet()) {
+                } else if (isCompatibilityWalEnabled) {
                     setSyncMode(SQLiteCompatibilityWalFlags.getWALSyncMode());
                 } else {
                     setSyncMode(SQLiteGlobal.getWALSyncMode());
@@ -504,7 +505,7 @@
                 != mConfiguration.foreignKeyConstraintsEnabled;
         boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
                 & (SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING
-                | SQLiteDatabase.DISABLE_COMPATIBILITY_WAL)) != 0;
+                | SQLiteDatabase.ENABLE_LEGACY_COMPATIBILITY_WAL)) != 0;
         boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
 
         // Update configuration parameters.
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index dbc1766..852f8f2 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -321,7 +321,7 @@
             // We should do in-place switching when transitioning from compatibility WAL
             // to rollback journal. Otherwise transient connection state will be lost
             boolean onlyCompatWalChanged = (mConfiguration.openFlags ^ configuration.openFlags)
-                    == SQLiteDatabase.DISABLE_COMPATIBILITY_WAL;
+                    == SQLiteDatabase.ENABLE_LEGACY_COMPATIBILITY_WAL;
 
             if (!onlyCompatWalChanged && mConfiguration.openFlags != configuration.openFlags) {
                 // If we are changing open flags and WAL mode at the same time, then
@@ -1113,19 +1113,18 @@
             if (directories != null) {
                 directories.add(new File(mConfiguration.path).getParent());
             }
+            boolean isCompatibilityWalEnabled = mConfiguration.isLegacyCompatibilityWalEnabled();
             printer.println("Connection pool for " + mConfiguration.path + ":");
             printer.println("  Open: " + mIsOpen);
             printer.println("  Max connections: " + mMaxConnectionPoolSize);
             printer.println("  Total execution time: " + mTotalExecutionTimeCounter);
             printer.println("  Configuration: openFlags=" + mConfiguration.openFlags
-                    + ", useCompatibilityWal=" + mConfiguration.useCompatibilityWal()
+                    + ", isLegacyCompatibilityWalEnabled=" + isCompatibilityWalEnabled
                     + ", journalMode=" + TextUtils.emptyIfNull(mConfiguration.journalMode)
                     + ", syncMode=" + TextUtils.emptyIfNull(mConfiguration.syncMode));
 
-            if (SQLiteCompatibilityWalFlags.areFlagsSet()) {
-                printer.println("  Compatibility WAL settings: compatibility_wal_supported="
-                        + SQLiteCompatibilityWalFlags
-                        .isCompatibilityWalSupported() + ", wal_syncmode="
+            if (isCompatibilityWalEnabled) {
+                printer.println("  Compatibility WAL enabled: wal_syncmode="
                         + SQLiteCompatibilityWalFlags.getWALSyncMode());
             }
             if (mConfiguration.isLookasideConfigSet()) {
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index ae456af..dffbd89 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -266,12 +266,17 @@
      */
     public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
 
+
+    // Note: The below value was only used on Android Pie.
+    // public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
+
     /**
-     * Open flag: Flag for {@link #openDatabase} to disable Compatibility WAL when opening database.
+     * Open flag: Flag for {@link #openDatabase} to enable the legacy Compatibility WAL when opening
+     * database.
      *
      * @hide
      */
-    public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
+    public static final int ENABLE_LEGACY_COMPATIBILITY_WAL = 0x80000000;
 
     /**
      * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
@@ -309,10 +314,8 @@
         mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
         mConfigurationLocked.journalMode = journalMode;
         mConfigurationLocked.syncMode = syncMode;
-        if (!SQLiteGlobal.isCompatibilityWalSupported() || (
-                SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
-                        .isCompatibilityWalSupported())) {
-            mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
+        if (SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled()) {
+            mConfigurationLocked.openFlags |= ENABLE_LEGACY_COMPATIBILITY_WAL;
         }
     }
 
@@ -2123,15 +2126,18 @@
             throwIfNotOpenLocked();
 
             final int oldFlags = mConfigurationLocked.openFlags;
-            final boolean walDisabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0;
-            final boolean compatibilityWalDisabled = (oldFlags & DISABLE_COMPATIBILITY_WAL) != 0;
-            if (walDisabled && compatibilityWalDisabled) {
+            final boolean walEnabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
+            final boolean compatibilityWalEnabled =
+                    (oldFlags & ENABLE_LEGACY_COMPATIBILITY_WAL) != 0;
+            // WAL was never enabled for this database, so there's nothing left to do.
+            if (!walEnabled && !compatibilityWalEnabled) {
                 return;
             }
 
+            // If an app explicitly disables WAL, it takes priority over any directive
+            // to use the legacy "compatibility WAL" mode.
             mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
-            // If an app explicitly disables WAL, compatibility mode should be disabled too
-            mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
+            mConfigurationLocked.openFlags &= ~ENABLE_LEGACY_COMPATIBILITY_WAL;
 
             try {
                 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index 48f1021..fcdaf0a 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -17,6 +17,7 @@
 package android.database.sqlite;
 
 import android.annotation.UnsupportedAppUsage;
+
 import java.util.ArrayList;
 import java.util.Locale;
 import java.util.regex.Pattern;
@@ -197,9 +198,9 @@
         return path.equalsIgnoreCase(MEMORY_DB_PATH);
     }
 
-    boolean useCompatibilityWal() {
+    boolean isLegacyCompatibilityWalEnabled() {
         return journalMode == null && syncMode == null
-                && (openFlags & SQLiteDatabase.DISABLE_COMPATIBILITY_WAL) == 0;
+                && (openFlags & SQLiteDatabase.ENABLE_LEGACY_COMPATIBILITY_WAL) != 0;
     }
 
     private static String stripPathForLogs(String path) {
diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java
index ff286fd..d796003 100644
--- a/core/java/android/database/sqlite/SQLiteGlobal.java
+++ b/core/java/android/database/sqlite/SQLiteGlobal.java
@@ -91,16 +91,6 @@
     }
 
     /**
-     * Returns true if compatibility WAL mode is supported. In this mode, only
-     * database journal mode is changed. Connection pool will use at most one connection.
-     */
-    public static boolean isCompatibilityWalSupported() {
-        return SystemProperties.getBoolean("debug.sqlite.compatibility_wal_supported",
-                Resources.getSystem().getBoolean(
-                        com.android.internal.R.bool.db_compatibility_wal_supported));
-    }
-
-    /**
      * Gets the journal size limit in bytes.
      */
     public static int getJournalSizeLimit() {
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 0e869c8..8163c4d 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -202,8 +202,9 @@
                 }
                 mOpenParamsBuilder.setWriteAheadLoggingEnabled(enabled);
             }
+
             // Compatibility WAL is disabled if an app disables or enables WAL
-            mOpenParamsBuilder.addOpenFlags(SQLiteDatabase.DISABLE_COMPATIBILITY_WAL);
+            mOpenParamsBuilder.removeOpenFlags(SQLiteDatabase.ENABLE_LEGACY_COMPATIBILITY_WAL);
         }
     }
 
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
similarity index 82%
rename from core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
rename to core/java/android/hardware/display/AmbientDisplayConfiguration.java
index 87e048c..b122f19 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -11,11 +11,12 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
-package com.android.internal.hardware;
+package android.hardware.display;
 
+import android.annotation.TestApi;
 import android.content.Context;
 import android.os.Build;
 import android.os.SystemProperties;
@@ -24,16 +25,25 @@
 
 import com.android.internal.R;
 
+/**
+ * AmbientDisplayConfiguration encapsulates reading access to the configuration of ambient display.
+ *
+ * {@hide}
+ */
+@TestApi
 public class AmbientDisplayConfiguration {
 
     private final Context mContext;
     private final boolean mAlwaysOnByDefault;
 
+    /** {@hide} */
+    @TestApi
     public AmbientDisplayConfiguration(Context context) {
         mContext = context;
         mAlwaysOnByDefault = mContext.getResources().getBoolean(R.bool.config_dozeAlwaysOnEnabled);
     }
 
+    /** {@hide} */
     public boolean enabled(int user) {
         return pulseOnNotificationEnabled(user)
                 || pulseOnLongPressEnabled(user)
@@ -41,67 +51,83 @@
                 || wakeScreenGestureEnabled(user);
     }
 
+    /** {@hide} */
     public boolean pulseOnNotificationEnabled(int user) {
-        return boolSettingDefaultOn(Settings.Secure.DOZE_ENABLED, user) && pulseOnNotificationAvailable();
+        return boolSettingDefaultOn(Settings.Secure.DOZE_ENABLED, user)
+                && pulseOnNotificationAvailable();
     }
 
+    /** {@hide} */
     public boolean pulseOnNotificationAvailable() {
         return ambientDisplayAvailable();
     }
 
+    /** {@hide} */
     public boolean pickupGestureEnabled(int user) {
         return boolSettingDefaultOn(Settings.Secure.DOZE_PICK_UP_GESTURE, user)
                 && dozePickupSensorAvailable();
     }
 
+    /** {@hide} */
     public boolean dozePickupSensorAvailable() {
         return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup);
     }
 
+    /** {@hide} */
     public boolean tapGestureEnabled(int user) {
         return boolSettingDefaultOn(Settings.Secure.DOZE_TAP_SCREEN_GESTURE, user)
                 && tapSensorAvailable();
     }
 
+    /** {@hide} */
     public boolean tapSensorAvailable() {
         return !TextUtils.isEmpty(tapSensorType());
     }
 
+    /** {@hide} */
     public boolean doubleTapGestureEnabled(int user) {
         return boolSettingDefaultOn(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, user)
                 && doubleTapSensorAvailable();
     }
 
+    /** {@hide} */
     public boolean doubleTapSensorAvailable() {
         return !TextUtils.isEmpty(doubleTapSensorType());
     }
 
+    /** {@hide} */
     public boolean wakeScreenGestureAvailable() {
         return mContext.getResources()
                 .getBoolean(R.bool.config_dozeWakeLockScreenSensorAvailable);
     }
 
+    /** {@hide} */
     public boolean wakeScreenGestureEnabled(int user) {
         return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, user)
                 && wakeScreenGestureAvailable();
     }
 
+    /** {@hide} */
     public long getWakeLockScreenDebounce() {
         return mContext.getResources().getInteger(R.integer.config_dozeWakeLockScreenDebounce);
     }
 
+    /** {@hide} */
     public String doubleTapSensorType() {
         return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
     }
 
+    /** {@hide} */
     public String tapSensorType() {
         return mContext.getResources().getString(R.string.config_dozeTapSensorType);
     }
 
+    /** {@hide} */
     public String longPressSensorType() {
         return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
     }
 
+    /** {@hide} */
     public boolean pulseOnLongPressEnabled(int user) {
         return pulseOnLongPressAvailable() && boolSettingDefaultOff(
                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, user);
@@ -111,28 +137,49 @@
         return !TextUtils.isEmpty(longPressSensorType());
     }
 
+    /**
+     * Returns if Always-on-Display functionality is enabled on the display for a specified user.
+     *
+     * {@hide}
+     */
+    @TestApi
     public boolean alwaysOnEnabled(int user) {
         return boolSetting(Settings.Secure.DOZE_ALWAYS_ON, user, mAlwaysOnByDefault ? 1 : 0)
                 && alwaysOnAvailable() && !accessibilityInversionEnabled(user);
     }
 
+    /**
+     * Returns if Always-on-Display functionality is available on the display.
+     *
+     * {@hide}
+     */
+    @TestApi
     public boolean alwaysOnAvailable() {
         return (alwaysOnDisplayDebuggingEnabled() || alwaysOnDisplayAvailable())
                 && ambientDisplayAvailable();
     }
 
+    /**
+     * Returns if Always-on-Display functionality is available on the display for a specified user.
+     *
+     *  {@hide}
+     */
+    @TestApi
     public boolean alwaysOnAvailableForUser(int user) {
         return alwaysOnAvailable() && !accessibilityInversionEnabled(user);
     }
 
+    /** {@hide} */
     public String ambientDisplayComponent() {
         return mContext.getResources().getString(R.string.config_dozeComponent);
     }
 
+    /** {@hide} */
     public boolean accessibilityInversionEnabled(int user) {
         return boolSettingDefaultOff(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, user);
     }
 
+    /** {@hide} */
     public boolean ambientDisplayAvailable() {
         return !TextUtils.isEmpty(ambientDisplayComponent());
     }
@@ -145,7 +192,6 @@
         return SystemProperties.getBoolean("debug.doze.aod", false) && Build.IS_DEBUGGABLE;
     }
 
-
     private boolean boolSettingDefaultOn(String name, int user) {
         return boolSetting(name, user, 1);
     }
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 90dccb5..45860b3 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -23,8 +23,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.RoSystemProperties;
-import com.android.org.conscrypt.Conscrypt;
-import com.android.org.conscrypt.OpenSSLContextImpl;
+import com.android.org.conscrypt.ClientSessionContext;
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 import com.android.org.conscrypt.SSLClientSessionCache;
 
@@ -33,6 +32,8 @@
 import java.net.Socket;
 import java.net.SocketException;
 import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
 
@@ -40,6 +41,7 @@
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.net.ssl.SSLSession;
@@ -251,11 +253,12 @@
     private SSLSocketFactory makeSocketFactory(
             KeyManager[] keyManagers, TrustManager[] trustManagers) {
         try {
-            OpenSSLContextImpl sslContext =  (OpenSSLContextImpl) Conscrypt.newPreferredSSLContextSpi();
-            sslContext.engineInit(keyManagers, trustManagers, null);
-            sslContext.engineGetClientSessionContext().setPersistentCache(mSessionCache);
-            return sslContext.engineGetSocketFactory();
-        } catch (KeyManagementException e) {
+            SSLContext sslContext = SSLContext.getInstance("TLS", "AndroidOpenSSL");
+            sslContext.init(keyManagers, trustManagers, null);
+            ((ClientSessionContext) sslContext.getClientSessionContext())
+                .setPersistentCache(mSessionCache);
+            return sslContext.getSocketFactory();
+        } catch (KeyManagementException | NoSuchAlgorithmException | NoSuchProviderException e) {
             Log.wtf(TAG, e);
             return (SSLSocketFactory) SSLSocketFactory.getDefault();  // Fallback
         }
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 784f233..ebb1ae4 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -19,6 +19,7 @@
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
 
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
@@ -512,7 +513,7 @@
          * Sets an HTTP proxy for the VPN network. This proxy is only a recommendation
          * and it is possible that some apps will ignore it.
          */
-        public Builder setHttpProxy(ProxyInfo proxyInfo) {
+        public Builder setHttpProxy(@NonNull ProxyInfo proxyInfo) {
             mConfig.proxyInfo = proxyInfo;
             return this;
         }
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index da03895..330bde5 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -16,11 +16,14 @@
 
 package android.os;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.Log;
 
 import java.io.File;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -45,6 +48,24 @@
  * keep a reference to the FileObserver instance from some other live object.</p>
  */
 public abstract class FileObserver {
+    /** @hide */
+    @IntDef(flag = true, value = {
+            ACCESS,
+            MODIFY,
+            ATTRIB,
+            CLOSE_WRITE,
+            CLOSE_NOWRITE,
+            OPEN,
+            MOVED_FROM,
+            MOVED_TO,
+            CREATE,
+            DELETE,
+            DELETE_SELF,
+            MOVE_SELF
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface NotifyEventType {}
+
     /** Event type: Data was read from a file */
     public static final int ACCESS = 0x00000001;
     /** Event type: Data was written to a file */
@@ -71,6 +92,7 @@
     public static final int MOVE_SELF = 0x00000800;
 
     /** Event mask: All valid event types, combined */
+    @NotifyEventType
     public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE
             | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
             | DELETE_SELF | MOVE_SELF;
@@ -90,7 +112,8 @@
             observe(m_fd);
         }
 
-        public int[] startWatching(List<File> files, int mask, FileObserver observer) {
+        public int[] startWatching(List<File> files,
+                @NotifyEventType int mask, FileObserver observer) {
             final int count = files.size();
             final String[] paths = new String[count];
             for (int i = 0; i < count; ++i) {
@@ -118,7 +141,7 @@
             stopWatching(m_fd, descriptors);
         }
 
-        public void onEvent(int wfd, int mask, String path) {
+        public void onEvent(int wfd, @NotifyEventType int mask, String path) {
             // look up our observer, fixing up the map if necessary...
             FileObserver observer = null;
 
@@ -144,7 +167,8 @@
 
         private native int init();
         private native void observe(int fd);
-        private native void startWatching(int fd, String[] paths, int mask, int[] wfds);
+        private native void startWatching(int fd, String[] paths,
+                @NotifyEventType int mask, int[] wfds);
         private native void stopWatching(int fd, int[] wfds);
     }
 
@@ -197,7 +221,7 @@
      * @deprecated use {@link #FileObserver(File, int)} instead.
      */
     @Deprecated
-    public FileObserver(String path, int mask) {
+    public FileObserver(String path, @NotifyEventType int mask) {
         this(new File(path), mask);
     }
 
@@ -209,7 +233,7 @@
      * @param file The file or directory to monitor
      * @param mask The event or events (added together) to watch for
      */
-    public FileObserver(@NonNull File file, int mask) {
+    public FileObserver(@NonNull File file, @NotifyEventType int mask) {
         this(Arrays.asList(file), mask);
     }
 
@@ -220,7 +244,7 @@
      * @param files The files or directories to monitor
      * @param mask The event or events (added together) to watch for
      */
-    public FileObserver(@NonNull List<File> files, int mask) {
+    public FileObserver(@NonNull List<File> files, @NotifyEventType int mask) {
         mFiles = files;
         mMask = mask;
     }
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 868a36b..ce28c30 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -197,6 +197,7 @@
      */
     @SystemApi
     public interface MediaNative {
+        /** The flag namespace for media native features. */
         String NAMESPACE = "media_native";
     }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8acdc8c..0d7e00f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7483,6 +7483,7 @@
          * @hide
          */
         @SystemApi
+        @TestApi
         public static final String DOZE_ALWAYS_ON = "doze_always_on";
 
         private static final Validator DOZE_ALWAYS_ON_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -11416,7 +11417,7 @@
         /**
          * Feature flag to enable or disable the activity starts logging feature.
          * Type: int (0 for false, 1 for true)
-         * Default: 0
+         * Default: 1
          * @hide
          */
         public static final String ACTIVITY_STARTS_LOGGING_ENABLED
@@ -14200,10 +14201,24 @@
          * Configuration flags for SQLite Compatibility WAL. Encoded as a key-value list, separated
          * by commas. E.g.: compatibility_wal_supported=true, wal_syncmode=OFF
          *
-         * Supported keys:
-         * compatibility_wal_supported      (boolean)
-         * wal_syncmode       (String)
-         * truncate_size      (int)
+         * Supported keys:<br/>
+         * <li>
+         * <ul> {@code legacy_compatibility_wal_enabled} : A {code boolean} flag that determines
+         * whether or not "compatibility WAL" mode is enabled by default. This is a legacy flag
+         * and is honoured on Android Q and higher. This flag will be removed in a future release.
+         * </ul>
+         * <ul> {@code wal_syncmode} : A {@code String} representing the synchronization mode to use
+         * when WAL is enabled, either via {@code legacy_compatibility_wal_enabled} or using the
+         * obsolete {@code compatibility_wal_supported} flag.
+         * </ul>
+         * <ul> {@code truncate_size} : A {@code int} flag that specifies the truncate size of the
+         * WAL journal.
+         * </ul>
+         * <ul> {@code compatibility_wal_supported} : A {code boolean} flag that specifies whether
+         * the legacy "compatibility WAL" mode is enabled by default. This flag is obsolete and is
+         * only supported on Android Pie.
+         * </ul>
+         * </li>
          *
          * @hide
          */
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 3e8002f..60daddd 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -156,6 +156,17 @@
     }
 
     /**
+     * Called when a display config changed event is received.
+     *
+     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
+     * timebase.
+     * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
+     * @param configId The new config Id
+     */
+    public void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId) {
+    }
+
+    /**
      * Schedules a single vertical sync pulse to be delivered when the next
      * display frame begins.
      */
@@ -182,4 +193,11 @@
     private void dispatchHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
         onHotplug(timestampNanos, physicalDisplayId, connected);
     }
+
+    // Called from native code.
+    @SuppressWarnings("unused")
+    private void dispatchConfigChanged(long timestampNanos, long physicalDisplayId, int configId) {
+        onConfigChanged(timestampNanos, physicalDisplayId, configId);
+    }
+
 }
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index dd88e3c..50ef91f 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -20,6 +20,7 @@
 import static android.view.InsetsState.INSET_SIDE_LEFT;
 import static android.view.InsetsState.INSET_SIDE_RIGHT;
 import static android.view.InsetsState.INSET_SIDE_TOP;
+import static android.view.InsetsState.toPublicType;
 
 import android.annotation.Nullable;
 import android.graphics.Insets;
@@ -33,6 +34,7 @@
 import android.view.InsetsState.InsetSide;
 import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
 import android.view.WindowInsets.Type.InsetType;
+import android.view.WindowInsetsAnimationListener.InsetsAnimation;
 import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -66,8 +68,12 @@
     private final Supplier<SyncRtSurfaceTransactionApplier> mTransactionApplierSupplier;
     private final InsetsController mController;
     private final WindowInsetsAnimationListener.InsetsAnimation mAnimation;
+    private final Rect mFrame;
     private Insets mCurrentInsets;
     private Insets mPendingInsets;
+    private boolean mFinished;
+    private boolean mCancelled;
+    private int mFinishedShownTypes;
 
     @VisibleForTesting
     public InsetsAnimationControlImpl(SparseArray<InsetsSourceConsumer> consumers, Rect frame,
@@ -86,6 +92,7 @@
                 null /* typeSideMap */);
         mShownInsets = calculateInsets(mInitialInsetsState, frame, consumers, true /* shown */,
                 mTypeSideMap);
+        mFrame = new Rect(frame);
         buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mConsumers);
 
         // TODO: Check for controllability first and wait for IME if needed.
@@ -119,12 +126,26 @@
 
     @Override
     public void changeInsets(Insets insets) {
+        if (mFinished) {
+            throw new IllegalStateException(
+                    "Can't change insets on an animation that is finished.");
+        }
+        if (mCancelled) {
+            throw new IllegalStateException(
+                    "Can't change insets on an animation that is cancelled.");
+        }
         mPendingInsets = sanitize(insets);
         mController.scheduleApplyChangeInsets();
     }
 
     @VisibleForTesting
-    public void applyChangeInsets(InsetsState state) {
+    /**
+     * @return Whether the finish callback of this animation should be invoked.
+     */
+    public boolean applyChangeInsets(InsetsState state) {
+        if (mCancelled) {
+            return false;
+        }
         final Insets offset = Insets.subtract(mShownInsets, mPendingInsets);
         ArrayList<SurfaceParams> params = new ArrayList<>();
         if (offset.left != 0) {
@@ -144,13 +165,40 @@
         SyncRtSurfaceTransactionApplier applier = mTransactionApplierSupplier.get();
         applier.scheduleApply(params.toArray(new SurfaceParams[params.size()]));
         mCurrentInsets = mPendingInsets;
+        if (mFinished) {
+            mController.notifyFinished(this, mFinishedShownTypes);
+        }
+        return mFinished;
     }
 
     @Override
     public void finish(int shownTypes) {
-        // TODO
+        if (mCancelled) {
+            return;
+        }
+        InsetsState state = new InsetsState(mController.getState());
+        for (int i = mConsumers.size() - 1; i >= 0; i--) {
+            InsetsSourceConsumer consumer = mConsumers.valueAt(i);
+            boolean visible = (shownTypes & toPublicType(consumer.getType())) != 0;
+            state.getSource(consumer.getType()).setVisible(visible);
+        }
+        Insets insets = getInsetsFromState(state, mFrame, null /* typeSideMap */);
+        changeInsets(insets);
+        mFinished = true;
+        mFinishedShownTypes = shownTypes;
+    }
 
-        mController.dispatchAnimationFinished(mAnimation);
+    @VisibleForTesting
+    public void onCancelled() {
+        if (mFinished) {
+            return;
+        }
+        mCancelled = true;
+        mListener.onCancelled();
+    }
+
+    InsetsAnimation getAnimation() {
+        return mAnimation;
     }
 
     private Insets calculateInsets(InsetsState state, Rect frame,
@@ -225,4 +273,3 @@
         }
     }
 }
-
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 2586000..08f2e8d 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -17,6 +17,8 @@
 package android.view;
 
 import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.toPublicType;
+import static android.view.WindowInsets.Type.all;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -99,6 +101,7 @@
 
     private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();
     private final ArrayList<InsetsAnimationControlImpl> mAnimationControls = new ArrayList<>();
+    private final ArrayList<InsetsAnimationControlImpl> mTmpFinishedControls = new ArrayList<>();
     private WindowInsets mLastInsets;
 
     private boolean mAnimCallbackScheduled;
@@ -107,7 +110,6 @@
 
     private final Rect mLastLegacyContentInsets = new Rect();
     private final Rect mLastLegacyStableInsets = new Rect();
-    private ObjectAnimator mAnimator;
     private @AnimationDirection int mAnimationDirection;
 
     private int mPendingTypesToShow;
@@ -122,19 +124,29 @@
                 return;
             }
 
+            mTmpFinishedControls.clear();
             InsetsState state = new InsetsState(mState, true /* copySources */);
             for (int i = mAnimationControls.size() - 1; i >= 0; i--) {
-                mAnimationControls.get(i).applyChangeInsets(state);
+                InsetsAnimationControlImpl control = mAnimationControls.get(i);
+                if (mAnimationControls.get(i).applyChangeInsets(state)) {
+                    mTmpFinishedControls.add(control);
+                }
             }
+
             WindowInsets insets = state.calculateInsets(mFrame, mLastInsets.isRound(),
                     mLastInsets.shouldAlwaysConsumeNavBar(), mLastInsets.getDisplayCutout(),
                     mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode,
                     null /* typeSideMap */);
             mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets);
+
+            for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) {
+                dispatchAnimationFinished(mTmpFinishedControls.get(i).getAnimation());
+            }
         };
     }
 
-    void onFrameChanged(Rect frame) {
+    @VisibleForTesting
+    public void onFrameChanged(Rect frame) {
         if (mFrame.equals(frame)) {
             return;
         }
@@ -279,7 +291,8 @@
             // nothing to animate.
             return;
         }
-        // TODO: Check whether we already have a controller.
+        cancelExistingControllers(types);
+
         final ArraySet<Integer> internalTypes = mState.toInternalType(types);
         final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
 
@@ -321,7 +334,7 @@
                     // Show request
                     switch(consumer.requestShow(fromIme)) {
                         case ShowResult.SHOW_IMMEDIATELY:
-                            typesReady |= InsetsState.toPublicType(TYPE_IME);
+                            typesReady |= InsetsState.toPublicType(consumer.getType());
                             break;
                         case ShowResult.SHOW_DELAYED:
                             isReady = false;
@@ -365,6 +378,36 @@
         return typesReady;
     }
 
+    private void cancelExistingControllers(@InsetType int types) {
+        for (int i = mAnimationControls.size() - 1; i >= 0; i--) {
+            InsetsAnimationControlImpl control = mAnimationControls.get(i);
+            if ((control.getTypes() & types) != 0) {
+                cancelAnimation(control);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    public void notifyFinished(InsetsAnimationControlImpl controller, int shownTypes) {
+        mAnimationControls.remove(controller);
+        hideDirectly(controller.getTypes() & ~shownTypes);
+        showDirectly(controller.getTypes() & shownTypes);
+    }
+
+    void notifyControlRevoked(InsetsSourceConsumer consumer) {
+        for (int i = mAnimationControls.size() - 1; i >= 0; i--) {
+            InsetsAnimationControlImpl control = mAnimationControls.get(i);
+            if ((control.getTypes() & toPublicType(consumer.getType())) != 0) {
+                cancelAnimation(control);
+            }
+        }
+    }
+
+    private void cancelAnimation(InsetsAnimationControlImpl control) {
+        control.onCancelled();
+        mAnimationControls.remove(control);
+    }
+
     private void applyLocalVisibilityOverride() {
         for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
             final InsetsSourceConsumer controller = mSourceConsumers.valueAt(i);
@@ -455,8 +498,13 @@
         }
 
         WindowInsetsAnimationControlListener listener = new WindowInsetsAnimationControlListener() {
+
+            private WindowInsetsAnimationController mController;
+            private ObjectAnimator mAnimator;
+
             @Override
             public void onReady(WindowInsetsAnimationController controller, int types) {
+                mController = controller;
                 if (show) {
                     showDirectly(types);
                 } else {
@@ -474,10 +522,6 @@
                         : ANIMATION_DURATION_HIDE_MS);
                 mAnimator.setInterpolator(INTERPOLATOR);
                 mAnimator.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationCancel(Animator animation) {
-                        onAnimationFinish();
-                    }
 
                     @Override
                     public void onAnimationEnd(Animator animation) {
@@ -488,15 +532,15 @@
             }
 
             @Override
-            public void onCancelled() {}
+            public void onCancelled() {
+                mAnimator.cancel();
+            }
 
             private void onAnimationFinish() {
                 mAnimationDirection = DIRECTION_NONE;
+                mController.finish(show ? types : 0);
             }
         };
-        // TODO: Instead of clearing this here, properly wire up
-        // InsetsAnimationControlImpl.finish() to remove this from mAnimationControls.
-        mAnimationControls.clear();
 
         // Show/hide animations always need to be relative to the display frame, in order that shown
         // and hidden state insets are correct.
@@ -522,10 +566,7 @@
      */
     @VisibleForTesting
     public void cancelExistingAnimation() {
-        mAnimationDirection = DIRECTION_NONE;
-        if (mAnimator != null) {
-            mAnimator.cancel();
-        }
+        cancelExistingControllers(all());
     }
 
     void dump(String prefix, PrintWriter pw) {
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index eab83ce..1383463 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -77,6 +77,9 @@
         if (applyLocalVisibilityOverride()) {
             mController.notifyVisibilityChanged();
         }
+        if (mSourceControl == null) {
+            mController.notifyControlRevoked(this);
+        }
     }
 
     @VisibleForTesting
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index c24b8b2..7c69cfd 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -201,7 +201,7 @@
         mListener = listener;
         final ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
         mSpanSlop = viewConfiguration.getScaledTouchSlop() * 2;
-        mMinSpan = viewConfiguration.getScaledMinScalingSpan();
+        mMinSpan = viewConfiguration.getScaledMinimumScalingSpan();
         mHandler = handler;
         // Quick scale is enabled by default after JB_MR2
         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index ee91c85..ea7f31d 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -158,6 +158,8 @@
             IBinder displayToken, long numFrames, long timestamp);
     private static native int nativeGetActiveConfig(IBinder displayToken);
     private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
+    private static native boolean nativeSetAllowedDisplayConfigs(IBinder displayToken,
+                                                                 int[] allowedConfigs);
     private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
     private static native SurfaceControl.DisplayPrimaries nativeGetDisplayNativePrimaries(
             IBinder displayToken);
@@ -1522,6 +1524,20 @@
     /**
      * @hide
      */
+    public static boolean setAllowedDisplayConfigs(IBinder displayToken, int[] allowedConfigs) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (allowedConfigs == null) {
+            throw new IllegalArgumentException("allowedConfigs must not be null");
+        }
+
+        return nativeSetAllowedDisplayConfigs(displayToken, allowedConfigs);
+    }
+
+    /**
+     * @hide
+     */
     public static int[] getDisplayColorModes(IBinder displayToken) {
         if (displayToken == null) {
             throw new IllegalArgumentException("displayToken must not be null");
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1a9d3a0..7afdc70 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10968,7 +10968,7 @@
     }
 
     void dispatchWindowInsetsAnimationFinished(InsetsAnimation animation) {
-        if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
+        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
             mListenerInfo.mWindowInsetsAnimationListener.onFinished(animation);
         }
     }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index c030ac2..81e9c13 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -979,7 +979,7 @@
      * @throws IllegalStateException if this method is called on a ViewConfiguration that was
      *         instantiated using a constructor with no Context parameter.
      */
-    public int getScaledMinScalingSpan() {
+    public int getScaledMinimumScalingSpan() {
         if (!mConstructedWithContext) {
             throw new IllegalStateException("Min scaling span cannot be determined when this "
                     + "method is called on a ViewConfiguration that was instantiated using a "
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index c1536ae..135a891 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -28,6 +28,7 @@
 import static android.view.WindowInsets.Type.indexOf;
 
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
@@ -700,7 +701,8 @@
      * @return the inset insets
      */
     @NonNull
-    public WindowInsets inset(int left, int top, int right, int bottom) {
+    public WindowInsets inset(@IntRange(from = 0) int left, @IntRange(from = 0) int top,
+            @IntRange(from = 0) int right, @IntRange(from = 0) int bottom) {
         Preconditions.checkArgumentNonnegative(left);
         Preconditions.checkArgumentNonnegative(top);
         Preconditions.checkArgumentNonnegative(right);
@@ -794,7 +796,7 @@
     /**
      * Builder for WindowInsets.
      */
-    public static class Builder {
+    public static final class Builder {
 
         private final Insets[] mTypeInsetsMap;
         private final Insets[] mTypeMaxInsetsMap;
@@ -821,7 +823,7 @@
          *
          * @param insets the instance to initialize from.
          */
-        public Builder(WindowInsets insets) {
+        public Builder(@NonNull WindowInsets insets) {
             mTypeInsetsMap = insets.mTypeInsetsMap.clone();
             mTypeMaxInsetsMap = insets.mTypeMaxInsetsMap.clone();
             mTypeVisibilityMap = insets.mTypeVisibilityMap.clone();
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index a6129b0..f44c331 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -312,7 +312,7 @@
      * @return The view that is currently selected, if it happens to be in the
      *         range that we draw.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private View fillDown(int pos, int nextTop) {
         View selectedView = null;
 
@@ -412,7 +412,7 @@
      *
      * @return The view that is currently selected
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private View fillUp(int pos, int nextBottom) {
         View selectedView = null;
 
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 2aa019b..2f44d6e 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -782,7 +782,7 @@
      * @return The view that is currently selected, if it happens to be in the
      *         range that we draw.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private View fillDown(int pos, int nextTop) {
         View selectedView = null;
 
@@ -817,7 +817,7 @@
      *
      * @return The view that is currently selected
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private View fillUp(int pos, int nextBottom) {
         View selectedView = null;
 
@@ -1490,7 +1490,7 @@
      * @return The selected view, or null if the selected view is outside the
      *         visible area.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private View fillSpecific(int position, int top) {
         boolean tempIsSelected = position == mSelectedPosition;
         View temp = makeAndAddView(position, top, true, mListPadding.left, tempIsSelected);
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 2c78be7..bab4787 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -568,7 +568,7 @@
     }
 
     /**
-     * Aggregated data by uid/class/method to be sent through WestWorld.
+     * Aggregated data by uid/class/method to be sent through statsd.
      */
     public static class ExportedCallStat {
         public int callingUid;
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/jni/android_media_AudioProductStrategies.cpp b/core/jni/android_media_AudioProductStrategies.cpp
index a18e80a..d7d31e5 100644
--- a/core/jni/android_media_AudioProductStrategies.cpp
+++ b/core/jni/android_media_AudioProductStrategies.cpp
@@ -194,12 +194,34 @@
     return jStatus;
 }
 
+static jint
+android_media_AudioSystem_getProductStrategyFromAudioAttributes(JNIEnv *env, jobject clazz,
+                                                                jobject jAudioAttributes)
+{
+    JNIAudioAttributeHelper::UniqueAaPtr attributes = JNIAudioAttributeHelper::makeUnique();
+    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env,
+                                                           jAudioAttributes,
+                                                           attributes.get());
+    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+        return jStatus;
+    }
+    product_strategy_t psId;
+    status_t status = AudioSystem::getProductStrategyFromAudioAttributes(
+            AudioAttributes(*attributes.get()), psId);
+    if (status != NO_ERROR) {
+        return nativeToJavaStatus(status);
+    }
+    return psId;
+}
+
 /*
  * JNI registration.
  */
 static const JNINativeMethod gMethods[] = {
     {"native_list_audio_product_strategies", "(Ljava/util/ArrayList;)I",
                         (void *)android_media_AudioSystem_listAudioProductStrategies},
+    {"native_get_product_strategies_from_audio_attributes", "(Landroid/media/AudioAttributes;)I",
+                        (void *)android_media_AudioSystem_getProductStrategyFromAudioAttributes},
 };
 
 int register_android_media_AudioProductStrategies(JNIEnv *env)
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 191472d..8d702d1 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -41,6 +41,7 @@
 
     jmethodID dispatchVsync;
     jmethodID dispatchHotplug;
+    jmethodID dispatchConfigChanged;
 } gDisplayEventReceiverClassInfo;
 
 
@@ -61,6 +62,8 @@
 
     void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override;
     void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
+    void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
+                               int32_t configId) override;
 };
 
 
@@ -114,6 +117,23 @@
     mMessageQueue->raiseAndClearException(env, "dispatchHotplug");
 }
 
+void NativeDisplayEventReceiver::dispatchConfigChanged(nsecs_t timestamp,
+                                                       PhysicalDisplayId displayId,
+                                                       int32_t configId) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
+    if (receiverObj.get()) {
+        ALOGV("receiver %p ~ Invoking config changed handler.", this);
+        env->CallVoidMethod(receiverObj.get(),
+                            gDisplayEventReceiverClassInfo.dispatchConfigChanged,
+                            timestamp, displayId, configId);
+        ALOGV("receiver %p ~ Returned from config changed handler.", this);
+    }
+
+    mMessageQueue->raiseAndClearException(env, "dispatchConfigChanged");
+}
+
 
 static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
         jobject messageQueueObj, jint vsyncSource) {
@@ -180,6 +200,8 @@
             gDisplayEventReceiverClassInfo.clazz, "dispatchVsync", "(JJI)V");
     gDisplayEventReceiverClassInfo.dispatchHotplug = GetMethodIDOrDie(env,
             gDisplayEventReceiverClassInfo.clazz, "dispatchHotplug", "(JJZ)V");
+    gDisplayEventReceiverClassInfo.dispatchConfigChanged = GetMethodIDOrDie(env,
+           gDisplayEventReceiverClassInfo.clazz, "dispatchConfigChanged", "(JJI)V");
 
     return res;
 }
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 4069e95..4c25fd4 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -698,6 +698,25 @@
     return configArray;
 }
 
+static jboolean nativeSetAllowedDisplayConfigs(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jintArray configArray) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == nullptr) return JNI_FALSE;
+
+    std::vector<int32_t> allowedConfigs;
+    jsize configArraySize = env->GetArrayLength(configArray);
+    allowedConfigs.reserve(configArraySize);
+
+    jint* configArrayElements = env->GetIntArrayElements(configArray, 0);
+    for (int i = 0; i < configArraySize; i++) {
+        allowedConfigs.push_back(configArrayElements[i]);
+    }
+    env->ReleaseIntArrayElements(configArray, configArrayElements, 0);
+
+    size_t result = SurfaceComposerClient::setAllowedDisplayConfigs(token, allowedConfigs);
+    return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
+}
+
 static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
     if (token == NULL) return -1;
@@ -1194,6 +1213,8 @@
             (void*)nativeGetActiveConfig },
     {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
             (void*)nativeSetActiveConfig },
+    {"nativeSetAllowedDisplayConfigs", "(Landroid/os/IBinder;[I)Z",
+            (void*)nativeSetAllowedDisplayConfigs },
     {"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
             (void*)nativeGetDisplayColorModes},
     {"nativeGetDisplayNativePrimaries", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayPrimaries;",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 7443c36..2ccb01a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1240,6 +1240,8 @@
 
     // Turn fdsan back on.
     android_fdsan_set_error_level(fdsan_error_level);
+  } else {
+    ALOGD("Forked child process %d", pid);
   }
 
   // We blocked SIGCHLD prior to a fork, we unblock it here.
diff --git a/core/res/res/drawable/ic_qs_battery_saver.xml b/core/res/res/drawable/ic_qs_battery_saver.xml
index 89b2569..93975b6 100644
--- a/core/res/res/drawable/ic_qs_battery_saver.xml
+++ b/core/res/res/drawable/ic_qs_battery_saver.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2018 The Android Open Source Project
+    Copyright (C) 2019 The Android Open Source Project
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -21,8 +21,10 @@
         android:viewportHeight="24.0"
         android:tint="?android:attr/colorControlNormal">
     <path
-            android:pathData="M5,3
-            l3.5,0 l0,-1.5 l7,0 l0,1.5 l3.5,0 l0,19.5 l-14,0z
-            M10.5,8.5 l0,3 l-3,0 l0,3 l3,0 l0,3 l3,0 l0,-3 l3,0 l0,-3 l-3,0 l0,-3 z"
-            android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFF"
+        android:pathData="M16.67,4H14.5V2h-5v2H7.33C6.6,4 6,4.6 6,5.33V15v5.67C6,21.4 6.6,22 7.33,22h9.33C17.4,22 18,21.4 18,20.67V15V5.33C18,4.6 17.4,4 16.67,4zM16,15v5H8v-5V6h8V15z"/>
+    <path
+        android:fillColor="#FFF"
+        android:pathData="M15,12l-2,0l0,-2l-2,0l0,2l-2,0l0,2l2,0l0,2l2,0l0,-2l2,0z"/>
+
 </vector>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0041bfc..910af4c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2008,11 +2008,6 @@
          a transaction, so it interacts poorly with SECURE_DELETE. -->
     <string name="db_default_journal_mode" translatable="false">TRUNCATE</string>
 
-    <!-- Enables compatibility WAL mode.
-         In this mode, only database journal mode will be changed, connection pool
-         size will still be limited to a single connection. -->
-    <bool name="db_compatibility_wal_supported">true</bool>
-
     <!-- Maximum size of the persistent journal file in bytes.
          If the journal file grows to be larger than this amount then SQLite will
          truncate it after committing the transaction. -->
@@ -3935,4 +3930,25 @@
          The same restrictions apply to this array. -->
     <array name="config_displayWhiteBalanceDisplayColorTemperatures">
     </array>
+
+    <!-- All of the paths defined for the batterymeter are defined on a 12x20 canvas, and must
+     be parsable by android.utill.PathParser -->
+    <string name="config_batterymeterPerimeterPath" translatable="false">
+		M3.5,2 v0 H1.33 C0.6,2 0,2.6 0,3.33 V13v5.67 C0,19.4 0.6,20 1.33,20 h9.33 C11.4,20 12,19.4 12,18.67 V13V3.33 C12,2.6 11.4,2 10.67,2 H8.5 V0 H3.5 z M2,18v-7V4h8v9v5H2L2,18z
+    </string>
+
+    <string name="config_batterymeterFillMask" translatable="false">
+        M2,18 v-14 h8 v14 z
+    </string>
+    <string name="config_batterymeterBoltPath" translatable="false">
+        M5,17.5 V12 H3 L7,4.5 V10 h2 L5,17.5 z
+    </string>
+    <string name="config_batterymeterPowersavePath" translatable="false">
+		M9,10l-2,0l0,-2l-2,0l0,2l-2,0l0,2l2,0l0,2l2,0l0,-2l2,0z
+    </string>
+
+    <!-- A dual tone battery meter draws the perimeter path twice - once to define the shape
+     and a second time clipped to the fill level to indicate charge -->
+    <bool name="config_batterymeterDualTone">false</bool>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 33ca311..426d813 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -752,7 +752,6 @@
   <java-symbol type="string" name="date_time" />
   <java-symbol type="string" name="date_time_set" />
   <java-symbol type="string" name="date_time_done" />
-  <java-symbol type="bool" name="db_compatibility_wal_supported" />
   <java-symbol type="string" name="db_default_journal_mode" />
   <java-symbol type="string" name="db_default_sync_mode" />
   <java-symbol type="string" name="db_wal_sync_mode" />
@@ -3197,6 +3196,11 @@
   <java-symbol type="raw" name="fallback_categories" />
 
   <java-symbol type="string" name="config_icon_mask" />
+  <java-symbol type="string" name="config_batterymeterPerimeterPath" />
+  <java-symbol type="string" name="config_batterymeterFillMask" />
+  <java-symbol type="string" name="config_batterymeterBoltPath" />
+  <java-symbol type="string" name="config_batterymeterPowersavePath" />
+  <java-symbol type="bool" name="config_batterymeterDualTone" />
 
   <!-- Accessibility Shortcut -->
   <java-symbol type="string" name="accessibility_shortcut_warning_dialog_title" />
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/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
index 5dbcb3c..82bd588 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.content.Context;
 import android.database.DatabaseUtils;
@@ -54,44 +55,52 @@
     @Test
     public void testParseConfig() {
         SQLiteCompatibilityWalFlags.init("");
-        assertFalse(SQLiteCompatibilityWalFlags.areFlagsSet());
-
         SQLiteCompatibilityWalFlags.init(null);
-        assertFalse(SQLiteCompatibilityWalFlags.areFlagsSet());
 
-        SQLiteCompatibilityWalFlags.init("compatibility_wal_supported=false,wal_syncmode=OFF");
-        assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
-        assertFalse(SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
-        assertEquals("OFF", SQLiteCompatibilityWalFlags.getWALSyncMode());
+        // Ensure that legacy compatibility wal isn't turned on by the old flag.
+        SQLiteCompatibilityWalFlags.init("compatibility_wal_supported=true,wal_syncmode=OFF");
+        assertFalse(SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled());
+        try {
+            SQLiteCompatibilityWalFlags.getWALSyncMode();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
         assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
 
+
         SQLiteCompatibilityWalFlags.init("wal_syncmode=VALUE");
-        assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
-        assertEquals(SQLiteGlobal.isCompatibilityWalSupported(),
-                SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
-        assertEquals("VALUE", SQLiteCompatibilityWalFlags.getWALSyncMode());
+        assertFalse(SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled());
         assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
+        try {
+            SQLiteCompatibilityWalFlags.getWALSyncMode();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
 
-        SQLiteCompatibilityWalFlags.init("compatibility_wal_supported=true");
-        assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
+        SQLiteCompatibilityWalFlags.init("legacy_compatibility_wal_enabled=true");
+        assertTrue(SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled());
         assertEquals(SQLiteGlobal.getWALSyncMode(),
                 SQLiteCompatibilityWalFlags.getWALSyncMode());
-        assertTrue(SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
-        assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
+
+        SQLiteCompatibilityWalFlags.init(
+                "legacy_compatibility_wal_enabled=true,wal_syncmode=VALUE");
+        assertTrue(SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled());
+        assertEquals("VALUE", SQLiteCompatibilityWalFlags.getWALSyncMode());
 
         SQLiteCompatibilityWalFlags.init("truncate_size=1024");
         assertEquals(1024, SQLiteCompatibilityWalFlags.getTruncateSize());
 
         SQLiteCompatibilityWalFlags.reset();
         SQLiteCompatibilityWalFlags.init("Invalid value");
-        assertFalse(SQLiteCompatibilityWalFlags.areFlagsSet());
+        assertFalse(SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled());
     }
 
     @Test
     public void testApplyFlags() {
         Context ctx = InstrumentationRegistry.getContext();
 
-        SQLiteCompatibilityWalFlags.init("compatibility_wal_supported=true,wal_syncmode=NORMAL");
+        SQLiteCompatibilityWalFlags.init(
+                "legacy_compatibility_wal_enabled=true,wal_syncmode=NORMAL");
         mDatabase = SQLiteDatabase
                 .openOrCreateDatabase(ctx.getDatabasePath("SQLiteCompatibilityWalFlagsTest"), null);
         String journalMode = DatabaseUtils.stringForQuery(mDatabase, "PRAGMA journal_mode", null);
@@ -100,5 +109,22 @@
         assertEquals("Normal mode (1) is expected", "1", syncMode);
     }
 
+    @Test
+    public void testApplyFlags_thenDisableWriteAheadLogging() {
+        Context ctx = InstrumentationRegistry.getContext();
 
+        SQLiteCompatibilityWalFlags.init(
+                "legacy_compatibility_wal_enabled=true,wal_syncmode=FULL");
+        mDatabase = SQLiteDatabase
+                .openOrCreateDatabase(ctx.getDatabasePath("SQLiteCompatibilityWalFlagsTest"), null);
+
+        mDatabase.disableWriteAheadLogging();
+        String journalMode = DatabaseUtils.stringForQuery(mDatabase, "PRAGMA journal_mode", null);
+        assertEquals(SQLiteGlobal.getDefaultJournalMode(), journalMode.toUpperCase());
+        String syncMode = DatabaseUtils.stringForQuery(mDatabase, "PRAGMA synchronous", null);
+        // TODO: This is the old behaviour and seems incorrect. The specified wal_syncmode was only
+        // intended to be used if the database is in WAL mode, and we should revert to the global
+        // default sync mode if WAL is disabled.
+        assertEquals("Normal mode (2) is expected", "2", syncMode);
+    }
 }
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 71ce02d..23ab05e 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -129,6 +129,29 @@
         assertPosition(navParams.matrix, new Rect(400, 0, 500, 500), new Rect(460, 0, 560, 500));
     }
 
+    @Test
+    public void testFinishing() {
+        when(mMockController.getState()).thenReturn(mInsetsState);
+        mController.finish(sideBars());
+        mController.applyChangeInsets(mInsetsState);
+        assertFalse(mInsetsState.getSource(TYPE_TOP_BAR).isVisible());
+        assertTrue(mInsetsState.getSource(TYPE_NAVIGATION_BAR).isVisible());
+        assertEquals(Insets.of(0, 0, 100, 0), mController.getCurrentInsets());
+        verify(mMockController).notifyFinished(eq(mController), eq(sideBars()));
+    }
+
+    @Test
+    public void testCancelled() {
+        mController.onCancelled();
+        try {
+            mController.changeInsets(Insets.NONE);
+            fail("Expected exception to be thrown");
+        } catch (IllegalStateException ignored) {
+        }
+        verify(mMockListener).onCancelled();
+        mController.finish(sideBars());
+    }
+
     private void assertPosition(Matrix m, Rect original, Rect transformed) {
         RectF rect = new RectF(original);
         rect.offsetTo(0, 0);
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 731d564..d71bde83 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -20,6 +20,7 @@
 import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.TYPE_TOP_BAR;
 
+import static android.view.WindowInsets.Type.topBar;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -48,6 +49,9 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.concurrent.CountDownLatch;
 
 @Presubmit
 @FlakyTest(detail = "Promote once confirmed non-flaky")
@@ -80,6 +84,8 @@
                     new DisplayCutout(
                             Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
                     rect, rect, SOFT_INPUT_ADJUST_RESIZE);
+            mController.onFrameChanged(new Rect(0, 0, 100, 100));
+            mController.getState().setDisplayFrame(new Rect(0, 0, 100, 100));
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
@@ -101,6 +107,19 @@
     }
 
     @Test
+    public void testControlsRevoked_duringAnim() {
+        InsetsSourceControl control = new InsetsSourceControl(TYPE_TOP_BAR, mLeash, new Point());
+        mController.onControlsChanged(new InsetsSourceControl[] { control });
+
+        WindowInsetsAnimationControlListener mockListener =
+                mock(WindowInsetsAnimationControlListener.class);
+        mController.controlWindowInsetsAnimation(topBar(), mockListener);
+        verify(mockListener).onReady(any(), anyInt());
+        mController.onControlsChanged(new InsetsSourceControl[0]);
+        verify(mockListener).onCancelled();
+    }
+
+    @Test
     public void testFrameDoesntMatchDisplay() {
         mController.onFrameChanged(new Rect(0, 0, 100, 100));
         mController.getState().setDisplayFrame(new Rect(0, 0, 200, 200));
@@ -119,24 +138,21 @@
         InsetsSourceControl ime = controls[2];
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            // since there is no focused view, forcefully make IME visible.
+            mController.applyImeVisibility(true /* setVisible */);
             mController.show(Type.all());
             // quickly jump to final state by cancelling it.
             mController.cancelExistingAnimation();
             assertTrue(mController.getSourceConsumer(navBar.getType()).isVisible());
             assertTrue(mController.getSourceConsumer(topBar.getType()).isVisible());
-            // no focused view, no IME.
-            assertFalse(mController.getSourceConsumer(ime.getType()).isVisible());
+            assertTrue(mController.getSourceConsumer(ime.getType()).isVisible());
 
+            mController.applyImeVisibility(false /* setVisible */);
             mController.hide(Type.all());
             mController.cancelExistingAnimation();
             assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible());
             assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible());
             assertFalse(mController.getSourceConsumer(ime.getType()).isVisible());
-
-            mController.show(Type.ime());
-            mController.cancelExistingAnimation();
-            // no focused view, no IME.
-            assertFalse(mController.getSourceConsumer(ime.getType()).isVisible());
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
@@ -292,6 +308,35 @@
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
 
+    @Test
+    public void testAnimationEndState_controller() throws Exception {
+        InsetsSourceControl control = new InsetsSourceControl(TYPE_TOP_BAR, mLeash, new Point());
+        mController.onControlsChanged(new InsetsSourceControl[] { control });
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            WindowInsetsAnimationControlListener mockListener =
+                    mock(WindowInsetsAnimationControlListener.class);
+            mController.controlWindowInsetsAnimation(topBar(), mockListener);
+
+            ArgumentCaptor<WindowInsetsAnimationController> controllerCaptor =
+                    ArgumentCaptor.forClass(WindowInsetsAnimationController.class);
+            verify(mockListener).onReady(controllerCaptor.capture(), anyInt());
+            controllerCaptor.getValue().finish(0 /* shownTypes */);
+        });
+        waitUntilNextFrame();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            assertFalse(mController.getSourceConsumer(TYPE_TOP_BAR).isVisible());
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
+    private void waitUntilNextFrame() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
+                latch::countDown, null /* token */);
+        latch.await();
+    }
+
     private InsetsSourceControl[] prepareControls() {
         final InsetsSourceControl navBar = new InsetsSourceControl(TYPE_NAVIGATION_BAR, mLeash,
                 new Point());
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index aaf40b4..83c8b01 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -599,9 +599,6 @@
             int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
             @NonNull Paint paint) {
         checkRange(verts.length, vertOffset, vertexCount);
-        if (isHardwareAccelerated()) {
-            return;
-        }
         if (texs != null) {
             checkRange(texs.length, texOffset, vertexCount);
         }
diff --git a/libs/androidfw/DisplayEventDispatcher.cpp b/libs/androidfw/DisplayEventDispatcher.cpp
index 3b9a348..6606148 100644
--- a/libs/androidfw/DisplayEventDispatcher.cpp
+++ b/libs/androidfw/DisplayEventDispatcher.cpp
@@ -135,6 +135,9 @@
             case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                 dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
                 break;
+            case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+                dispatchConfigChanged(ev.header.timestamp, ev.header.displayId, ev.config.configId);
+                break;
             default:
                 ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);
                 break;
diff --git a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
index d2addba..5381c01 100644
--- a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
+++ b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
@@ -40,6 +40,8 @@
     virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) = 0;
     virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
                                  bool connected) = 0;
+    virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
+                                       int32_t configId) = 0;
 
     virtual int handleEvent(int receiveFd, int events, void* data);
     bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 733b866..abf0837 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -759,11 +759,11 @@
 
 void PointerController::loadResourcesLocked() REQUIRES(mLock) {
     mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
+    mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
 
+    mLocked.additionalMouseResources.clear();
+    mLocked.animationResources.clear();
     if (mLocked.presentation == PRESENTATION_POINTER) {
-        mLocked.additionalMouseResources.clear();
-        mLocked.animationResources.clear();
-        mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
         mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
                 &mLocked.animationResources, mLocked.viewport.displayId);
     }
diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt
index dbb581f..d1b39b3 100644
--- a/location/lib/api/current.txt
+++ b/location/lib/api/current.txt
@@ -11,7 +11,7 @@
     method public android.os.IBinder getBinder();
     method public boolean isEnabled();
     method @Deprecated protected void onDisable();
-    method protected void onDump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
+    method @Deprecated protected void onDump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
     method @Deprecated protected void onEnable();
     method @Deprecated protected int onGetStatus(android.os.Bundle);
     method @Deprecated protected long onGetStatusUpdateTime();
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index 7cd7207..fa113a8 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -240,8 +240,10 @@
     protected abstract void onSetRequest(ProviderRequestUnbundled request, WorkSource source);
 
     /**
-     * Dump debug information.
+     * @deprecated This callback will never be invoked on Android Q and above. This method may be
+     * removed in the future. Prefer to dump provider state via the containing service instead.
      */
+    @Deprecated
     protected void onDump(FileDescriptor fd, PrintWriter pw, String[] args) {}
 
     /**
@@ -336,10 +338,5 @@
         public void sendExtraCommand(String command, Bundle extras) {
             onSendExtraCommand(command, extras);
         }
-
-        @Override
-        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            onDump(fd, pw, args);
-        }
     }
 }
diff --git a/media/apex/java/android/media/MediaConstants.java b/media/apex/java/android/media/MediaConstants.java
index 65b6f55..776c1ba 100644
--- a/media/apex/java/android/media/MediaConstants.java
+++ b/media/apex/java/android/media/MediaConstants.java
@@ -27,6 +27,7 @@
     static final String KEY_SESSION2LINK = "android.media.key.SESSION2LINK";
     static final String KEY_ALLOWED_COMMANDS = "android.media.key.ALLOWED_COMMANDS";
     static final String KEY_PLAYBACK_ACTIVE = "android.media.key.PLAYBACK_ACTIVE";
+    static final String KEY_TOKEN_EXTRAS = "android.media.key.TOKEN_EXTRAS";
 
     private MediaConstants() {
     }
diff --git a/media/apex/java/android/media/MediaController2.java b/media/apex/java/android/media/MediaController2.java
index 4ea384a..2709df0 100644
--- a/media/apex/java/android/media/MediaController2.java
+++ b/media/apex/java/android/media/MediaController2.java
@@ -21,6 +21,7 @@
 import static android.media.MediaConstants.KEY_PID;
 import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
 import static android.media.MediaConstants.KEY_SESSION2LINK;
+import static android.media.MediaConstants.KEY_TOKEN_EXTRAS;
 import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR;
 import static android.media.Session2Command.RESULT_INFO_SKIPPED;
 import static android.media.Session2Token.TYPE_SESSION;
@@ -264,6 +265,7 @@
         Session2CommandGroup allowedCommands =
                 connectionResult.getParcelable(KEY_ALLOWED_COMMANDS);
         boolean playbackActive = connectionResult.getBoolean(KEY_PLAYBACK_ACTIVE);
+        Bundle tokenExtras = connectionResult.getBundle(KEY_TOKEN_EXTRAS);
         if (DEBUG) {
             Log.d(TAG, "notifyConnected sessionBinder=" + sessionBinder
                     + ", allowedCommands=" + allowedCommands);
@@ -282,7 +284,7 @@
             // so can be used without worrying about deadlock.
             sessionBinder.linkToDeath(mDeathRecipient, 0);
             mConnectedToken = new Session2Token(mSessionToken.getUid(), TYPE_SESSION,
-                    mSessionToken.getPackageName(), sessionBinder);
+                    mSessionToken.getPackageName(), sessionBinder, tokenExtras);
         }
         mCallbackExecutor.execute(() -> {
             mCallback.onConnected(MediaController2.this, allowedCommands);
diff --git a/media/apex/java/android/media/MediaSession2.java b/media/apex/java/android/media/MediaSession2.java
index 4c6945a..148e16c 100644
--- a/media/apex/java/android/media/MediaSession2.java
+++ b/media/apex/java/android/media/MediaSession2.java
@@ -21,6 +21,7 @@
 import static android.media.MediaConstants.KEY_PID;
 import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
 import static android.media.MediaConstants.KEY_SESSION2LINK;
+import static android.media.MediaConstants.KEY_TOKEN_EXTRAS;
 import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR;
 import static android.media.Session2Command.RESULT_INFO_SKIPPED;
 import static android.media.Session2Token.TYPE_SESSION;
@@ -94,7 +95,8 @@
     private ForegroundServiceEventCallback mForegroundServiceEventCallback;
 
     MediaSession2(@NonNull Context context, @NonNull String id, PendingIntent sessionActivity,
-            @NonNull Executor callbackExecutor, @NonNull SessionCallback callback) {
+            @NonNull Executor callbackExecutor, @NonNull SessionCallback callback,
+            Bundle tokenExtras) {
         synchronized (MediaSession2.class) {
             if (SESSION_ID_LIST.contains(id)) {
                 throw new IllegalStateException("Session ID must be unique. ID=" + id);
@@ -109,7 +111,7 @@
         mCallback = callback;
         mSessionStub = new Session2Link(this);
         mSessionToken = new Session2Token(Process.myUid(), TYPE_SESSION, context.getPackageName(),
-                mSessionStub);
+                mSessionStub, tokenExtras);
         mSessionManager = (MediaSessionManager) mContext.getSystemService(
                 Context.MEDIA_SESSION_SERVICE);
         // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
@@ -339,6 +341,7 @@
                 connectionResult.putParcelable(KEY_ALLOWED_COMMANDS,
                         controllerInfo.mAllowedCommands);
                 connectionResult.putBoolean(KEY_PLAYBACK_ACTIVE, isPlaybackActive());
+                connectionResult.putBundle(KEY_TOKEN_EXTRAS, mSessionToken.getExtras());
 
                 // Double check if session is still there, because close() can be called in
                 // another thread.
@@ -444,6 +447,7 @@
         private PendingIntent mSessionActivity;
         private Executor mCallbackExecutor;
         private SessionCallback mCallback;
+        private Bundle mExtras;
 
         /**
          * Creates a builder for {@link MediaSession2}.
@@ -507,6 +511,18 @@
         }
 
         /**
+         * Set extras for the session token.
+         *
+         * @return The Builder to allow chaining
+         * @see Session2Token#getExtras()
+         */
+        @NonNull
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
          * Build {@link MediaSession2}.
          *
          * @return a new session
@@ -525,7 +541,7 @@
                 mId = "";
             }
             MediaSession2 session2 = new MediaSession2(mContext, mId, mSessionActivity,
-                    mCallbackExecutor, mCallback);
+                    mCallbackExecutor, mCallback, mExtras);
 
             // Notify framework about the newly create session after the constructor is finished.
             // Otherwise, framework may access the session before the initialization is finished.
diff --git a/media/apex/java/android/media/Session2Token.java b/media/apex/java/android/media/Session2Token.java
index 238cc2b..6680e40 100644
--- a/media/apex/java/android/media/Session2Token.java
+++ b/media/apex/java/android/media/Session2Token.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -88,6 +89,7 @@
     private final String mServiceName;
     private final Session2Link mSessionLink;
     private final ComponentName mComponentName;
+    private final Bundle mExtras;
 
     /**
      * Constructor for the token with type {@link #TYPE_SESSION_SERVICE}.
@@ -116,15 +118,18 @@
         mUid = uid;
         mType = TYPE_SESSION_SERVICE;
         mSessionLink = null;
+        mExtras = null;
     }
 
-    Session2Token(int uid, int type, String packageName, Session2Link sessionLink) {
+    Session2Token(int uid, int type, String packageName, Session2Link sessionLink,
+            Bundle tokenExtras) {
         mUid = uid;
         mType = type;
         mPackageName = packageName;
         mServiceName = null;
         mComponentName = null;
         mSessionLink = sessionLink;
+        mExtras = tokenExtras;
     }
 
     Session2Token(Parcel in) {
@@ -134,6 +139,7 @@
         mServiceName = in.readString();
         mSessionLink = in.readParcelable(null);
         mComponentName = ComponentName.unflattenFromString(in.readString());
+        mExtras = in.readBundle();
     }
 
     @Override
@@ -144,6 +150,7 @@
         dest.writeString(mServiceName);
         dest.writeParcelable(mSessionLink, flags);
         dest.writeString(mComponentName == null ? "" : mComponentName.flattenToString());
+        dest.writeBundle(mExtras);
     }
 
     @Override
@@ -207,6 +214,14 @@
         return mType;
     }
 
+    /**
+     * @return extras of the token
+     */
+    @Nullable
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
     Session2Link getSessionLink() {
         return mSessionLink;
     }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index bd828ee..3fb2365 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -36,6 +36,7 @@
 import android.content.Intent;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
+import android.media.audiopolicy.AudioProductStrategies;
 import android.media.projection.MediaProjection;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
@@ -5221,6 +5222,30 @@
         return AudioSystem.isHapticPlaybackSupported();
     }
 
+    /**
+     * @hide
+     * Introspection API to retrieve audio product strategies.
+     * When implementing {Car|Oem}AudioManager, use this method  to retrieve the collection of
+     * audio product strategies, which is indexed by a weakly typed index in order to be extended
+     * by OEM without any needs of AOSP patches.
+     * The {Car|Oem}AudioManager can expose API to build {@link AudioAttributes} for a given product
+     * strategy refered either by its index or human readable string. It will allow clients
+     * application to start streaming data using these {@link AudioAttributes} on the selected
+     * device by Audio Policy Engine.
+     * @return a (possibly zero-length) array of
+     *         {@see android.media.audiopolicy.AudioProductStrategy} objects.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public @NonNull AudioProductStrategies getAudioProductStrategies() {
+        final IAudioService service = getService();
+        try {
+            return service.getAudioProductStrategies();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
 
     //---------------------------------------------------------
     // Inner classes
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 571e67e..abdc3c9 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -33,6 +33,7 @@
 import android.media.PlayerBase;
 import android.media.VolumePolicy;
 import android.media.audiopolicy.AudioPolicyConfig;
+import android.media.audiopolicy.AudioProductStrategies;
 import android.media.audiopolicy.IAudioPolicyCallback;
 import android.media.projection.IMediaProjection;
 
@@ -82,6 +83,8 @@
 
     int getLastAudibleStreamVolume(int streamType);
 
+    AudioProductStrategies getAudioProductStrategies();
+
     void setMicrophoneMute(boolean on, String callingPackage, int userId);
 
     void setRingerModeExternal(int ringerMode, String caller);
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.java b/media/java/android/media/audiopolicy/AudioProductStrategies.java
index b836409..6a2375f 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategies.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategies.java
@@ -144,8 +144,10 @@
      * @hide
      * @param aa the {@link AudioAttributes} for which stream type is requested
      * @return the legacy stream type relevant for the given {@link AudioAttributes}.
-     *         If the product strategy is not associated to any stream, it returns STREAM_MUSIC.
-     *         If no product strategy supports the stream type, it returns STREAM_MUSIC.
+     *         If the product strategy is not associated to any stream, it returns
+     *         {@link AudioSystem#STREAM_MUSIC}.
+     *         If no product strategy supports the stream type, it returns
+     *         {@link AudioSystem#STREAM_MUSIC}.
      */
     @SystemApi
     public int getLegacyStreamTypeForAudioAttributes(@NonNull AudioAttributes aa) {
@@ -165,6 +167,19 @@
         return AudioSystem.STREAM_MUSIC;
     }
 
+    /**
+     * @hide
+     * @param aa the {@link AudioAttributes} to be considered
+     * @return {@link AudioProductStrategy} supporting the given {@link AudioAttributes}.
+     *         null is returned if no match with given attributes.
+     */
+    @SystemApi
+    @Nullable
+    public AudioProductStrategy getProductStrategyForAudioAttributes(@NonNull AudioAttributes aa) {
+        Preconditions.checkNotNull(aa, "attributes must not be null");
+        return getById(native_get_product_strategies_from_audio_attributes(aa));
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -198,4 +213,7 @@
 
     private static native int native_list_audio_product_strategies(
             ArrayList<AudioProductStrategy> strategies);
+
+    private static native int native_get_product_strategies_from_audio_attributes(
+            AudioAttributes attributes);
 }
diff --git a/native/android/choreographer.cpp b/native/android/choreographer.cpp
index 2db575b..3fecd53 100644
--- a/native/android/choreographer.cpp
+++ b/native/android/choreographer.cpp
@@ -70,6 +70,8 @@
 
     void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override;
     void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
+    void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
+                               int32_t configId) override;
 
     void scheduleCallbacks();
 
@@ -164,6 +166,13 @@
             this, displayId, toString(connected));
 }
 
+void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId displayId,
+                                          int32_t configId) {
+    ALOGV("choreographer %p ~ received config changed event (displayId=%"
+            ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", configId=%s), ignoring.",
+            this, displayId, toString(configId));
+}
+
 void Choreographer::handleMessage(const Message& message) {
     switch (message.what) {
     case MSG_SCHEDULE_CALLBACKS:
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index caa928f..730e9e1 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -29,7 +29,7 @@
 
     resource_dirs: ["res"],
 
-    srcs: ["src/**/*.java"],
+    srcs: ["src/**/*.java", "src/**/*.kt"],
 
     min_sdk_version: "21",
 
diff --git a/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml
index b053317..4bc68b3 100644
--- a/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml
+++ b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml
@@ -25,8 +25,7 @@
     <View
         android:id="@+id/bar_view"
         android:layout_width="8dp"
-        android:layout_height="wrap_content"
-        android:background="?android:attr/colorAccent"/>
+        android:layout_height="wrap_content"/>
 
     <ImageView
         android:id="@+id/icon_view"
diff --git a/packages/SettingsLib/BarChartPreference/res/values/styles.xml b/packages/SettingsLib/BarChartPreference/res/values/styles.xml
index 647d080..4876cb6 100644
--- a/packages/SettingsLib/BarChartPreference/res/values/styles.xml
+++ b/packages/SettingsLib/BarChartPreference/res/values/styles.xml
@@ -18,7 +18,7 @@
 <resources>
     <style name="BarViewStyle">
         <item name="android:layout_width">0dp</item>
-        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_height">226dp</item>
         <item name="android:layout_weight">1</item>
         <item name="android:layout_marginStart">8dp</item>
         <item name="android:layout_marginEnd">8dp</item>
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
index 3b87fca..1003c97 100644
--- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
@@ -160,8 +160,11 @@
 
         // If the state is loading, we just show a blank view.
         if (mIsLoading) {
+            holder.itemView.setVisibility(View.INVISIBLE);
             return;
         }
+        holder.itemView.setVisibility(View.VISIBLE);
+
         // We must show title of bar chart.
         bindChartTitleView(holder);
 
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java
index 6bf61ae..3ef0235 100644
--- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java
@@ -89,7 +89,7 @@
     private void init() {
         LayoutInflater.from(getContext()).inflate(R.layout.settings_bar_view, this);
         setOrientation(LinearLayout.VERTICAL);
-        setGravity(Gravity.CENTER);
+        setGravity(Gravity.CENTER | Gravity.BOTTOM);
 
         mBarView = findViewById(R.id.bar_view);
         mIcon = findViewById(R.id.icon_view);
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
new file mode 100644
index 0000000..337106b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settingslib.graph
+
+import android.content.Context
+import android.graphics.BlendMode
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.ColorFilter
+import android.graphics.Matrix
+import android.graphics.Paint
+import android.graphics.Path
+import android.graphics.PixelFormat
+import android.graphics.Rect
+import android.graphics.RectF
+import android.graphics.drawable.Drawable
+import android.util.PathParser
+import android.util.TypedValue
+
+import com.android.settingslib.R
+import com.android.settingslib.Utils
+
+/**
+ * A battery meter drawable that respects paths configured in
+ * frameworks/base/core/res/res/values/config.xml to allow for an easily overrideable battery icon
+ */
+open class ThemedBatteryDrawable(private val context: Context, frameColor: Int) : Drawable() {
+
+    // Need to load:
+    // 1. perimeter shape
+    // 2. fill mask (if smaller than perimeter, this would create a fill that
+    //    doesn't touch the walls
+    private val perimeterPath = Path()
+    private val scaledPerimeter = Path()
+    // Fill will cover the whole bounding rect of the fillMask, and be masked by the path
+    private val fillMask = Path()
+    private val scaledFill = Path()
+    // Based off of the mask, the fill will interpolate across this space
+    private val fillRect = RectF()
+    // Top of this rect changes based on level, 100% == fillRect
+    private val levelRect = RectF()
+    private val levelPath = Path()
+    // Updates the transform of the paths when our bounds change
+    private val scaleMatrix = Matrix()
+    private val padding = Rect()
+    // The net result of fill + perimeter paths
+    private val unifiedPath = Path()
+
+    // Bolt path (used while charging)
+    private val boltPath = Path()
+    private val scaledBolt = Path()
+
+    // Plus sign (used for power save mode)
+    private val plusPath = Path()
+    private val scaledPlus = Path()
+
+    private var intrinsicHeight: Int
+    private var intrinsicWidth: Int
+
+    // To implement hysteresis, keep track of the need to invert the interior icon of the battery
+    private var invertFillIcon = false
+
+    // Colors can be configured based on battery level (see res/values/arrays.xml)
+    private var colorLevels: IntArray
+
+    private var fillColor: Int = Color.MAGENTA
+    private var backgroundColor: Int = Color.MAGENTA
+    // updated whenever level changes
+    private var levelColor: Int = Color.MAGENTA
+
+    // Dual tone implies that battery level is a clipped overlay over top of the whole shape
+    private var dualTone = false
+
+    private val invalidateRunnable: () -> Unit = {
+        invalidateSelf()
+    }
+
+    open var criticalLevel: Int = 0
+
+    var charging = false
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
+    var powerSaveEnabled = false
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
+    private val fillColorStrokePaint: Paint by lazy {
+        val p = Paint(Paint.ANTI_ALIAS_FLAG)
+        p.color = frameColor
+        p.isDither = true
+        p.strokeWidth = 5f
+        p.style = Paint.Style.STROKE
+        p.blendMode = BlendMode.SRC
+        p.strokeMiter = 5f
+        p
+    }
+
+    private val fillColorStrokeProtection: Paint by lazy {
+        val p = Paint(Paint.ANTI_ALIAS_FLAG)
+        p.isDither = true
+        p.strokeWidth = 5f
+        p.style = Paint.Style.STROKE
+        p.blendMode = BlendMode.CLEAR
+        p.strokeMiter = 5f
+        p
+    }
+
+    private val fillPaint: Paint by lazy {
+        val p = Paint(Paint.ANTI_ALIAS_FLAG)
+        p.color = frameColor
+        p.alpha = 255
+        p.isDither = true
+        p.strokeWidth = 0f
+        p.style = Paint.Style.FILL_AND_STROKE
+        p
+    }
+
+    // Only used if dualTone is set to true
+    private val dualToneBackgroundFill: Paint by lazy {
+        val p = Paint(Paint.ANTI_ALIAS_FLAG)
+        p.color = frameColor
+        p.alpha = 255
+        p.isDither = true
+        p.strokeWidth = 0f
+        p.style = Paint.Style.FILL_AND_STROKE
+        p
+    }
+
+    init {
+        val density = context.resources.displayMetrics.density
+        intrinsicHeight = (Companion.HEIGHT * density).toInt()
+        intrinsicWidth = (Companion.WIDTH * density).toInt()
+
+        val res = context.resources
+        val levels = res.obtainTypedArray(R.array.batterymeter_color_levels)
+        val colors = res.obtainTypedArray(R.array.batterymeter_color_values)
+        val N = levels.length()
+        colorLevels = IntArray(2 * N)
+        for (i in 0 until N) {
+            colorLevels[2 * i] = levels.getInt(i, 0)
+            if (colors.getType(i) == TypedValue.TYPE_ATTRIBUTE) {
+                colorLevels[2 * i + 1] = Utils.getColorAttrDefaultColor(context,
+                        colors.getThemeAttributeId(i, 0))
+            } else {
+                colorLevels[2 * i + 1] = colors.getColor(i, 0)
+            }
+        }
+        levels.recycle()
+        colors.recycle()
+
+        criticalLevel = context.resources.getInteger(
+                com.android.internal.R.integer.config_criticalBatteryWarningLevel)
+
+        loadPaths()
+    }
+
+    override fun draw(c: Canvas) {
+        unifiedPath.reset()
+        levelPath.reset()
+        levelRect.set(fillRect)
+        val fillFraction = level / 100f
+        val fillTop =
+                if (level >= 95)
+                    fillRect.top
+                else
+                    fillRect.top + (fillRect.height() * (1 - fillFraction))
+
+        levelRect.top = Math.floor(fillTop.toDouble()).toFloat()
+        levelPath.addRect(levelRect, Path.Direction.CCW)
+
+        // The perimeter should never change
+        unifiedPath.addPath(scaledPerimeter)
+        // IF drawing dual tone, the level is used only to clip the whole drawable path
+        if (!dualTone) {
+            unifiedPath.op(levelPath, Path.Op.UNION)
+        }
+
+        fillPaint.color = levelColor
+
+        // Deal with unifiedPath clipping before it draws
+        if (charging) {
+            // Clip out the bolt shape
+            unifiedPath.op(scaledBolt, Path.Op.DIFFERENCE)
+            if (!invertFillIcon) {
+                c.drawPath(scaledBolt, fillPaint)
+            }
+        } else if (powerSaveEnabled) {
+            // Clip out the plus shape
+            unifiedPath.op(scaledPlus, Path.Op.DIFFERENCE)
+            if (!invertFillIcon) {
+                c.drawPath(scaledPlus, fillPaint)
+            }
+        }
+
+        if (dualTone) {
+            // Dual tone means we draw the shape again, clipped to the charge level
+            c.drawPath(unifiedPath, dualToneBackgroundFill)
+            c.save()
+            c.clipRect(0f,
+                    bounds.bottom - bounds.height() * fillFraction,
+                    bounds.right.toFloat(),
+                    bounds.bottom.toFloat())
+            c.drawPath(unifiedPath, fillPaint)
+            c.restore()
+        } else {
+            // Non dual-tone means we draw the perimeter (with the level fill), and potentially
+            // draw the fill again with a critical color
+            fillPaint.color = fillColor
+            c.drawPath(unifiedPath, fillPaint)
+            fillPaint.color = levelColor
+
+            // Show colorError below this level
+            if (level <= Companion.CRITICAL_LEVEL && !charging) {
+                c.save()
+                c.clipPath(scaledFill)
+                c.drawPath(levelPath, fillPaint)
+                c.restore()
+            }
+        }
+
+        if (charging) {
+            c.clipOutPath(scaledBolt)
+            if (invertFillIcon) {
+                c.drawPath(scaledBolt, fillColorStrokePaint)
+            } else {
+                c.drawPath(scaledBolt, fillColorStrokeProtection)
+            }
+        } else if (powerSaveEnabled) {
+            c.clipOutPath(scaledPlus)
+            if (invertFillIcon) {
+                c.drawPath(scaledPlus, fillColorStrokePaint)
+            } else {
+                c.drawPath(scaledPlus, fillColorStrokeProtection)
+            }
+        }
+    }
+
+    private fun batteryColorForLevel(level: Int): Int {
+        return when {
+            charging || powerSaveEnabled -> fillPaint.color
+            else -> getColorForLevel(level)
+        }
+    }
+
+    private fun getColorForLevel(level: Int): Int {
+        var thresh: Int
+        var color = 0
+        var i = 0
+        while (i < colorLevels.size) {
+            thresh = colorLevels[i]
+            color = colorLevels[i + 1]
+            if (level <= thresh) {
+
+                // Respect tinting for "normal" level
+                return if (i == colorLevels.size - 2) {
+                    fillColor
+                } else {
+                    color
+                }
+            }
+            i += 2
+        }
+        return color
+    }
+
+    /**
+     * Alpha is unused internally, and should be defined in the colors passed to {@link setColors}.
+     * Further, setting an alpha for a dual tone battery meter doesn't make sense without bounds
+     * defining the minimum background fill alpha. This is because fill + background must be equal
+     * to the net alpha passed in here.
+     */
+    override fun setAlpha(alpha: Int) {
+    }
+
+    override fun setColorFilter(colorFilter: ColorFilter?) {
+        fillPaint.colorFilter = colorFilter
+        fillColorStrokePaint.colorFilter = colorFilter
+        dualToneBackgroundFill.colorFilter = colorFilter
+    }
+
+    /**
+     * Deprecated, but required by Drawable
+     */
+    override fun getOpacity(): Int {
+        return PixelFormat.OPAQUE
+    }
+
+    override fun getIntrinsicHeight(): Int {
+        return intrinsicHeight
+    }
+
+    override fun getIntrinsicWidth(): Int {
+        return intrinsicWidth
+    }
+
+    /**
+     * Set the fill level
+     */
+    public open fun setBatteryLevel(l: Int) {
+        invertFillIcon = if (l >= 67) true else if (l <= 33) false else invertFillIcon
+        level = l
+        levelColor = batteryColorForLevel(level)
+        invalidateSelf()
+    }
+
+    public fun getBatteryLevel(): Int {
+        return level
+    }
+
+    override fun onBoundsChange(bounds: Rect?) {
+        super.onBoundsChange(bounds)
+        updateSize()
+    }
+
+    fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
+        padding.left = left
+        padding.top = top
+        padding.right = right
+        padding.bottom = bottom
+
+        updateSize()
+    }
+
+    fun setColors(fgColor: Int, bgColor: Int, singleToneColor: Int) {
+        fillColor = if (dualTone) fgColor else singleToneColor
+
+        fillPaint.color = fillColor
+        fillColorStrokePaint.color = fillColor
+
+        backgroundColor = bgColor
+        dualToneBackgroundFill.color = bgColor
+
+        invalidateSelf()
+    }
+
+    private fun postInvalidate() {
+        unscheduleSelf(invalidateRunnable)
+        scheduleSelf(invalidateRunnable, 0)
+    }
+
+    private fun updateSize() {
+        val b = bounds
+        if (b.isEmpty) {
+            scaleMatrix.setScale(1f, 1f)
+        } else {
+            scaleMatrix.setScale((b.right / Companion.WIDTH), (b.bottom / Companion.HEIGHT))
+        }
+
+        perimeterPath.transform(scaleMatrix, scaledPerimeter)
+        fillMask.transform(scaleMatrix, scaledFill)
+        scaledFill.computeBounds(fillRect, true)
+        boltPath.transform(scaleMatrix, scaledBolt)
+        plusPath.transform(scaleMatrix, scaledPlus)
+    }
+
+    private fun loadPaths() {
+        val pathString = context.resources.getString(
+                com.android.internal.R.string.config_batterymeterPerimeterPath)
+        perimeterPath.set(PathParser.createPathFromPathData(pathString))
+        val b = RectF()
+        perimeterPath.computeBounds(b, true)
+
+        val fillMaskString = context.resources.getString(
+                com.android.internal.R.string.config_batterymeterFillMask)
+        fillMask.set(PathParser.createPathFromPathData(fillMaskString))
+        // Set the fill rect so we can calculate the fill properly
+        fillMask.computeBounds(fillRect, true)
+
+        val boltPathString = context.resources.getString(
+                com.android.internal.R.string.config_batterymeterBoltPath)
+        boltPath.set(PathParser.createPathFromPathData(boltPathString))
+
+        val plusPathString = context.resources.getString(
+                com.android.internal.R.string.config_batterymeterPowersavePath)
+        plusPath.set(PathParser.createPathFromPathData(plusPathString))
+
+        dualTone = context.resources.getBoolean(
+                com.android.internal.R.bool.config_batterymeterDualTone)
+    }
+
+    companion object {
+        private const val TAG = "ThemedBatteryDrawable"
+        private const val WIDTH = 12f
+        private const val HEIGHT = 20f
+        private const val CRITICAL_LEVEL = 15
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
index 2a12810..a31b71e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
@@ -59,6 +59,5 @@
         setIcon(R.drawable.ic_info_outline_24);
         setKey(KEY_FOOTER);
         setOrder(ORDER_FOOTER);
-        setSelectable(false);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
index 1080cf4..3acca2a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
@@ -305,7 +305,7 @@
     }
 
     @Test
-    public void onBindViewHolder_loadingStateIsTrue_shouldNotInitAnyView() {
+    public void onBindViewHolder_loadingStateIsTrue_shouldHideAllViews() {
         final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app);
         viewInfo.setClickListener(v -> {
         });
@@ -317,8 +317,7 @@
 
         mPreference.onBindViewHolder(mHolder);
 
-        assertThat(TextUtils.isEmpty(mTitleView.getText())).isTrue();
-        assertThat(TextUtils.isEmpty(mDetailsView.getText())).isTrue();
+        assertThat(mHolder.itemView.getVisibility()).isEqualTo(View.INVISIBLE);
     }
 
     @Test
@@ -334,6 +333,7 @@
 
         mPreference.onBindViewHolder(mHolder);
 
+        assertThat(mHolder.itemView.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(TextUtils.isEmpty(mTitleView.getText())).isFalse();
         assertThat(TextUtils.isEmpty(mDetailsView.getText())).isFalse();
     }
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml b/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
index bc15f2c4..665fc3f 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
@@ -54,9 +54,6 @@
                 android:orientation="vertical"
                 android:gravity="start"
             />
-
-            <include android:id="@+id/overflow" layout="@layout/ongoing_privacy_dialog_item"
-                     android:visibility="gone" />
         </LinearLayout>
 
     </LinearLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 536bc4e..50cf37b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -44,8 +44,9 @@
     <!-- Height of the battery icon in the status bar. -->
     <dimen name="status_bar_battery_icon_height">13.0dp</dimen>
 
-    <!-- Width of the battery icon in the status bar. -->
-    <dimen name="status_bar_battery_icon_width">8.5dp</dimen>
+    <!-- Width of the battery icon in the status bar. The battery drawable assumes a 12x20 canvas,
+    so the width of the icon should be 13.0dp * (12.0 / 20.0) -->
+    <dimen name="status_bar_battery_icon_width">7.8dp</dimen>
 
     <!-- The font size for the clock in the status bar. -->
     <dimen name="status_bar_clock_size">14sp</dimen>
@@ -1049,4 +1050,7 @@
     <dimen name="bubble_pointer_margin">8dp</dimen>
     <!-- Height of the permission prompt shown with bubbles -->
     <dimen name="bubble_permission_height">120dp</dimen>
+
+    <!-- Size of the RAT type for CellularTile -->
+    <dimen name="celltile_rat_type_size">10sp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 1e411cf..30dbc8b 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -216,6 +216,12 @@
         <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
     </style>
 
+    <!-- This is hard coded to be sans-serif-condensed to match the icons -->
+    <style name="TextAppearance.RATBadge" parent="@style/TextAppearance.QS.TileLabel.Secondary">
+        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:textSize">@dimen/celltile_rat_type_size</item>
+    </style>
+
     <style name="TextAppearance.QS.CarrierInfo">
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
         <item name="android:textSize">@dimen/qs_carrier_info_text_size</item>
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/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 2006794..592b603 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -46,7 +46,7 @@
 import android.widget.TextView;
 
 import com.android.settingslib.Utils;
-import com.android.settingslib.graph.BatteryMeterDrawableBase;
+import com.android.settingslib.graph.ThemedBatteryDrawable;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.settings.CurrentUserTracker;
@@ -76,7 +76,7 @@
     public static final int MODE_OFF = 2;
     public static final int MODE_ESTIMATE = 3;
 
-    private final BatteryMeterDrawableBase mDrawable;
+    private final ThemedBatteryDrawable mDrawable;
     private final String mSlotBattery;
     private final ImageView mBatteryIconView;
     private final CurrentUserTracker mUserTracker;
@@ -94,9 +94,11 @@
     private boolean mIsSubscribedForTunerUpdates;
     private boolean mCharging;
 
+    private int mDarkModeSingleToneColor;
     private int mDarkModeBackgroundColor;
     private int mDarkModeFillColor;
 
+    private int mLightModeSingleToneColor;
     private int mLightModeBackgroundColor;
     private int mLightModeFillColor;
     private int mUser;
@@ -106,6 +108,7 @@
      */
     private boolean mUseWallpaperTextColors;
 
+    private int mNonAdaptedSingleToneColor;
     private int mNonAdaptedForegroundColor;
     private int mNonAdaptedBackgroundColor;
 
@@ -127,7 +130,7 @@
                 defStyle, 0);
         final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
                 context.getColor(R.color.meter_background_color));
-        mDrawable = new BatteryMeterDrawableBase(context, frameColor);
+        mDrawable = new ThemedBatteryDrawable(context, frameColor);
         atts.recycle();
 
         mSettingObserver = new SettingObserver(new Handler(context.getMainLooper()));
@@ -169,6 +172,10 @@
         setClipChildren(false);
         setClipToPadding(false);
         Dependency.get(ConfigurationController.class).observe(viewAttachLifecycle(this), this);
+
+        // Needed for PorderDuff.Mode.CLEAR operations to work properly, but redraws don't happen
+        // enough to justify a hardware layer.
+        setLayerType(LAYER_TYPE_SOFTWARE, null);
     }
 
     public void setForceShowPercent(boolean show) {
@@ -243,9 +250,11 @@
         if (mUseWallpaperTextColors) {
             updateColors(
                     Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor),
-                    Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColorSecondary));
+                    Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColorSecondary),
+                    Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor));
         } else {
-            updateColors(mNonAdaptedForegroundColor, mNonAdaptedBackgroundColor);
+            updateColors(mNonAdaptedForegroundColor, mNonAdaptedBackgroundColor,
+                    mNonAdaptedSingleToneColor);
         }
     }
 
@@ -258,10 +267,14 @@
                 Utils.getThemeAttr(context, R.attr.darkIconTheme));
         Context dualToneLightTheme = new ContextThemeWrapper(context,
                 Utils.getThemeAttr(context, R.attr.lightIconTheme));
+        mDarkModeSingleToneColor = Utils.getColorAttrDefaultColor(dualToneDarkTheme,
+                R.attr.singleToneColor);
         mDarkModeBackgroundColor = Utils.getColorAttrDefaultColor(dualToneDarkTheme,
                 R.attr.backgroundColor);
         mDarkModeFillColor = Utils.getColorAttrDefaultColor(dualToneDarkTheme,
                 R.attr.fillColor);
+        mLightModeSingleToneColor = Utils.getColorAttrDefaultColor(dualToneLightTheme,
+                R.attr.singleToneColor);
         mLightModeBackgroundColor = Utils.getColorAttrDefaultColor(dualToneLightTheme,
                 R.attr.backgroundColor);
         mLightModeFillColor = Utils.getColorAttrDefaultColor(dualToneLightTheme, R.attr.fillColor);
@@ -303,8 +316,8 @@
 
     @Override
     public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-        mDrawable.setBatteryLevel(level);
         mDrawable.setCharging(pluggedIn);
+        mDrawable.setBatteryLevel(level);
         mCharging = pluggedIn;
         mLevel = level;
         updatePercentText();
@@ -315,7 +328,7 @@
 
     @Override
     public void onPowerSaveChanged(boolean isPowerSave) {
-        mDrawable.setPowerSave(isPowerSave);
+        mDrawable.setPowerSaveEnabled(isPowerSave);
     }
 
     private TextView loadPercentView() {
@@ -406,21 +419,24 @@
     @Override
     public void onDarkChanged(Rect area, float darkIntensity, int tint) {
         float intensity = DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0;
+        mNonAdaptedSingleToneColor = getColorForDarkIntensity(
+                intensity, mLightModeSingleToneColor, mDarkModeSingleToneColor);
         mNonAdaptedForegroundColor = getColorForDarkIntensity(
                 intensity, mLightModeFillColor, mDarkModeFillColor);
         mNonAdaptedBackgroundColor = getColorForDarkIntensity(
                 intensity, mLightModeBackgroundColor,mDarkModeBackgroundColor);
 
         if (!mUseWallpaperTextColors) {
-            updateColors(mNonAdaptedForegroundColor, mNonAdaptedBackgroundColor);
+            updateColors(mNonAdaptedForegroundColor, mNonAdaptedBackgroundColor,
+                    mNonAdaptedSingleToneColor);
         }
     }
 
-    private void updateColors(int foregroundColor, int backgroundColor) {
-        mDrawable.setColors(foregroundColor, backgroundColor);
-        mTextColor = foregroundColor;
+    private void updateColors(int foregroundColor, int backgroundColor, int singleToneColor) {
+        mDrawable.setColors(foregroundColor, backgroundColor, singleToneColor);
+        mTextColor = singleToneColor;
         if (mBatteryPercentView != null) {
-            mBatteryPercentView.setTextColor(foregroundColor);
+            mBatteryPercentView.setTextColor(singleToneColor);
         }
     }
 
@@ -429,7 +445,7 @@
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        String powerSave = mDrawable == null ? null : mDrawable.getPowerSave() + "";
+        String powerSave = mDrawable == null ? null : mDrawable.getPowerSaveEnabled() + "";
         CharSequence percent = mBatteryPercentView == null ? null : mBatteryPercentView.getText();
         pw.println("  BatteryMeterView:");
         pw.println("    mDrawable.getPowerSave: " + powerSave);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index 5353ee6..06dbdbf 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -17,11 +17,11 @@
 package com.android.systemui.doze;
 
 import android.content.Context;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.util.Log;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.doze.DozeMachine.State;
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 3250182..36e28dc 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -21,9 +21,9 @@
 import android.content.Context;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Handler;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 4d89a39..6c4be06 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -17,12 +17,12 @@
 package com.android.systemui.doze;
 
 import android.annotation.MainThread;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.util.Log;
 import android.view.Display;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.util.Preconditions;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.Assert;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index d1e127d..c5799cc 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -30,6 +30,7 @@
 import android.hardware.SensorManager;
 import android.hardware.TriggerEvent;
 import android.hardware.TriggerEventListener;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.SystemClock;
@@ -40,7 +41,6 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.plugins.SensorManagerPlugin;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index b6e830c..3654aac 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -27,6 +27,7 @@
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -34,7 +35,6 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.util.Preconditions;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
index 75b8a05..84a3446 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
@@ -42,14 +42,10 @@
 
     private val iconSize = context.resources.getDimensionPixelSize(
             R.dimen.ongoing_appops_dialog_icon_size)
-    private val plusSize = context.resources.getDimensionPixelSize(
-            R.dimen.ongoing_appops_dialog_app_plus_size)
     private val iconColor = context.resources.getColor(
             com.android.internal.R.color.text_color_primary, context.theme)
-    private val plusColor: Int
     private val iconMargin = context.resources.getDimensionPixelSize(
             R.dimen.ongoing_appops_dialog_icon_margin)
-    private val MAX_ITEMS = context.resources.getInteger(R.integer.ongoing_appops_dialog_max_apps)
     private val iconFactory = IconDrawableFactory.newInstance(context, true)
     private var dismissDialog: (() -> Unit)? = null
     private val appsAndTypes = dialogBuilder.appsAndTypes
@@ -57,13 +53,6 @@
             { it.second.min() },
             { it.first }))
 
-    init {
-        val a = context.theme.obtainStyledAttributes(
-                intArrayOf(com.android.internal.R.attr.colorAccent))
-        plusColor = a.getColor(0, 0)
-        a.recycle()
-    }
-
     fun createDialog(): Dialog {
         val builder = AlertDialog.Builder(context).apply {
             setPositiveButton(R.string.ongoing_privacy_dialog_ok, null)
@@ -96,33 +85,9 @@
 
         val numItems = appsAndTypes.size
         for (i in 0..(numItems - 1)) {
-            if (i >= MAX_ITEMS) break
             val item = appsAndTypes[i]
             addAppItem(appsList, item.first, item.second, dialogBuilder.types.size > 1)
         }
-
-        if (numItems > MAX_ITEMS) {
-            val overflow = contentView.findViewById(R.id.overflow) as LinearLayout
-            overflow.visibility = View.VISIBLE
-            val overflowText = overflow.findViewById(R.id.app_name) as TextView
-            overflowText.text = context.resources.getQuantityString(
-                    R.plurals.ongoing_privacy_dialog_overflow_text,
-                    numItems - MAX_ITEMS,
-                    numItems - MAX_ITEMS
-            )
-            val overflowPlus = overflow.findViewById(R.id.app_icon) as ImageView
-            val lp = overflowPlus.layoutParams.apply {
-                height = plusSize
-                width = plusSize
-            }
-            overflowPlus.layoutParams = lp
-            overflowPlus.apply {
-                val plus = context.getDrawable(R.drawable.plus)
-                imageTintList = ColorStateList.valueOf(plusColor)
-                setImageDrawable(plus)
-            }
-        }
-
         return contentView
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
index a6e48f8..3f581c4d 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
@@ -18,6 +18,8 @@
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
 import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import android.util.IconDrawableFactory
 import com.android.systemui.R
 
 typealias Privacy = PrivacyType
@@ -46,14 +48,21 @@
 
     private val applicationInfo: ApplicationInfo? by lazy {
         try {
-            context.packageManager.getApplicationInfo(packageName, 0)
+            val userHandle = UserHandle.getUserHandleForUid(uid)
+            context.createPackageContextAsUser(packageName, 0, userHandle).getPackageManager()
+                    .getApplicationInfo(packageName, 0)
         } catch (_: PackageManager.NameNotFoundException) {
             null
         }
     }
     val icon: Drawable by lazy {
         applicationInfo?.let {
-            context.packageManager.getApplicationIcon(it)
+            try {
+                val iconFactory = IconDrawableFactory.newInstance(context, true)
+                iconFactory.getBadgedIcon(it, UserHandle.getUserId(uid))
+            } catch (_: Exception) {
+                null
+            }
         } ?: context.getDrawable(android.R.drawable.sym_def_app_icon)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 7f76900..c664a20 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -15,14 +15,11 @@
  */
 package com.android.systemui.qs.tiles;
 
-import android.content.Context;
 import android.content.Intent;
-import android.graphics.drawable.Drawable;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.graph.BatteryMeterDrawableBase;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.QSHost;
@@ -41,6 +38,8 @@
     private boolean mCharging;
     private boolean mPluggedIn;
 
+    private Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_battery_saver);
+
     @Inject
     public BatterySaverTile(QSHost host, BatteryController batteryController) {
         super(host);
@@ -84,9 +83,7 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         state.state = mPluggedIn ? Tile.STATE_UNAVAILABLE
                 : mPowerSave ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
-        BatterySaverIcon bsi = new BatterySaverIcon();
-        bsi.mState = state.state;
-        state.icon = bsi;
+        state.icon = mIcon;
         state.label = mContext.getString(R.string.battery_detail_switch_title);
         state.contentDescription = state.label;
         state.value = mPowerSave;
@@ -106,48 +103,4 @@
         mPowerSave = isPowerSave;
         refreshState(null);
     }
-
-    public static class BatterySaverIcon extends Icon {
-        private int mState;
-
-        @Override
-        public Drawable getDrawable(Context context) {
-            BatterySaverDrawable b =
-                    new BatterySaverDrawable(context, QSTileImpl.getColorForState(context, mState));
-            b.mState = mState;
-            final int pad = context.getResources()
-                    .getDimensionPixelSize(R.dimen.qs_tile_divider_height);
-            b.setPadding(pad, pad, pad, pad);
-            return b;
-        }
-    }
-
-    private static class BatterySaverDrawable extends BatteryMeterDrawableBase {
-        private int mState;
-        private static final int MAX_BATTERY = 100;
-
-        BatterySaverDrawable(Context context, int frameColor) {
-            super(context, frameColor);
-            // Show as full so it's always uniform color
-            super.setBatteryLevel(MAX_BATTERY);
-            setPowerSave(true);
-            setCharging(false);
-            setPowerSaveAsColorError(false);
-            mPowerSaveAsColorError = true;
-            mFramePaint.setColor(0);
-            mPowersavePaint.setColor(frameColor);
-            mFramePaint.setStrokeWidth(mPowersavePaint.getStrokeWidth());
-            mPlusPaint.setColor(frameColor);
-        }
-
-        @Override
-        protected int batteryColorForLevel(int level) {
-            return 0;
-        }
-
-        @Override
-        public void setBatteryLevel(int val) {
-            // Don't change the actual level, otherwise this won't draw correctly
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index e1becdb..c587a39 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -25,7 +25,11 @@
 import android.content.res.Resources;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.style.TextAppearanceSpan;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -188,7 +192,8 @@
             state.secondaryLabel = r.getString(R.string.status_bar_airplane);
         } else if (mobileDataEnabled) {
             state.state = Tile.STATE_ACTIVE;
-            state.secondaryLabel = getMobileDataSubscriptionName(cb);
+            state.secondaryLabel = appendMobileDataType(getMobileDataSubscriptionName(cb),
+                    cb.dataContentDescription);
         } else {
             state.state = Tile.STATE_INACTIVE;
             state.secondaryLabel = r.getString(R.string.cell_data_off);
@@ -207,6 +212,18 @@
         state.contentDescription = state.label + ", " + contentDescriptionSuffix;
     }
 
+    private CharSequence appendMobileDataType(CharSequence current, CharSequence dataType) {
+        if (TextUtils.isEmpty(dataType)) {
+            return current;
+        }
+        SpannableString type = new SpannableString(dataType);
+        SpannableStringBuilder builder = new SpannableStringBuilder(current);
+        builder.append(" ");
+        builder.append(type, new TextAppearanceSpan(mContext, R.style.TextAppearance_RATBadge),
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return builder;
+    }
+
     private CharSequence getMobileDataSubscriptionName(CallbackInfo cb) {
         if (cb.roaming && !TextUtils.isEmpty(cb.dataSubscriptionName)) {
             String roaming = mContext.getString(R.string.data_connection_roaming);
@@ -232,6 +249,7 @@
     private static final class CallbackInfo {
         boolean airplaneModeEnabled;
         CharSequence dataSubscriptionName;
+        CharSequence dataContentDescription;
         boolean activityIn;
         boolean activityOut;
         boolean noSim;
@@ -250,6 +268,7 @@
                 return;
             }
             mInfo.dataSubscriptionName = mController.getMobileDataNetworkName();
+            mInfo.dataContentDescription = (description != null) ? typeContentDescription : null;
             mInfo.activityIn = activityIn;
             mInfo.activityOut = activityOut;
             mInfo.roaming = roaming;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index c9be2c8..007c50c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -25,6 +25,8 @@
 import com.android.systemui.qs.AutoAddTracker;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastController.CastDevice;
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.DataSaverController.Listener;
 import com.android.systemui.statusbar.policy.HotspotController;
@@ -42,6 +44,7 @@
     public static final String INVERSION = "inversion";
     public static final String WORK = "work";
     public static final String NIGHT = "night";
+    public static final String CAST = "cast";
 
     private final Context mContext;
     private final QSTileHost mHost;
@@ -51,6 +54,7 @@
     private final DataSaverController mDataSaverController;
     private final ManagedProfileController mManagedProfileController;
     private final NightDisplayListener mNightDisplayListener;
+    private final CastController mCastController;
 
     @Inject
     public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host,
@@ -58,7 +62,8 @@
             HotspotController hotspotController,
             DataSaverController dataSaverController,
             ManagedProfileController managedProfileController,
-            NightDisplayListener nightDisplayListener) {
+            NightDisplayListener nightDisplayListener,
+            CastController castController) {
         mAutoTracker = autoAddTracker;
         mContext = context;
         mHost = host;
@@ -67,6 +72,7 @@
         mDataSaverController = dataSaverController;
         mManagedProfileController = managedProfileController;
         mNightDisplayListener = nightDisplayListener;
+        mCastController = castController;
         if (!mAutoTracker.isAdded(HOTSPOT)) {
             hotspotController.addCallback(mHotspotCallback);
         }
@@ -95,6 +101,9 @@
                 && ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             nightDisplayListener.setCallback(mNightDisplayCallback);
         }
+        if (!mAutoTracker.isAdded(CAST)) {
+            castController.addCallback(mCastCallback);
+        }
     }
 
     public void destroy() {
@@ -108,6 +117,7 @@
         if (ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             mNightDisplayListener.setCallback(null);
         }
+        mCastController.removeCallback(mCastCallback);
     }
 
     public void unmarkTileAsAutoAdded(String tabSpec) {
@@ -181,4 +191,27 @@
             mHandler.post(() -> mNightDisplayListener.setCallback(null));
         }
     };
+
+    @VisibleForTesting
+    final CastController.Callback mCastCallback = new CastController.Callback() {
+        @Override
+        public void onCastDevicesChanged() {
+            if (mAutoTracker.isAdded(CAST)) return;
+
+            boolean isCasting = false;
+            for (CastDevice device : mCastController.getCastDevices()) {
+                if (device.state == CastDevice.STATE_CONNECTED
+                        || device.state == CastDevice.STATE_CONNECTING) {
+                    isCasting = true;
+                    break;
+                }
+            }
+
+            if (isCasting) {
+                mHost.addTile(CAST);
+                mAutoTracker.setTileAdded(CAST);
+                mHandler.post(() -> mCastController.removeCallback(mCastCallback));
+            }
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 1049773..a17e042 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.PowerManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -26,7 +27,6 @@
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.doze.AlwaysOnDisplayPolicy;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index d3ff63a..50c4fac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -29,6 +29,7 @@
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.media.AudioManager;
 import android.media.session.MediaSessionLegacyHelper;
 import android.net.Uri;
@@ -56,7 +57,6 @@
 import android.widget.FrameLayout;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.view.FloatingActionMode;
 import com.android.internal.widget.FloatingToolbar;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index b22150b..8b81585 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -57,13 +57,17 @@
     private final int mDefaultMinNumSystemGeneratedReplies;
     private final int mDefaultMaxNumActions;
 
-    private boolean mEnabled;
-    private boolean mRequiresTargetingP;
-    private int mMaxSqueezeRemeasureAttempts;
-    private boolean mEditChoicesBeforeSending;
-    private boolean mShowInHeadsUp;
-    private int mMinNumSystemGeneratedReplies;
-    private int mMaxNumActions;
+    // These fields are updated on the UI thread but can be accessed on both the UI thread and
+    // background threads. We use the volatile keyword here instead of synchronization blocks since
+    // we only care about variable updates here being visible to other threads (and not for example
+    // whether the variables we are reading were updated in the same go).
+    private volatile boolean mEnabled;
+    private volatile boolean mRequiresTargetingP;
+    private volatile int mMaxSqueezeRemeasureAttempts;
+    private volatile boolean mEditChoicesBeforeSending;
+    private volatile boolean mShowInHeadsUp;
+    private volatile int mMinNumSystemGeneratedReplies;
+    private volatile int mMaxNumActions;
 
     private final Context mContext;
     private final KeyValueListParser mParser = new KeyValueListParser(',');
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index ecf1784..0070dcf 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -19,6 +19,7 @@
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.content.DialogInterface;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Build;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -29,7 +30,6 @@
 import androidx.preference.Preference;
 import androidx.preference.PreferenceFragment;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
index 45342d4..6807c22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
@@ -18,12 +18,12 @@
 
 import static junit.framework.TestCase.assertEquals;
 
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index e4558df..9438cbb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -16,12 +16,13 @@
 
 package com.android.systemui.doze;
 
+import android.hardware.display.AmbientDisplayConfiguration;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.withSettings;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import org.mockito.Answers;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index 0fc0953..23ff3d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Instrumentation;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Handler;
 import android.os.Looper;
 import android.support.test.InstrumentationRegistry;
@@ -35,7 +36,6 @@
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManagerFake;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 5a6200f..f972508 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -38,11 +38,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.UiThreadTest;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.wakelock.WakeLockFake;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 066dff2..463a6e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -31,12 +31,12 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AlarmManager;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.SensorManagerPlugin;
 import com.android.systemui.statusbar.phone.DozeParameters;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index cdac7c97..ca37347 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -27,6 +27,7 @@
 
 import android.app.AlarmManager;
 import android.app.Instrumentation;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Handler;
 import android.os.Looper;
 import android.support.test.InstrumentationRegistry;
@@ -34,7 +35,6 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManagerFake;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index f3740c4..87699b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -31,6 +32,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.qs.AutoAddTracker;
 import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastController.CastDevice;
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.HotspotController;
 
@@ -40,6 +43,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Collections;
+import java.util.Set;
+
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
@@ -47,6 +53,7 @@
 
     @Mock private QSTileHost mQsTileHost;
     @Mock private AutoAddTracker mAutoAddTracker;
+    @Mock private CastController mCastController;
 
     private AutoTileManager mAutoTileManager;
 
@@ -58,7 +65,8 @@
                 mock(HotspotController.class),
                 mock(DataSaverController.class),
                 mock(ManagedProfileController.class),
-                mock(NightDisplayListener.class));
+                mock(NightDisplayListener.class),
+                mCastController);
     }
 
     @Test
@@ -108,4 +116,24 @@
                 ColorDisplayManager.AUTO_MODE_DISABLED);
         verify(mQsTileHost, never()).addTile("night");
     }
+
+    private static Set<CastDevice> buildFakeCastDevice(boolean isCasting) {
+        CastDevice cd = new CastDevice();
+        cd.state = isCasting ? CastDevice.STATE_CONNECTED : CastDevice.STATE_DISCONNECTED;
+        return Collections.singleton(cd);
+    }
+
+    @Test
+    public void castTileAdded_whenDeviceIsCasting() {
+        doReturn(buildFakeCastDevice(true)).when(mCastController).getCastDevices();
+        mAutoTileManager.mCastCallback.onCastDevicesChanged();
+        verify(mQsTileHost).addTile("cast");
+    }
+
+    @Test
+    public void castTileNotAdded_whenDeviceIsNotCasting() {
+        doReturn(buildFakeCastDevice(false)).when(mCastController).getCastDevices();
+        mAutoTileManager.mCastCallback.onCastDevicesChanged();
+        verify(mQsTileHost, never()).addTile("cast");
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index d025d73..de41152 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -402,7 +402,7 @@
 
     private void updateActivityStartsLoggingEnabled() {
         mFlagActivityStartsLoggingEnabled = Settings.Global.getInt(mResolver,
-                Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, 0) == 1;
+                Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, 1) == 1;
     }
 
     private void updateBackgroundActivityStartsEnabled() {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index ac20f6c..1e406c0 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -2214,7 +2214,11 @@
         void startUserWidgets(int userId) {
             AppWidgetManagerInternal awm = LocalServices.getService(AppWidgetManagerInternal.class);
             if (awm != null) {
-                awm.unlockUser(userId);
+                // Out of band, because this is called during a sequence with
+                // sensitive cross-service lock management
+                FgThread.getHandler().post(() -> {
+                    awm.unlockUser(userId);
+                });
             }
         }
 
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 9e92745..5d802a7 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -88,6 +88,7 @@
 import android.media.audiopolicy.AudioMix;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicyConfig;
+import android.media.audiopolicy.AudioProductStrategies;
 import android.media.audiopolicy.IAudioPolicyCallback;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionManager;
@@ -274,6 +275,9 @@
 
     private SettingsObserver mSettingsObserver;
 
+    /** @see AudioProductStrategies */
+    private static AudioProductStrategies sAudioProductStrategies;
+
     private int mMode = AudioSystem.MODE_NORMAL;
     // protects mRingerMode
     private final Object mSettingsLock = new Object();
@@ -624,6 +628,8 @@
         mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
 
+        sAudioProductStrategies = new AudioProductStrategies();
+
         // Initialize volume
         int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
         if (maxCallVolume != -1) {
@@ -988,6 +994,14 @@
         }
     }
 
+    /**
+     * @return the {@link android.media.audiopolicy.AudioProductStrategies} discovered from the
+     * platform configuration file.
+     */
+    public @NonNull AudioProductStrategies getAudioProductStrategies() {
+        return sAudioProductStrategies;
+    }
+
     private void checkAllAliasStreamVolumes() {
         synchronized (mSettingsLock) {
             synchronized (VolumeStreamState.class) {
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 4891947..77df10b 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -65,7 +65,8 @@
             new LongSparseArray<LocalDisplayDevice>();
 
     @SuppressWarnings("unused")  // Becomes active at instantiation time.
-    private HotplugDisplayEventReceiver mHotplugReceiver;
+    private PhysicalDisplayEventReceiver mPhysicalDisplayEventReceiver;
+
 
     // Called with SyncRoot lock held.
     public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
@@ -77,7 +78,7 @@
     public void registerLocked() {
         super.registerLocked();
 
-        mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
+        mPhysicalDisplayEventReceiver = new PhysicalDisplayEventReceiver(getHandler().getLooper());
 
         for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
             tryConnectDisplayLocked(physicalDisplayId);
@@ -727,8 +728,8 @@
         }
     }
 
-    private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
-        public HotplugDisplayEventReceiver(Looper looper) {
+    private final class PhysicalDisplayEventReceiver extends DisplayEventReceiver {
+        PhysicalDisplayEventReceiver(Looper looper) {
             super(looper, VSYNC_SOURCE_APP);
         }
 
@@ -742,5 +743,15 @@
                 }
             }
         }
+
+        @Override
+        public void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId) {
+            if (DEBUG) {
+                Slog.d(TAG, "onConfigChanged("
+                        + "timestampNanos=" + timestampNanos
+                        + ", builtInDisplayId=" + physicalDisplayId
+                        + ", configId=" + configId + ")");
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index bffa8f4..3052e3c 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -28,6 +28,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ServiceInfo;
 import android.database.ContentObserver;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.hardware.input.InputManagerInternal;
 import android.os.Binder;
 import android.os.Build;
@@ -46,7 +47,6 @@
 import android.util.Slog;
 import android.view.Display;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.util.DumpUtils;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index afe3473..00e1ffa 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -34,13 +34,11 @@
 import com.android.internal.location.ILocationProviderManager;
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
-import com.android.internal.os.TransferPipe;
 import com.android.server.FgThread;
 import com.android.server.LocationManagerService;
 import com.android.server.ServiceWatcher;
 
 import java.io.FileDescriptor;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -189,14 +187,6 @@
                 pw.println("  additional packages=" + mProviderPackages);
             }
         }
-        mServiceWatcher.runOnBinderBlocking(binder -> {
-            try {
-                TransferPipe.dumpAsync(binder, fd, args);
-            } catch (IOException | RemoteException e) {
-                pw.println("  <failed to dump location provider: " + e + ">");
-            }
-            return null;
-        }, null);
     }
 
     @Override
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/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index b52c021..1c9028d 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -333,7 +333,7 @@
         PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
                 collectingInstaller, mPackageManagerService.mInstallLock, mContext);
 
-        optimizer.performDexOpt(pkg, pkg.usesLibraryInfos,
+        optimizer.performDexOpt(pkg,
                 null /* ISAs */,
                 null /* CompilerStats.PackageStats */,
                 mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(pkg.packageName),
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 5b38208..580137d 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -125,7 +125,7 @@
      * <p>Calls to {@link com.android.server.pm.Installer#dexopt} on {@link #mInstaller} are
      * synchronized on {@link #mInstallLock}.
      */
-    int performDexOpt(PackageParser.Package pkg, List<SharedLibraryInfo> sharedLibraries,
+    int performDexOpt(PackageParser.Package pkg,
             String[] instructionSets, CompilerStats.PackageStats packageStats,
             PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
         if (pkg.applicationInfo.uid == -1) {
@@ -138,7 +138,7 @@
         synchronized (mInstallLock) {
             final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid);
             try {
-                return performDexOptLI(pkg, sharedLibraries, instructionSets,
+                return performDexOptLI(pkg, instructionSets,
                         packageStats, packageUseInfo, options);
             } finally {
                 releaseWakeLockLI(acquireTime);
@@ -152,9 +152,9 @@
      */
     @GuardedBy("mInstallLock")
     private int performDexOptLI(PackageParser.Package pkg,
-            List<SharedLibraryInfo> sharedLibraries,
             String[] targetInstructionSets, CompilerStats.PackageStats packageStats,
             PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
+        final List<SharedLibraryInfo> sharedLibraries = pkg.usesLibraryInfos;
         final String[] instructionSets = targetInstructionSets != null ?
                 targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index eeb4812..b72e836 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -204,7 +204,8 @@
         mSessionsDir.mkdirs();
 
         mApexManager = am;
-        mStagingManager = new StagingManager(pm, this, am);
+
+        mStagingManager = new StagingManager(pm, this, am, context);
     }
 
     boolean okToSendBroadcasts()  {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 20829b5..80e794f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9413,12 +9413,12 @@
                     options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY);
             for (PackageParser.Package depPackage : deps) {
                 // TODO: Analyze and investigate if we (should) profile libraries.
-                pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets,
+                pdo.performDexOpt(depPackage, instructionSets,
                         getOrCreateCompilerPackageStats(depPackage),
                     mDexManager.getPackageUseInfoOrDefault(depPackage.packageName), libraryOptions);
             }
         }
-        return pdo.performDexOpt(p, p.usesLibraryInfos, instructionSets,
+        return pdo.performDexOpt(p, instructionSets,
                 getOrCreateCompilerPackageStats(p),
                 mDexManager.getPackageUseInfoOrDefault(p.packageName), options);
     }
@@ -16324,7 +16324,7 @@
                         REASON_INSTALL,
                         DexoptOptions.DEXOPT_BOOT_COMPLETE
                                 | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
-                mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryInfos,
+                mPackageDexOptimizer.performDexOpt(pkg,
                         null /* instructionSets */,
                         getOrCreateCompilerPackageStats(pkg),
                         mDexManager.getPackageUseInfoOrDefault(packageName),
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index cbf5e9e..fac3839 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -39,6 +39,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Slog;
@@ -68,15 +69,18 @@
     private final PackageInstallerService mPi;
     private final PackageManagerService mPm;
     private final ApexManager mApexManager;
+    private final PowerManager mPowerManager;
     private final Handler mBgHandler;
 
     @GuardedBy("mStagedSessions")
     private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();
 
-    StagingManager(PackageManagerService pm, PackageInstallerService pi, ApexManager am) {
+    StagingManager(PackageManagerService pm, PackageInstallerService pi, ApexManager am,
+            Context context) {
         mPm = pm;
         mPi = pi;
         mApexManager = am;
+        mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mBgHandler = BackgroundThread.getHandler();
     }
 
@@ -286,6 +290,20 @@
             session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
                     "Staged installation of APKs failed. Check logcat messages for"
                         + "more information.");
+
+            if (!hasApex) {
+                return;
+            }
+
+            if (!mApexManager.abortActiveSession()) {
+                Slog.e(TAG, "Failed to abort APEXd session");
+            } else {
+                Slog.e(TAG,
+                        "Successfully aborted apexd session. Rebooting device in order to revert "
+                                + "to the previous state of APEXd.");
+                mPowerManager.reboot(null);
+            }
+
             return;
         }
 
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 176dbbf..89d24b1 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -36,6 +36,7 @@
 import android.database.ContentObserver;
 import android.hardware.SensorManager;
 import android.hardware.SystemSensorManager;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
 import android.hardware.power.V1_0.PowerHint;
@@ -81,7 +82,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.DumpUtils;
 import com.android.server.EventLogTags;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ab1b6ae..706901b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4373,7 +4373,11 @@
             Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit="
                     + mRemoveOnExit + ", mDestroying=" + mDestroying);
 
-            mWinAnimator.cancelExitAnimationForNextAnimationLocked();
+            // Cancel the existing exit animation for the next enter animation.
+            if (isSelfAnimating()) {
+                cancelAnimation();
+                destroySurfaceUnchecked();
+            }
             mAnimatingExit = false;
         }
         if (mDestroying) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 2e2da6d..969ced4 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -248,14 +248,6 @@
         mWallpaperControllerLocked = win.getDisplayContent().mWallpaperController;
     }
 
-    void cancelExitAnimationForNextAnimationLocked() {
-        if (DEBUG_ANIM) Slog.d(TAG,
-                "cancelExitAnimationForNextAnimationLocked: " + mWin);
-
-        mWin.cancelAnimation();
-        mWin.destroySurfaceUnchecked();
-    }
-
     void onAnimationFinished() {
         // Done animating, clean up.
         if (DEBUG_ANIM) Slog.v(
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/rescueparty/how_to_run.txt b/services/tests/rescueparty/how_to_run.txt
index 9528d39..a3a26d6 100644
--- a/services/tests/rescueparty/how_to_run.txt
+++ b/services/tests/rescueparty/how_to_run.txt
@@ -1,4 +1,3 @@
-# Per http://go/westworld-local-development#step3-test-atom-and-metric-locally-on-device ,
 # In one terminal:
 make statsd_testdrive
 ./out/host/linux-x86/bin/statsd_testdrive 122
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
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 3881e9e..4d6ff48 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
@@ -41,6 +42,8 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.HashMap;
@@ -339,6 +342,90 @@
         public static final String[] strings = { "current", "disabled", "enabled" };
     }
 
+    /**
+     * Security types we support.
+     */
+    /** @hide */
+    public static final int SECURITY_TYPE_OPEN = 0;
+    /** @hide */
+    public static final int SECURITY_TYPE_WEP = 1;
+    /** @hide */
+    public static final int SECURITY_TYPE_PSK = 2;
+    /** @hide */
+    public static final int SECURITY_TYPE_EAP = 3;
+    /** @hide */
+    public static final int SECURITY_TYPE_SAE = 4;
+    /** @hide */
+    public static final int SECURITY_TYPE_EAP_SUITE_B = 5;
+    /** @hide */
+    public static final int SECURITY_TYPE_OWE = 6;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "SECURITY_TYPE_" }, value = {
+            SECURITY_TYPE_OPEN,
+            SECURITY_TYPE_WEP,
+            SECURITY_TYPE_PSK,
+            SECURITY_TYPE_EAP,
+            SECURITY_TYPE_SAE,
+            SECURITY_TYPE_EAP_SUITE_B,
+            SECURITY_TYPE_OWE
+    })
+    public @interface SecurityType {}
+
+    /**
+     * @hide
+     * Set security params (sets the various bitsets exposed in WifiConfiguration).
+     *
+     * @param securityType One of the security types from {@link SecurityType}.
+     */
+    public void setSecurityParams(@SecurityType int securityType) {
+        // Clear all the bitsets.
+        allowedKeyManagement.clear();
+        allowedProtocols.clear();
+        allowedAuthAlgorithms.clear();
+        allowedPairwiseCiphers.clear();
+        allowedGroupCiphers.clear();
+        allowedGroupManagementCiphers.clear();
+        allowedSuiteBCiphers.clear();
+
+        switch (securityType) {
+            case SECURITY_TYPE_OPEN:
+                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                break;
+            case SECURITY_TYPE_WEP:
+                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+                allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
+                break;
+            case SECURITY_TYPE_PSK:
+                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                break;
+            case SECURITY_TYPE_EAP:
+                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+                break;
+            case SECURITY_TYPE_SAE:
+                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
+                requirePMF = true;
+                break;
+            case SECURITY_TYPE_EAP_SUITE_B:
+                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
+                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+                allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
+                allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
+                allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+                requirePMF = true;
+                break;
+            case SECURITY_TYPE_OWE:
+                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
+                requirePMF = true;
+                break;
+            default:
+                throw new IllegalArgumentException("unknown security type " + securityType);
+        }
+    }
+
     /** @hide */
     public static final int UNKNOWN_UID = -1;
 
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 333b82c..c99bd2e 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -269,58 +269,26 @@
         }
 
 
-        /**
-         * Set defaults for the various low level credential type fields in the newly created
-         * WifiConfiguration object.
-         *
-         * See {@link com.android.server.wifi.WifiConfigManager#setDefaultsInWifiConfiguration(
-         * WifiConfiguration)}.
-         *
-         * @param configuration provided WifiConfiguration object.
-         */
-        private static void setDefaultsInWifiConfiguration(
-                @NonNull WifiConfiguration configuration) {
-            configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
-            configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
-            configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
-            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
-            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
-        }
-
         private void setSecurityParamsInWifiConfiguration(
                 @NonNull WifiConfiguration configuration) {
             if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
                 // WifiConfiguration.preSharedKey needs quotes around ASCII password.
                 configuration.preSharedKey = "\"" + mWpa2PskPassphrase + "\"";
             } else if (!TextUtils.isEmpty(mWpa3SaePassphrase)) { // WPA3-SAE network.
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
-                // PMF mandatory for SAE.
-                configuration.requirePMF = true;
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
                 // WifiConfiguration.preSharedKey needs quotes around ASCII password.
                 configuration.preSharedKey = "\"" + mWpa3SaePassphrase + "\"";
             } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
                 configuration.enterpriseConfig = mWpa2EnterpriseConfig;
             } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
-                configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
-                // TODO (b/113878056): Verify these params once we verify SuiteB configuration.
-                configuration.allowedGroupManagementCiphers.set(
-                        WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
-                configuration.allowedSuiteBCiphers.set(
-                        WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
-                configuration.allowedSuiteBCiphers.set(
-                        WifiConfiguration.SuiteBCipher.ECDHE_RSA);
-                configuration.requirePMF = true;
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
                 configuration.enterpriseConfig = mWpa3EnterpriseConfig;
             } else if (mIsEnhancedOpen) { // OWE network
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
-                // PMF mandatory.
-                configuration.requirePMF = true;
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
             } else { // Open network
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
             }
         }
 
@@ -330,7 +298,6 @@
          */
         private WifiConfiguration buildWifiConfiguration() {
             final WifiConfiguration wifiConfiguration = new WifiConfiguration();
-            setDefaultsInWifiConfiguration(wifiConfiguration);
             // WifiConfiguration.SSID needs quotes around unicode SSID.
             if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) {
                 wifiConfiguration.SSID = "\"" + mSsidPatternMatcher.getPath() + "\"";
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 233fa2c..f02404f 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -303,58 +303,26 @@
             return this;
         }
 
-        /**
-         * Set defaults for the various low level credential type fields in the newly created
-         * WifiConfiguration object.
-         *
-         * See {@link com.android.server.wifi.WifiConfigManager#setDefaultsInWifiConfiguration(
-         * WifiConfiguration)}.
-         *
-         * @param configuration provided WifiConfiguration object.
-         */
-        private static void setDefaultsInWifiConfiguration(
-                @NonNull WifiConfiguration configuration) {
-            configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
-            configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
-            configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
-            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
-            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
-        }
-
         private void setSecurityParamsInWifiConfiguration(
                 @NonNull WifiConfiguration configuration) {
             if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
                 // WifiConfiguration.preSharedKey needs quotes around ASCII password.
                 configuration.preSharedKey = "\"" + mWpa2PskPassphrase + "\"";
             } else if (!TextUtils.isEmpty(mWpa3SaePassphrase)) { // WPA3-SAE network.
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
-                // PMF mandatory for SAE.
-                configuration.requirePMF = true;
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
                 // WifiConfiguration.preSharedKey needs quotes around ASCII password.
                 configuration.preSharedKey = "\"" + mWpa3SaePassphrase + "\"";
             } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
                 configuration.enterpriseConfig = mWpa2EnterpriseConfig;
             } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
-                configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
-                // TODO (b/113878056): Verify these params once we verify SuiteB configuration.
-                configuration.allowedGroupManagementCiphers.set(
-                        WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
-                configuration.allowedSuiteBCiphers.set(
-                        WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
-                configuration.allowedSuiteBCiphers.set(
-                        WifiConfiguration.SuiteBCipher.ECDHE_RSA);
-                configuration.requirePMF = true;
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
                 configuration.enterpriseConfig = mWpa3EnterpriseConfig;
             } else if (mIsEnhancedOpen) { // OWE network
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
-                // PMF mandatory.
-                configuration.requirePMF = true;
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
             } else { // Open network
-                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
             }
         }
 
@@ -364,7 +332,6 @@
          */
         private WifiConfiguration buildWifiConfiguration() {
             final WifiConfiguration wifiConfiguration = new WifiConfiguration();
-            setDefaultsInWifiConfiguration(wifiConfiguration);
             // WifiConfiguration.SSID needs quotes around unicode SSID.
             wifiConfiguration.SSID = "\"" + mSsid + "\"";
             if (mBssid != null) {
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index acc0518..b73551f 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -259,8 +259,17 @@
          * {@hide}
          */
         @SystemApi
-        @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
         public boolean ignoreLocationSettings;
+        /**
+         * This scan request will be hidden from app-ops noting for location information. This
+         * should only be used by FLP/NLP module on the device which is using the scan results to
+         * compute results for behalf on their clients. FLP/NLP module using this flag should ensure
+         * that they note in app-ops the eventual delivery of location information computed using
+         * these results to their client .
+         * {@hide}
+         */
+        @SystemApi
+        public boolean hideFromAppOps;
 
         /** Implement the Parcelable interface {@hide} */
         public int describeContents() {
@@ -279,6 +288,7 @@
             dest.writeInt(isPnoScan ? 1 : 0);
             dest.writeInt(type);
             dest.writeInt(ignoreLocationSettings ? 1 : 0);
+            dest.writeInt(hideFromAppOps ? 1 : 0);
             if (channels != null) {
                 dest.writeInt(channels.length);
                 for (int i = 0; i < channels.length; i++) {
@@ -314,6 +324,7 @@
                         settings.isPnoScan = in.readInt() == 1;
                         settings.type = in.readInt();
                         settings.ignoreLocationSettings = in.readInt() == 1;
+                        settings.hideFromAppOps = in.readInt() == 1;
                         int num_channels = in.readInt();
                         settings.channels = new ChannelSpec[num_channels];
                         for (int i = 0; i < num_channels; i++) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index f931ad2..479adbc 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -26,6 +26,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.regex.PatternSyntaxException;
 
 /**
  * A class representing a Wi-Fi P2p configuration for setting up a connection
@@ -252,7 +253,12 @@
          * Specify the network name, a.k.a. group name,
          * for creating or joining a group.
          * <p>
-         *     Must be called - an empty network name is not valid.
+         * A network name shall begin with "DIRECT-xy". x and y are selected
+         * from the following character set: upper case letters, lower case
+         * letters and numbers.
+         * <p>
+         *     Must be called - an empty network name or an network name
+         *     not conforming to the P2P Group ID naming rule is not valid.
          *
          * @param networkName network name of a group.
          * @return The builder to facilitate chaining
@@ -263,6 +269,14 @@
                 throw new IllegalArgumentException(
                         "network name must be non-empty.");
             }
+            try {
+                if (!networkName.matches("^DIRECT-[a-zA-Z0-9]{2}.*")) {
+                    throw new IllegalArgumentException(
+                            "network name must starts with the prefix DIRECT-xy.");
+                }
+            } catch (PatternSyntaxException e) {
+                // can never happen (fixed pattern)
+            }
             mNetworkName = networkName;
             return this;
         }
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index bef33b7..feac0e5 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -69,16 +69,6 @@
         assertEquals(MacAddress.ALL_ZEROS_ADDRESS, wifiNetworkSpecifier.bssidPatternMatcher.second);
         assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
                 .get(WifiConfiguration.KeyMgmt.NONE));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
-                .get(WifiConfiguration.Protocol.RSN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
-                .get(WifiConfiguration.AuthAlgorithm.OPEN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
-                .get(WifiConfiguration.PairwiseCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.TKIP));
     }
 
     /**
@@ -105,16 +95,6 @@
                 wifiNetworkSpecifier.bssidPatternMatcher.second);
         assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
                 .get(WifiConfiguration.KeyMgmt.WPA_PSK));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
-                .get(WifiConfiguration.Protocol.RSN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
-                .get(WifiConfiguration.AuthAlgorithm.OPEN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
-                .get(WifiConfiguration.PairwiseCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.TKIP));
         assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
                 wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
     }
@@ -150,16 +130,6 @@
                 .get(WifiConfiguration.KeyMgmt.WPA_EAP));
         assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
                 .get(WifiConfiguration.KeyMgmt.IEEE8021X));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
-                .get(WifiConfiguration.Protocol.RSN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
-                .get(WifiConfiguration.AuthAlgorithm.OPEN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
-                .get(WifiConfiguration.PairwiseCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.TKIP));
         assertTrue(wifiNetworkSpecifier.wifiConfiguration.hiddenSSID);
         assertEquals(enterpriseConfig.getEapMethod(),
                 wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getEapMethod());
diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
new file mode 100644
index 0000000..560c88e
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import static org.junit.Assert.fail;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit test harness for {@link android.net.wifi.p2p.WifiP2pConfig}
+ */
+@SmallTest
+public class WifiP2pConfigTest {
+    /**
+     * Check network name setter
+     */
+    @Test
+    public void testBuilderInvalidNetworkName() throws Exception {
+        WifiP2pConfig.Builder b = new WifiP2pConfig.Builder();
+
+        // sunny case
+        try {
+            b.setNetworkName("DIRECT-ab-Hello");
+        } catch (IllegalArgumentException e) {
+            fail("Unexpected IllegalArgumentException");
+        }
+
+        // sunny case, no trailing string
+        try {
+            b.setNetworkName("DIRECT-WR");
+        } catch (IllegalArgumentException e) {
+            fail("Unexpected IllegalArgumentException");
+        }
+
+        // less than 9 characters.
+        try {
+            b.setNetworkName("DIRECT-z");
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) { }
+
+        // not starts with DIRECT-xy.
+        try {
+            b.setNetworkName("ABCDEFGHIJK");
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) { }
+
+        // not starts with uppercase DIRECT-xy
+        try {
+            b.setNetworkName("direct-ab");
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) { }
+
+        // x and y are not selected from upper case letters, lower case letters or
+        // numbers.
+        try {
+            b.setNetworkName("direct-a?");
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) { }
+    }
+}