Merge "Report orientation change when visibility changes."
diff --git a/api/current.txt b/api/current.txt
index 8ec2f5a..3cec35f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -287,6 +287,7 @@
     field public static final int alertDialogTheme = 16843529; // 0x1010309
     field public static final int alignmentMode = 16843642; // 0x101037a
     field public static final int allContactsName = 16843468; // 0x10102cc
+    field public static final int allowAudioPlaybackCapture = 16844199; // 0x10105a7
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
     field public static final int allowEmbedded = 16843765; // 0x10103f5
@@ -4250,10 +4251,9 @@
 
   public class AppComponentFactory {
     ctor public AppComponentFactory();
-    method public android.content.pm.ApplicationInfo getApplicationInfo();
     method @NonNull public android.app.Activity instantiateActivity(@NonNull ClassLoader, @NonNull String, @Nullable android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
     method @NonNull public android.app.Application instantiateApplication(@NonNull ClassLoader, @NonNull String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
-    method @NonNull public ClassLoader instantiateClassLoader(@NonNull ClassLoader);
+    method @NonNull public ClassLoader instantiateClassLoader(@NonNull ClassLoader, @NonNull android.content.pm.ApplicationInfo);
     method @NonNull public android.content.ContentProvider instantiateProvider(@NonNull ClassLoader, @NonNull String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
     method @NonNull public android.content.BroadcastReceiver instantiateReceiver(@NonNull ClassLoader, @NonNull String, @Nullable android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
     method @NonNull public android.app.Service instantiateService(@NonNull ClassLoader, @NonNull String, @Nullable android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
@@ -6171,6 +6171,7 @@
     ctor public Service();
     method protected void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
     method public final android.app.Application getApplication();
+    method public final int getForegroundServiceType();
     method @Nullable public abstract android.os.IBinder onBind(android.content.Intent);
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public void onCreate();
@@ -26035,6 +26036,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 +26399,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 +29359,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);
@@ -29944,13 +29947,14 @@
     method public String getMacAddress();
     method public int getNetworkId();
     method public int getRssi();
-    method public int getRxLinkSpeedMbps();
+    method @IntRange(from=0xffffffff) public int getRxLinkSpeedMbps();
     method public String getSSID();
     method public android.net.wifi.SupplicantState getSupplicantState();
-    method public int getTxLinkSpeedMbps();
+    method @IntRange(from=0xffffffff) public int getTxLinkSpeedMbps();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final String FREQUENCY_UNITS = "MHz";
     field public static final String LINK_SPEED_UNITS = "Mbps";
+    field public static final int LINK_SPEED_UNKNOWN = -1; // 0xffffffff
   }
 
   public class WifiManager {
@@ -35513,7 +35517,7 @@
 
   public abstract class VibrationEffect implements android.os.Parcelable {
     method public static android.os.VibrationEffect createOneShot(long, int);
-    method public static android.os.VibrationEffect createPrebaked(int);
+    method public static android.os.VibrationEffect createPredefined(int);
     method public static android.os.VibrationEffect createWaveform(long[], int);
     method public static android.os.VibrationEffect createWaveform(long[], int[], int);
     method public int describeContents();
@@ -38403,14 +38407,12 @@
 
   public final class MediaStore {
     ctor public MediaStore();
-    method @NonNull public static android.net.Uri createPending(@NonNull android.content.Context, @NonNull android.provider.MediaStore.PendingParams);
     method @NonNull public static java.util.Set<java.lang.String> getAllVolumeNames(android.content.Context);
     method public static android.net.Uri getDocumentUri(android.content.Context, android.net.Uri);
     method public static android.net.Uri getMediaScannerUri();
     method public static android.net.Uri getMediaUri(android.content.Context, android.net.Uri);
     method public static String getVersion(android.content.Context);
     method @NonNull public static String getVolumeName(@NonNull android.net.Uri);
-    method @NonNull public static android.provider.MediaStore.PendingSession openPending(@NonNull android.content.Context, @NonNull android.net.Uri);
     method @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri);
     method @NonNull public static android.net.Uri setRequireOriginal(@NonNull android.net.Uri);
     field public static final String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
@@ -38683,6 +38685,7 @@
   public static interface MediaStore.MediaColumns extends android.provider.BaseColumns {
     field @Deprecated public static final String DATA = "_data";
     field public static final String DATE_ADDED = "date_added";
+    field public static final String DATE_EXPIRES = "date_expires";
     field public static final String DATE_MODIFIED = "date_modified";
     field public static final String DISPLAY_NAME = "_display_name";
     field public static final String DOCUMENT_ID = "document_id";
@@ -38699,23 +38702,6 @@
     field public static final String WIDTH = "width";
   }
 
-  public static class MediaStore.PendingParams {
-    ctor public MediaStore.PendingParams(@NonNull android.net.Uri, @NonNull String, @NonNull String);
-    method public void setDownloadUri(@Nullable android.net.Uri);
-    method public void setPrimaryDirectory(@Nullable String);
-    method public void setRefererUri(@Nullable android.net.Uri);
-    method public void setSecondaryDirectory(@Nullable String);
-  }
-
-  public static class MediaStore.PendingSession implements java.lang.AutoCloseable {
-    method public void abandon();
-    method public void close();
-    method public void notifyProgress(@IntRange(from=0, to=100) int);
-    method @NonNull public android.os.ParcelFileDescriptor open() throws java.io.FileNotFoundException;
-    method @NonNull public java.io.OutputStream openOutputStream() throws java.io.FileNotFoundException;
-    method @NonNull public android.net.Uri publish();
-  }
-
   public static final class MediaStore.Video {
     ctor public MediaStore.Video();
     method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
@@ -42515,6 +42501,7 @@
     method public static void chown(String, int, int) throws android.system.ErrnoException;
     method public static void close(java.io.FileDescriptor) throws android.system.ErrnoException;
     method public static void connect(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+    method public static void connect(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
     method public static java.io.FileDescriptor dup(java.io.FileDescriptor) throws android.system.ErrnoException;
     method public static java.io.FileDescriptor dup2(java.io.FileDescriptor, int) throws android.system.ErrnoException;
     method public static String[] environ();
@@ -45020,7 +45007,7 @@
     method public String getCountryIso();
     method public int getDataRoaming();
     method public CharSequence getDisplayName();
-    method public String getGroupUuid();
+    method @Nullable public String getGroupUuid();
     method public String getIccId();
     method public int getIconTint();
     method @Deprecated public int getMcc();
@@ -45061,7 +45048,7 @@
     method public boolean isNetworkRoaming(int);
     method public static boolean isUsableSubscriptionId(int);
     method public static boolean isValidSubscriptionId(int);
-    method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
+    method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean removeSubscriptionsFromGroup(@NonNull int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setMetered(boolean, int);
@@ -45070,7 +45057,7 @@
     method public void setSubscriptionOverrideCongested(int, boolean, long);
     method public void setSubscriptionOverrideUnmetered(int, boolean, long);
     method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>);
-    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
+    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, @NonNull android.app.PendingIntent);
     field public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
     field public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
     field public static final String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
@@ -45179,7 +45166,7 @@
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSubscriberId();
     method public String getTypeAllocationCode();
     method public String getTypeAllocationCode(int);
-    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVisualVoicemailPackageName();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber();
@@ -45352,8 +45339,8 @@
   public final class UiccCardInfo implements android.os.Parcelable {
     method public int describeContents();
     method public int getCardId();
-    method public String getEid();
-    method public String getIccId();
+    method @Nullable public String getEid();
+    method @Nullable public String getIccId();
     method public int getSlotIndex();
     method public boolean isEuicc();
     method public boolean isRemovable();
@@ -51205,8 +51192,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 +51967,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);
@@ -57773,16 +57760,16 @@
     method @Deprecated public void onZoom(boolean);
   }
 
-  public class ZoomControls extends android.widget.LinearLayout {
-    ctor public ZoomControls(android.content.Context);
-    ctor public ZoomControls(android.content.Context, android.util.AttributeSet);
-    method public void hide();
-    method public void setIsZoomInEnabled(boolean);
-    method public void setIsZoomOutEnabled(boolean);
-    method public void setOnZoomInClickListener(android.view.View.OnClickListener);
-    method public void setOnZoomOutClickListener(android.view.View.OnClickListener);
-    method public void setZoomSpeed(long);
-    method public void show();
+  @Deprecated public class ZoomControls extends android.widget.LinearLayout {
+    ctor @Deprecated public ZoomControls(android.content.Context);
+    ctor @Deprecated public ZoomControls(android.content.Context, android.util.AttributeSet);
+    method @Deprecated public void hide();
+    method @Deprecated public void setIsZoomInEnabled(boolean);
+    method @Deprecated public void setIsZoomOutEnabled(boolean);
+    method @Deprecated public void setOnZoomInClickListener(android.view.View.OnClickListener);
+    method @Deprecated public void setOnZoomOutClickListener(android.view.View.OnClickListener);
+    method @Deprecated public void setZoomSpeed(long);
+    method @Deprecated public void show();
   }
 
 }
diff --git a/api/removed.txt b/api/removed.txt
index c4ed871..40b1316 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -508,6 +508,8 @@
   }
 
   public final class MediaStore {
+    method @Deprecated @NonNull public static android.net.Uri createPending(@NonNull android.content.Context, @NonNull android.provider.MediaStore.PendingParams);
+    method @Deprecated @NonNull public static android.provider.MediaStore.PendingSession openPending(@NonNull android.content.Context, @NonNull android.net.Uri);
     method @Deprecated @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
     method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
     method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
@@ -515,11 +517,27 @@
   }
 
   public static interface MediaStore.MediaColumns extends android.provider.BaseColumns {
-    field @Deprecated public static final String DATE_EXPIRES = "date_expires";
     field @Deprecated public static final String HASH = "_hash";
     field @Deprecated public static final String IS_TRASHED = "is_trashed";
   }
 
+  @Deprecated public static class MediaStore.PendingParams {
+    ctor public MediaStore.PendingParams(@NonNull android.net.Uri, @NonNull String, @NonNull String);
+    method public void setDownloadUri(@Nullable android.net.Uri);
+    method public void setPrimaryDirectory(@Nullable String);
+    method public void setRefererUri(@Nullable android.net.Uri);
+    method public void setSecondaryDirectory(@Nullable String);
+  }
+
+  @Deprecated public static class MediaStore.PendingSession implements java.lang.AutoCloseable {
+    method public void abandon();
+    method public void close();
+    method public void notifyProgress(@IntRange(from=0, to=100) int);
+    method @NonNull public android.os.ParcelFileDescriptor open() throws java.io.FileNotFoundException;
+    method @NonNull public java.io.OutputStream openOutputStream() throws java.io.FileNotFoundException;
+    method @NonNull public android.net.Uri publish();
+  }
+
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field @Deprecated public static final String CONTACT_METADATA_SYNC = "contact_metadata_sync";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 17ea2e1..9ed1706 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -565,7 +565,7 @@
   }
 
   public class StatusBarManager {
-    method public android.app.StatusBarManager.DisableInfo getDisableInfo();
+    method @NonNull public android.app.StatusBarManager.DisableInfo getDisableInfo();
     method public void setDisabledForSetup(boolean);
   }
 
@@ -3455,15 +3455,23 @@
     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 @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioVolumeGroups getAudioVolumeGroups();
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method public boolean isAudioServerRunning();
     method public boolean isHdmiSystemAudioSupported();
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
+    method public void registerVolumeGroupCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.VolumeGroupCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.MODIFY_AUDIO_ROUTING}) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int requestAudioFocus(@NonNull android.media.AudioFocusRequest, @Nullable android.media.audiopolicy.AudioPolicy);
     method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setVolumeIndexForAttributes(@NonNull android.media.AudioAttributes, int, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
+    method public void unregisterVolumeGroupCallback(@NonNull android.media.AudioManager.VolumeGroupCallback);
     field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
     field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
     field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
@@ -3477,6 +3485,11 @@
     method public void onAudioServerUp();
   }
 
+  public abstract static class AudioManager.VolumeGroupCallback {
+    ctor public AudioManager.VolumeGroupCallback();
+    method public void onAudioVolumeGroupChanged(int, int);
+  }
+
   public final class AudioPlaybackConfiguration implements android.os.Parcelable {
     method public int getClientPid();
     method public int getClientUid();
@@ -3647,6 +3660,9 @@
     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 int getVolumeGroupIdForAttributes(@NonNull android.media.AudioAttributes);
+    method public int getVolumeGroupIdForLegacyStreamType(int);
     method public java.util.Iterator<android.media.audiopolicy.AudioProductStrategy> iterator();
     method public int size();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -3662,6 +3678,27 @@
     field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategy> CREATOR;
   }
 
+  public final class AudioVolumeGroup implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.util.List<android.media.AudioAttributes> getAudioAttributes();
+    method public int getId();
+    method @NonNull public int[] getLegacyStreamTypes();
+    method @NonNull public String name();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioVolumeGroup> CREATOR;
+  }
+
+  public final class AudioVolumeGroups implements java.lang.Iterable<android.media.audiopolicy.AudioVolumeGroup> android.os.Parcelable {
+    ctor public AudioVolumeGroups();
+    method public int describeContents();
+    method @Nullable public android.media.audiopolicy.AudioVolumeGroup getById(int);
+    method public java.util.Iterator<android.media.audiopolicy.AudioVolumeGroup> iterator();
+    method public int size();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioVolumeGroups> CREATOR;
+    field public static final int DEFAULT_VOLUME_GROUP = -1; // 0xffffffff
+  }
+
 }
 
 package android.media.session {
@@ -4849,7 +4886,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;
@@ -5788,7 +5826,12 @@
 
   public final class DeviceConfig {
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(String, String, boolean);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(String, String, float);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(String, String, int);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static long getLong(String, String, long);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(String, String);
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(String, String, String);
     method public static void removeOnPropertyChangedListener(android.provider.DeviceConfig.OnPropertyChangedListener);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(String, String, String, boolean);
@@ -5797,6 +5840,7 @@
     field public static final String NAMESPACE_GAME_DRIVER = "game_driver";
     field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
     field public static final String NAMESPACE_NETD_NATIVE = "netd_native";
+    field public static final String NAMESPACE_SYSTEMUI = "systemui";
   }
 
   public static interface DeviceConfig.ActivityManager {
@@ -5839,14 +5883,6 @@
     field public static final String NAMESPACE = "media_native";
   }
 
-  public static interface DeviceConfig.NotificationAssistant {
-    field public static final String GENERATE_ACTIONS = "generate_actions";
-    field public static final String GENERATE_REPLIES = "generate_replies";
-    field public static final String MAX_MESSAGES_TO_EXTRACT = "max_messages_to_extract";
-    field public static final String MAX_SUGGESTIONS = "max_suggestions";
-    field public static final String NAMESPACE = "notification_assistant";
-  }
-
   public static interface DeviceConfig.OnPropertyChangedListener {
     method public void onPropertyChanged(String, String, String);
   }
@@ -7476,6 +7512,13 @@
     field public static final int VSNCP_TIMEOUT = 2236; // 0x8bc
   }
 
+  public final class DataSpecificRegistrationStates implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationStates> CREATOR;
+  }
+
   public final class DisconnectCause {
     field public static final int ALREADY_DIALING = 72; // 0x48
     field public static final int ANSWERED_ELSEWHERE = 52; // 0x34
@@ -7584,6 +7627,7 @@
     method public int getAccessNetworkTechnology();
     method public int[] getAvailableServices();
     method public android.telephony.CellIdentity getCellIdentity();
+    method @Nullable public android.telephony.DataSpecificRegistrationStates getDataSpecificStates();
     method public int getDomain();
     method public int getRegState();
     method public int getRejectCause();
@@ -8489,14 +8533,14 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSetting(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSetting(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSetting(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSetting(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
     field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1
@@ -8511,10 +8555,10 @@
 
   public static class ImsMmTelManager.RegistrationCallback {
     ctor public ImsMmTelManager.RegistrationCallback();
-    method public void onDeregistered(android.telephony.ims.ImsReasonInfo);
     method public void onRegistered(int);
     method public void onRegistering(int);
     method public void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
+    method public void onUnregistered(android.telephony.ims.ImsReasonInfo);
   }
 
   public final class ImsReasonInfo implements android.os.Parcelable {
@@ -9239,7 +9283,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 +9316,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..a1d691e 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);
@@ -1915,7 +1921,12 @@
 
   public final class DeviceConfig {
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static boolean getBoolean(String, String, boolean);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static float getFloat(String, String, float);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static int getInt(String, String, int);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static long getLong(String, String, long);
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(String, String);
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getString(String, String, String);
     method public static void removeOnPropertyChangedListener(android.provider.DeviceConfig.OnPropertyChangedListener);
     method @RequiresPermission("android.permission.WRITE_DEVICE_CONFIG") public static void resetToDefaults(int, @Nullable String);
     method @RequiresPermission("android.permission.WRITE_DEVICE_CONFIG") public static boolean setProperty(String, String, String, boolean);
@@ -1991,6 +2002,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 +2393,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 +2426,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/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index 6703909..c416fa1 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -28,7 +28,6 @@
 #include "idmap2/FileUtils.h"
 #include "idmap2/Idmap.h"
 #include "idmap2/Policies.h"
-#include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 
 using android::ApkAssets;
@@ -38,7 +37,6 @@
 using android::idmap2::PoliciesToBitmask;
 using android::idmap2::PolicyBitmask;
 using android::idmap2::PolicyFlags;
-using android::idmap2::Result;
 using android::idmap2::utils::kIdmapFilePermissionMask;
 using android::idmap2::utils::UidHasWriteAccessToPath;
 
@@ -77,9 +75,11 @@
   }
 
   PolicyBitmask fulfilled_policies = 0;
-  if (auto result = PoliciesToBitmask(policies, out_error)) {
-    fulfilled_policies |= *result;
+  auto conv_result = PoliciesToBitmask(policies);
+  if (conv_result) {
+    fulfilled_policies |= *conv_result;
   } else {
+    out_error << "error: " << conv_result.GetErrorMessage() << std::endl;
     return false;
   }
 
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index 553d8ca..83a40ef 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -53,6 +53,7 @@
 using android::StringPiece16;
 using android::base::StringPrintf;
 using android::idmap2::CommandLineOptions;
+using android::idmap2::Error;
 using android::idmap2::IdmapHeader;
 using android::idmap2::ResourceId;
 using android::idmap2::Result;
@@ -71,17 +72,17 @@
   ResourceId resid;
   resid = strtol(res.c_str(), &endptr, kBaseHex);
   if (*endptr == '\0') {
-    return {resid};
+    return resid;
   }
 
   // next, try to parse as a package:type/name string
   resid = am.GetResourceId(res, "", fallback_package);
   if (is_valid_resid(resid)) {
-    return {resid};
+    return resid;
   }
 
   // end of the road: res could not be parsed
-  return {};
+  return Error("failed to obtain resource id for %s", res.c_str());
 }
 
 Result<std::string> WARN_UNUSED GetValue(const AssetManager2& am, ResourceId resid) {
@@ -90,7 +91,7 @@
   uint32_t flags;
   ApkAssetsCookie cookie = am.GetResource(resid, false, 0, &value, &config, &flags);
   if (cookie == kInvalidCookie) {
-    return {};
+    return Error("no resource 0x%08x in asset manager", resid);
   }
 
   std::string out;
@@ -128,31 +129,31 @@
       out.append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data));
       break;
   }
-  return {out};
+  return out;
 }
 
 Result<std::string> GetTargetPackageNameFromManifest(const std::string& apk_path) {
   const auto zip = ZipFile::Open(apk_path);
   if (!zip) {
-    return {};
+    return Error("failed to open %s as zip", apk_path.c_str());
   }
   const auto entry = zip->Uncompress("AndroidManifest.xml");
   if (!entry) {
-    return {};
+    return Error("failed to uncompress AndroidManifest.xml in %s", apk_path.c_str());
   }
   const auto xml = Xml::Create(entry->buf, entry->size);
   if (!xml) {
-    return {};
+    return Error("failed to create XML buffer");
   }
   const auto tag = xml->FindTag("overlay");
   if (!tag) {
-    return {};
+    return Error("failed to find <overlay> tag");
   }
   const auto iter = tag->find("targetPackage");
   if (iter == tag->end()) {
-    return {};
+    return Error("failed to find targetPackage attribute");
   }
-  return {iter->second};
+  return iter->second;
 }
 }  // namespace
 
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 873779f..e5f6223 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -142,9 +142,9 @@
   std::vector<InputOverlay> interesting_apks;
   for (const std::string& path : *apk_paths) {
     Result<OverlayManifestInfo> overlay_info =
-        ExtractOverlayManifestInfo(path, out_error,
-                                   /* assert_overlay */ false);
+        ExtractOverlayManifestInfo(path, /* assert_overlay */ false);
     if (!overlay_info) {
+      out_error << "error: " << overlay_info.GetErrorMessage() << std::endl;
       return false;
     }
 
@@ -163,9 +163,11 @@
 
     PolicyBitmask fulfilled_policies;
     if (!override_policies.empty()) {
-      if (Result<PolicyBitmask> result = PoliciesToBitmask(override_policies, out_error)) {
-        fulfilled_policies = *result;
+      auto conv_result = PoliciesToBitmask(override_policies);
+      if (conv_result) {
+        fulfilled_policies = *conv_result;
       } else {
+        out_error << "error: " << conv_result.GetErrorMessage() << std::endl;
         return false;
       }
     } else {
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 0e4bd89..fa94414 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -34,7 +34,6 @@
 #include "idmap2/FileUtils.h"
 #include "idmap2/Idmap.h"
 #include "idmap2/Policies.h"
-#include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 
 #include "idmap2d/Idmap2Service.h"
@@ -45,7 +44,6 @@
 using android::idmap2::Idmap;
 using android::idmap2::IdmapHeader;
 using android::idmap2::PolicyBitmask;
-using android::idmap2::Result;
 using android::idmap2::utils::kIdmapCacheDir;
 using android::idmap2::utils::kIdmapFilePermissionMask;
 using android::idmap2::utils::UidHasWriteAccessToPath;
diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h
index eecee25..911d3f2 100644
--- a/cmds/idmap2/include/idmap2/Policies.h
+++ b/cmds/idmap2/include/idmap2/Policies.h
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <ostream>
 #include <string>
 #include <vector>
 
@@ -33,8 +32,7 @@
 
 // Parses a the string representation of a set of policies into a bitmask. The format of the string
 // is the same as for the <policy> element.
-Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies,
-                                        std::ostream& err);
+Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies);
 
 }  // namespace android::idmap2
 
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
index 22827ac..1d81c48 100644
--- a/cmds/idmap2/include/idmap2/ResourceUtils.h
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -18,10 +18,8 @@
 #define IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_
 
 #include <optional>
-#include <ostream>
 #include <string>
 
-#include "android-base/macros.h"
 #include "androidfw/AssetManager2.h"
 
 #include "idmap2/Idmap.h"
@@ -38,10 +36,9 @@
 };
 
 Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path,
-                                                       std::ostream& out_error,
                                                        bool assert_overlay = true);
 
-Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid);
+Result<std::string> ResToTypeEntryName(const AssetManager2& am, ResourceId resid);
 
 }  // namespace android::idmap2::utils
 
diff --git a/cmds/idmap2/include/idmap2/Result.h b/cmds/idmap2/include/idmap2/Result.h
index d88dd51..41b15eb 100644
--- a/cmds/idmap2/include/idmap2/Result.h
+++ b/cmds/idmap2/include/idmap2/Result.h
@@ -17,7 +17,6 @@
 #ifndef IDMAP2_INCLUDE_IDMAP2_RESULT_H_
 #define IDMAP2_INCLUDE_IDMAP2_RESULT_H_
 
-#include <optional>
 #include <string>
 #include <utility>
 #include <variant>
@@ -26,13 +25,6 @@
 
 namespace android::idmap2 {
 
-template <typename T>
-using Result = std::optional<T>;
-
-static constexpr std::nullopt_t kResultError = std::nullopt;
-
-namespace v2 {
-
 using Unit = std::monostate;
 
 class Error {
@@ -148,8 +140,6 @@
   return std::holds_alternative<T>(data_);
 }
 
-}  // namespace v2
-
 }  // namespace android::idmap2
 
 #endif  // IDMAP2_INCLUDE_IDMAP2_RESULT_H_
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index ec498ff..a1341fb 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -121,7 +121,9 @@
 Result<uint32_t> GetCrc(const ZipFile& zip) {
   const Result<uint32_t> a = zip.Crc("resources.arsc");
   const Result<uint32_t> b = zip.Crc("AndroidManifest.xml");
-  return a && b ? Result<uint32_t>(*a ^ *b) : kResultError;
+  return a && b
+             ? Result<uint32_t>(*a ^ *b)
+             : Error("Couldn't get CRC for \"%s\"", a ? "AndroidManifest.xml" : "resources.arsc");
 }
 
 }  // namespace
@@ -355,9 +357,9 @@
     return nullptr;
   }
 
-  Result<utils::OverlayManifestInfo> overlay_info =
-      utils::ExtractOverlayManifestInfo(overlay_apk_path, out_error);
+  auto overlay_info = utils::ExtractOverlayManifestInfo(overlay_apk_path);
   if (!overlay_info) {
+    out_error << "error: " << overlay_info.GetErrorMessage() << std::endl;
     return nullptr;
   }
 
diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp
index 6649288..c6ba87d 100644
--- a/cmds/idmap2/libidmap2/Policies.cpp
+++ b/cmds/idmap2/libidmap2/Policies.cpp
@@ -16,7 +16,6 @@
 
 #include <iterator>
 #include <map>
-#include <sstream>
 #include <string>
 #include <vector>
 
@@ -39,16 +38,14 @@
 };
 }  // namespace
 
-Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies,
-                                        std::ostream& err) {
+Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies) {
   PolicyBitmask bitmask = 0;
   for (const std::string& policy : policies) {
     const auto iter = kStringToFlag.find(policy);
     if (iter != kStringToFlag.end()) {
       bitmask |= iter->second;
     } else {
-      err << "error: unknown policy \"" << policy << "\"";
-      return kResultError;
+      return Error("unknown policy \"%s\"", policy.c_str());
     }
   }
 
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index b78e942..1149c90 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -75,7 +75,7 @@
                                             type_entry.GetEntryOffset() + i);
       const ResourceId overlay_resid =
           RESID(last_seen_package_id_, type_entry.GetOverlayTypeId(), entry);
-      Result<std::string> name;
+      Result<std::string> name(Error(""));
       if (target_package_loaded) {
         name = utils::ResToTypeEntryName(target_am_, target_resid);
       }
diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp
index 7a984f3..a24836d 100644
--- a/cmds/idmap2/libidmap2/ResourceUtils.cpp
+++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp
@@ -33,10 +33,10 @@
 
 namespace android::idmap2::utils {
 
-Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid) {
+Result<std::string> ResToTypeEntryName(const AssetManager2& am, ResourceId resid) {
   AssetManager2::ResourceName name;
   if (!am.GetResourceName(resid, &name)) {
-    return {};
+    return Error("no resource 0x%08x in asset manager", resid);
   }
   std::string out;
   if (name.type != nullptr) {
@@ -50,36 +50,31 @@
   } else {
     out += Utf16ToUtf8(StringPiece16(name.entry16, name.entry_len));
   }
-  return {out};
+  return out;
 }
 
 Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path,
-                                                       std::ostream& out_error,
                                                        bool assert_overlay) {
   std::unique_ptr<const ZipFile> zip = ZipFile::Open(path);
   if (!zip) {
-    out_error << "error: failed to open " << path << " as a zip file" << std::endl;
-    return kResultError;
+    return Error("failed to open %s as a zip file", path.c_str());
   }
 
   std::unique_ptr<const MemoryChunk> entry = zip->Uncompress("AndroidManifest.xml");
   if (!entry) {
-    out_error << "error: failed to uncompress AndroidManifest.xml from " << path << std::endl;
-    return kResultError;
+    return Error("failed to uncompress AndroidManifest.xml from %s", path.c_str());
   }
 
   std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size);
   if (!xml) {
-    out_error << "error: failed to parse AndroidManifest.xml from " << path << std::endl;
-    return kResultError;
+    return Error("failed to parse AndroidManifest.xml from %s", path.c_str());
   }
 
   OverlayManifestInfo info{};
   const auto tag = xml->FindTag("overlay");
   if (!tag) {
     if (assert_overlay) {
-      out_error << "error: <overlay> missing from AndroidManifest.xml of " << path << std::endl;
-      return kResultError;
+      return Error("<overlay> missing from AndroidManifest.xml of %s", path.c_str());
     }
     return info;
   }
@@ -87,8 +82,7 @@
   auto iter = tag->find("targetPackage");
   if (iter == tag->end()) {
     if (assert_overlay) {
-      out_error << "error: android:targetPackage missing from <overlay> of " << path << std::endl;
-      return kResultError;
+      return Error("android:targetPackage missing from <overlay> of %s", path.c_str());
     }
   } else {
     info.target_package = iter->second;
diff --git a/cmds/idmap2/libidmap2/Result.cpp b/cmds/idmap2/libidmap2/Result.cpp
index bd4fabd..471dab2 100644
--- a/cmds/idmap2/libidmap2/Result.cpp
+++ b/cmds/idmap2/libidmap2/Result.cpp
@@ -23,7 +23,7 @@
 namespace android::idmap2 {
 
 // NOLINTNEXTLINE(cert-dcl50-cpp)
-v2::Error::Error(const char* fmt, ...) {
+Error::Error(const char* fmt, ...) {
   va_list ap;
   va_start(ap, fmt);
   base::StringAppendV(&msg_, fmt, ap);
@@ -31,7 +31,7 @@
 }
 
 // NOLINTNEXTLINE(cert-dcl50-cpp)
-v2::Error::Error(const Error& parent, const char* fmt, ...) : msg_(parent.msg_) {
+Error::Error(const Error& parent, const char* fmt, ...) : msg_(parent.msg_) {
   msg_.append(" -> ");
 
   va_list ap;
diff --git a/cmds/idmap2/libidmap2/ZipFile.cpp b/cmds/idmap2/libidmap2/ZipFile.cpp
index 15ec3f9..0f07324 100644
--- a/cmds/idmap2/libidmap2/ZipFile.cpp
+++ b/cmds/idmap2/libidmap2/ZipFile.cpp
@@ -59,7 +59,10 @@
 Result<uint32_t> ZipFile::Crc(const std::string& entryPath) const {
   ::ZipEntry entry;
   int32_t status = ::FindEntry(handle_, ::ZipString(entryPath.c_str()), &entry);
-  return status == 0 ? Result<uint32_t>(entry.crc32) : kResultError;
+  if (status != 0) {
+    return Error("failed to find zip entry %s", entryPath.c_str());
+  }
+  return entry.crc32;
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 2e85eb6..34a0097 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -58,21 +58,15 @@
   });
   ASSERT_THAT(v, NotNull());
   ASSERT_EQ(v->size(), 10U);
-  ASSERT_EQ(
-      std::set<std::string>(v->begin(), v->end()),
-      std::set<std::string>(
-          {
-              root + "/target/target.apk",
-              root + "/target/target-no-overlayable.apk",
-              root + "/overlay/overlay.apk",
-              root + "/overlay/overlay-no-name.apk",
-              root + "/overlay/overlay-no-name-static.apk",
-              root + "/overlay/overlay-static-1.apk",
-              root + "/overlay/overlay-static-2.apk",
-              root + "/signature-overlay/signature-overlay.apk",
-              root + "/system-overlay/system-overlay.apk",
-              root + "/system-overlay-invalid/system-overlay-invalid.apk"
-          }));
+  ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
+            std::set<std::string>(
+                {root + "/target/target.apk", root + "/target/target-no-overlayable.apk",
+                 root + "/overlay/overlay.apk", root + "/overlay/overlay-no-name.apk",
+                 root + "/overlay/overlay-no-name-static.apk",
+                 root + "/overlay/overlay-static-1.apk", root + "/overlay/overlay-static-2.apk",
+                 root + "/signature-overlay/signature-overlay.apk",
+                 root + "/system-overlay/system-overlay.apk",
+                 root + "/system-overlay-invalid/system-overlay-invalid.apk"}));
 }
 
 TEST(FileUtilsTests, ReadFile) {
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 53ec03b..bbfbad9 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -256,10 +256,10 @@
   ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
   ASSERT_EQ(types[0]->GetEntryCount(), 4U);
   ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0001U);  // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0002U);  // string/policy_system_vendor
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);   // string/policy_public
+  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry);  // string/policy_signature
+  ASSERT_EQ(types[0]->GetEntry(2), 0x0001U);   // string/policy_system
+  ASSERT_EQ(types[0]->GetEntry(3), 0x0002U);   // string/policy_system_vendor
 }
 
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
@@ -267,7 +267,8 @@
   std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
   ASSERT_THAT(target_apk, NotNull());
 
-  const std::string overlay_apk_path(GetTestDataPath() + "/signature-overlay/signature-overlay.apk");
+  const std::string overlay_apk_path(GetTestDataPath() +
+                                     "/signature-overlay/signature-overlay.apk");
   std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
   ASSERT_THAT(overlay_apk, NotNull());
 
@@ -294,7 +295,7 @@
   ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
   ASSERT_EQ(types[0]->GetEntryCount(), 1U);
   ASSERT_EQ(types[0]->GetEntryOffset(), 7U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_signature
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/policy_signature
 }
 
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignatureNotFulfilled) {
@@ -302,7 +303,8 @@
   std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
   ASSERT_THAT(target_apk, NotNull());
 
-  const std::string overlay_apk_path(GetTestDataPath() + "/signature-overlay/signature-overlay.apk");
+  const std::string overlay_apk_path(GetTestDataPath() +
+                                     "/signature-overlay/signature-overlay.apk");
   std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
   ASSERT_THAT(overlay_apk, NotNull());
 
@@ -323,7 +325,7 @@
   ASSERT_EQ(data->GetHeader()->GetTypeCount(), 0U);
 
   const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 0U); // can't overlay, so contains nothing
+  ASSERT_EQ(types.size(), 0U);  // can't overlay, so contains nothing
 }
 
 // Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
@@ -359,10 +361,10 @@
   ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
   ASSERT_EQ(types[0]->GetEntryCount(), 4U);
   ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0003U);  // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0005U);  // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0006U);  // string/policy_system_vendor
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0003U);   // string/policy_public
+  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry);  // string/policy_signature
+  ASSERT_EQ(types[0]->GetEntry(2), 0x0005U);   // string/policy_system
+  ASSERT_EQ(types[0]->GetEntry(3), 0x0006U);   // string/policy_system_vendor
 }
 
 // Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp
index ab567ad..a76da53 100644
--- a/cmds/idmap2/tests/PoliciesTests.cpp
+++ b/cmds/idmap2/tests/PoliciesTests.cpp
@@ -27,44 +27,42 @@
 namespace android::idmap2 {
 
 TEST(PoliciesTests, PoliciesToBitmasks) {
-  const Result<PolicyBitmask> bitmask1 = PoliciesToBitmask({"system"}, std::cerr);
-  ASSERT_NE(bitmask1, kResultError);
-  ASSERT_EQ(bitmask1, PolicyFlags::POLICY_SYSTEM_PARTITION);
+  const auto bitmask1 = PoliciesToBitmask({"system"});
+  ASSERT_TRUE(bitmask1);
+  ASSERT_EQ(*bitmask1, PolicyFlags::POLICY_SYSTEM_PARTITION);
 
-  const Result<PolicyBitmask> bitmask2 = PoliciesToBitmask({"system", "vendor"}, std::cerr);
-  ASSERT_NE(bitmask2, kResultError);
-  ASSERT_EQ(bitmask2, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION);
+  const auto bitmask2 = PoliciesToBitmask({"system", "vendor"});
+  ASSERT_TRUE(bitmask2);
+  ASSERT_EQ(*bitmask2, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION);
 
-  const Result<PolicyBitmask> bitmask3 = PoliciesToBitmask({"vendor", "system"}, std::cerr);
-  ASSERT_NE(bitmask3, kResultError);
-  ASSERT_EQ(bitmask3, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION);
+  const auto bitmask3 = PoliciesToBitmask({"vendor", "system"});
+  ASSERT_TRUE(bitmask3);
+  ASSERT_EQ(*bitmask3, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION);
 
-  const Result<PolicyBitmask> bitmask4 =
-      PoliciesToBitmask({"public", "product", "system", "vendor"}, std::cerr);
-  ASSERT_NE(bitmask4, kResultError);
-  ASSERT_EQ(bitmask4, PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION |
-                          PolicyFlags::POLICY_SYSTEM_PARTITION |
-                          PolicyFlags::POLICY_VENDOR_PARTITION);
+  const auto bitmask4 = PoliciesToBitmask({"public", "product", "system", "vendor"});
+  ASSERT_TRUE(bitmask4);
+  ASSERT_EQ(*bitmask4, PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION |
+                           PolicyFlags::POLICY_SYSTEM_PARTITION |
+                           PolicyFlags::POLICY_VENDOR_PARTITION);
 
-  const Result<PolicyBitmask> bitmask5 =
-      PoliciesToBitmask({"system", "system", "system"}, std::cerr);
-  ASSERT_NE(bitmask5, kResultError);
-  ASSERT_EQ(bitmask5, PolicyFlags::POLICY_SYSTEM_PARTITION);
+  const auto bitmask5 = PoliciesToBitmask({"system", "system", "system"});
+  ASSERT_TRUE(bitmask5);
+  ASSERT_EQ(*bitmask5, PolicyFlags::POLICY_SYSTEM_PARTITION);
 
-  const Result<PolicyBitmask> bitmask6 = PoliciesToBitmask({""}, std::cerr);
-  ASSERT_EQ(bitmask6, kResultError);
+  const auto bitmask6 = PoliciesToBitmask({""});
+  ASSERT_FALSE(bitmask6);
 
-  const Result<PolicyBitmask> bitmask7 = PoliciesToBitmask({"foo"}, std::cerr);
-  ASSERT_EQ(bitmask7, kResultError);
+  const auto bitmask7 = PoliciesToBitmask({"foo"});
+  ASSERT_FALSE(bitmask7);
 
-  const Result<PolicyBitmask> bitmask8 = PoliciesToBitmask({"system", "foo"}, std::cerr);
-  ASSERT_EQ(bitmask8, kResultError);
+  const auto bitmask8 = PoliciesToBitmask({"system", "foo"});
+  ASSERT_FALSE(bitmask8);
 
-  const Result<PolicyBitmask> bitmask9 = PoliciesToBitmask({"system", ""}, std::cerr);
-  ASSERT_EQ(bitmask9, kResultError);
+  const auto bitmask9 = PoliciesToBitmask({"system", ""});
+  ASSERT_FALSE(bitmask9);
 
-  const Result<PolicyBitmask> bitmask10 = PoliciesToBitmask({"system "}, std::cerr);
-  ASSERT_EQ(bitmask10, kResultError);
+  const auto bitmask10 = PoliciesToBitmask({"system "});
+  ASSERT_FALSE(bitmask10);
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/ResultTests.cpp b/cmds/idmap2/tests/ResultTests.cpp
index d82f0c4..5f4daed 100644
--- a/cmds/idmap2/tests/ResultTests.cpp
+++ b/cmds/idmap2/tests/ResultTests.cpp
@@ -32,28 +32,28 @@
 // Tests: Error
 
 TEST(ResultTests, ErrorTraits) {
-  ASSERT_TRUE(std::is_move_constructible<v2::Error>::value);
-  ASSERT_TRUE(std::is_move_assignable<v2::Error>::value);
-  ASSERT_TRUE(std::is_copy_constructible<v2::Error>::value);
-  ASSERT_TRUE(std::is_copy_assignable<v2::Error>::value);
+  ASSERT_TRUE(std::is_move_constructible<Error>::value);
+  ASSERT_TRUE(std::is_move_assignable<Error>::value);
+  ASSERT_TRUE(std::is_copy_constructible<Error>::value);
+  ASSERT_TRUE(std::is_copy_assignable<Error>::value);
 }
 
 TEST(ResultTests, ErrorCtorFormat) {
-  v2::Error e("%s=0x%08x", "resid", 0x7f010002);
+  Error e("%s=0x%08x", "resid", 0x7f010002);
   ASSERT_EQ(e.GetMessage(), "resid=0x7f010002");
 }
 
 TEST(ResultTests, ErrorPropagateParent) {
-  v2::Error e1("foo");
+  Error e1("foo");
   ASSERT_EQ(e1.GetMessage(), "foo");
 
-  v2::Error e2(e1, "bar");
+  Error e2(e1, "bar");
   ASSERT_EQ(e2.GetMessage(), "foo -> bar");
 
-  v2::Error e3(e2);  // NOLINT(performance-unnecessary-copy-initialization)
+  Error e3(e2);  // NOLINT(performance-unnecessary-copy-initialization)
   ASSERT_EQ(e3.GetMessage(), "foo -> bar");
 
-  v2::Error e4(e3, "%02d", 1);
+  Error e4(e3, "%02d", 1);
   ASSERT_EQ(e4.GetMessage(), "foo -> bar -> 01");
 }
 
@@ -61,13 +61,13 @@
 
 // Result(const Result&)
 TEST(ResultTests, CopyConstructor) {
-  v2::Result<uint32_t> r1(42U);
+  Result<uint32_t> r1(42U);
 
-  v2::Result<uint32_t> r2(r1);
+  Result<uint32_t> r2(r1);
   ASSERT_TRUE(r2);
   ASSERT_EQ(*r2, 42U);
 
-  v2::Result<uint32_t> r3 = r2;
+  Result<uint32_t> r3 = r2;
   ASSERT_TRUE(r3);
   ASSERT_EQ(*r3, 42U);
 }
@@ -75,23 +75,23 @@
 // Result(const T&)
 TEST(ResultTests, Constructor) {
   uint32_t v = 42U;
-  v2::Result<uint32_t> r1(v);
+  Result<uint32_t> r1(v);
   ASSERT_TRUE(r1);
   ASSERT_EQ(*r1, 42U);
 
-  v2::Error e("foo");
-  v2::Result<uint32_t> r2(e);
+  Error e("foo");
+  Result<uint32_t> r2(e);
   ASSERT_FALSE(r2);
   ASSERT_EQ(r2.GetErrorMessage(), "foo");
 }
 
 // Result(const T&&)
 TEST(ResultTests, MoveConstructor) {
-  v2::Result<uint32_t> r1(42U);
+  Result<uint32_t> r1(42U);
   ASSERT_TRUE(r1);
   ASSERT_EQ(*r1, 42U);
 
-  v2::Result<uint32_t> r2(v2::Error("foo"));
+  Result<uint32_t> r2(Error("foo"));
   ASSERT_FALSE(r2);
   ASSERT_EQ(r2.GetErrorMessage(), "foo");
 }
@@ -99,52 +99,52 @@
 // operator=
 TEST(ResultTests, CopyAssignmentOperator) {
   // note: 'Result<...> r2 = r1;' calls the copy ctor
-  v2::Result<uint32_t> r1(42U);
-  v2::Result<uint32_t> r2(0U);
+  Result<uint32_t> r1(42U);
+  Result<uint32_t> r2(0U);
   r2 = r1;
   ASSERT_TRUE(r2);
   ASSERT_EQ(*r2, 42U);
 
-  v2::Result<uint32_t> r3(v2::Error("foo"));
+  Result<uint32_t> r3(Error("foo"));
   r2 = r3;
   ASSERT_FALSE(r2);
   ASSERT_EQ(r2.GetErrorMessage(), "foo");
 }
 
 TEST(ResultTests, MoveAssignmentOperator) {
-  v2::Result<uint32_t> r(0U);
-  r = v2::Result<uint32_t>(42U);
+  Result<uint32_t> r(0U);
+  r = Result<uint32_t>(42U);
   ASSERT_TRUE(r);
   ASSERT_EQ(*r, 42U);
 
-  r = v2::Result<uint32_t>(v2::Error("foo"));
+  r = Result<uint32_t>(Error("foo"));
   ASSERT_FALSE(r);
   ASSERT_EQ(r.GetErrorMessage(), "foo");
 }
 
 // operator bool()
 TEST(ResultTests, BoolOperator) {
-  v2::Result<uint32_t> r1(42U);
+  Result<uint32_t> r1(42U);
   ASSERT_TRUE(r1);
   ASSERT_EQ(*r1, 42U);
 
-  v2::Result<uint32_t> r2(v2::Error("foo"));
+  Result<uint32_t> r2(Error("foo"));
   ASSERT_FALSE(r2);
   ASSERT_EQ(r2.GetErrorMessage(), "foo");
 }
 
 // operator*
 TEST(ResultTests, IndirectionOperator) {
-  const v2::Result<uint32_t> r1(42U);
+  const Result<uint32_t> r1(42U);
   ASSERT_TRUE(r1);
   ASSERT_EQ(*r1, 42U);
 
-  const v2::Result<Container> r2(Container{42U});
+  const Result<Container> r2(Container{42U});
   ASSERT_TRUE(r2);
   const Container& c = *r2;
   ASSERT_EQ(c.value, 42U);
 
-  v2::Result<Container> r3(Container{42U});
+  Result<Container> r3(Container{42U});
   ASSERT_TRUE(r3);
   ASSERT_EQ((*r3).value, 42U);
   (*r3).value = 0U;
@@ -153,11 +153,11 @@
 
 // operator->
 TEST(ResultTests, DereferenceOperator) {
-  const v2::Result<Container> r1(Container{42U});
+  const Result<Container> r1(Container{42U});
   ASSERT_TRUE(r1);
   ASSERT_EQ(r1->value, 42U);
 
-  v2::Result<Container> r2(Container{42U});
+  Result<Container> r2(Container{42U});
   ASSERT_TRUE(r2);
   ASSERT_EQ(r2->value, 42U);
   r2->value = 0U;
@@ -167,14 +167,14 @@
 // Tests: intended use of Result<T>
 
 TEST(ResultTests, ResultTraits) {
-  ASSERT_TRUE(std::is_move_constructible<v2::Result<uint32_t>>::value);
-  ASSERT_TRUE(std::is_move_assignable<v2::Result<uint32_t>>::value);
-  ASSERT_TRUE(std::is_copy_constructible<v2::Result<uint32_t>>::value);
-  ASSERT_TRUE(std::is_copy_assignable<v2::Result<uint32_t>>::value);
+  ASSERT_TRUE(std::is_move_constructible<Result<uint32_t>>::value);
+  ASSERT_TRUE(std::is_move_assignable<Result<uint32_t>>::value);
+  ASSERT_TRUE(std::is_copy_constructible<Result<uint32_t>>::value);
+  ASSERT_TRUE(std::is_copy_assignable<Result<uint32_t>>::value);
 }
 
 TEST(ResultTests, UnitTypeResult) {
-  v2::Result<v2::Unit> r(v2::Unit{});
+  Result<Unit> r(Unit{});
   ASSERT_TRUE(r);
 }
 
@@ -220,16 +220,16 @@
   ASSERT_FALSE(std::is_copy_assignable<RefCountContainer>::value);
 
   RefCountData rc{0, 0, 0, 0};
-  { v2::Result<RefCountContainer> r(RefCountContainer{rc}); }
+  { Result<RefCountContainer> r(RefCountContainer{rc}); }
   ASSERT_EQ(rc.ctor, 1);
   ASSERT_EQ(rc.copy_ctor, 1);
   ASSERT_EQ(rc.move, 0);
   ASSERT_EQ(rc.dtor, 2);
 }
 
-v2::Result<Container> CreateContainer(bool succeed) {
+Result<Container> CreateContainer(bool succeed) {
   if (!succeed) {
-    return v2::Error("foo");
+    return Error("foo");
   }
   return Container{42U};
 }
@@ -245,10 +245,10 @@
   ASSERT_EQ(r2.GetError().GetMessage(), "foo");
 }
 
-v2::Result<Container> FailToCreateContainer() {
+Result<Container> FailToCreateContainer() {
   auto container = CreateContainer(false);
   if (!container) {
-    return v2::Error(container.GetError(), "bar");
+    return Error(container.GetError(), "bar");
   }
   return container;
 }
@@ -264,9 +264,9 @@
   DISALLOW_COPY_AND_ASSIGN(NoCopyContainer);
 };
 
-v2::Result<std::unique_ptr<NoCopyContainer>> CreateNoCopyContainer(bool succeed) {
+Result<std::unique_ptr<NoCopyContainer>> CreateNoCopyContainer(bool succeed) {
   if (!succeed) {
-    return v2::Error("foo");
+    return Error("foo");
   }
   std::unique_ptr<NoCopyContainer> p(new NoCopyContainer{0U});
   p->value = 42U;
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
index 0c861cf..a077745 100644
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -196,7 +196,7 @@
             int repeatCount = 0;
 
             KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, repeatCount,
-                    0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0/*flags*/,
+                    0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
                     inputSource);
             event.setDisplayId(displayId);
 
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index be5a5bf..4a6f87f 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -103,6 +103,8 @@
             runSetVirtualDisk();
         } else if ("set-isolated-storage".equals(op)) {
             runIsolatedStorage();
+        } else if ("set-legacy-greylist".equals(op)) {
+            runLegacyGreylist();
         } else {
             throw new IllegalArgumentException();
         }
@@ -282,7 +284,7 @@
                 StorageManager.DEBUG_VIRTUAL_DISK);
     }
 
-    public void runIsolatedStorage() {
+    public void runIsolatedStorage() throws RemoteException {
         final int value;
         final int mask = StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
                 | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF;
@@ -301,16 +303,13 @@
             default:
                 return;
         }
+        mSm.setDebugFlags(value, mask);
+    }
 
-        // Toggling isolated-storage state will result in a device reboot. So to avoid this command
-        // from erroring out (DeadSystemException), call setDebugFlags() in a separate thread.
-        new Thread(() -> {
-            try {
-                mSm.setDebugFlags(value, mask);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Encountered an error!", e);
-            }
-        }).start();
+    public void runLegacyGreylist() throws RemoteException {
+        final boolean legacyGreylist = Boolean.parseBoolean(nextArg());
+        mSm.setDebugFlags(legacyGreylist ? StorageManager.DEBUG_LEGACY_GREYLIST : 0,
+                StorageManager.DEBUG_LEGACY_GREYLIST);
     }
 
     public void runIdleMaint() throws RemoteException {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index de42398..b647400 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 {
@@ -5516,8 +5528,9 @@
     optional com.android.server.job.ConstraintEnum constraint = 3;
 
     enum State {
-        UNSATISFIED = 0;
-        SATISFIED = 1;
+        UNKNOWN = 0;
+        UNSATISFIED = 1;
+        SATISFIED = 2;
     }
     optional State state = 4;
 }
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 99cb5d4..046f996 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -69,7 +69,7 @@
           mTimeBaseNs(timeBaseNs),
           mCurrentBucketStartTimeNs(timeBaseNs),
           mCurrentBucketNum(0),
-          mCondition(conditionIndex >= 0 ? ConditionState::kUnknown : ConditionState::kTrue),
+          mCondition(initialCondition(conditionIndex)),
           mConditionSliced(false),
           mWizard(wizard),
           mConditionTrackerIndex(conditionIndex),
@@ -82,6 +82,10 @@
 
     virtual ~MetricProducer(){};
 
+    ConditionState initialCondition(const int conditionIndex) const {
+        return conditionIndex >= 0 ? ConditionState::kUnknown : ConditionState::kTrue;
+    }
+
     /**
      * Forces this metric to split into a partial bucket right now. If we're past a full bucket, we
      * first call the standard flushing code to flush up to the latest full bucket. Then we call
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 9de62a2..27ee570 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -394,7 +394,7 @@
         invalidateCurrentBucket();
         // Something weird happened. If we received another event if the future, the condition might
         // be wrong.
-        mCondition = ConditionState::kUnknown;
+        mCondition = initialCondition(mConditionTrackerIndex);
     }
 
     // This part should alway be called.
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index e25f463..07fba3b 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -437,7 +437,6 @@
 Landroid/content/res/ConfigurationBoundResourceCache;-><init>()V
 Landroid/content/res/DrawableCache;-><init>()V
 Landroid/content/UndoManager;-><init>()V
-Landroid/database/BulkCursorProxy;->mRemote:Landroid/os/IBinder;
 Landroid/database/IContentObserver$Stub;-><init>()V
 Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver;
 Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V
@@ -446,16 +445,13 @@
 Landroid/filterfw/GraphEnvironment;->addReferences([Ljava/lang/Object;)V
 Landroid/hardware/camera2/utils/HashCodeHelpers;->hashCode([I)I
 Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager;
-Landroid/hardware/display/IDisplayManager;->getDisplayInfo(I)Landroid/view/DisplayInfo;
 Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/fingerprint/IFingerprintService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/fingerprint/IFingerprintService;
 Landroid/hardware/ICameraService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/ICameraService;
 Landroid/hardware/input/IInputManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager;
 Landroid/hardware/input/IInputManager$Stub;->TRANSACTION_injectInputEvent:I
-Landroid/hardware/input/IInputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z
 Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
-Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V
 Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
 Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
@@ -465,60 +461,33 @@
 Landroid/location/ICountryListener$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/IGeocodeProvider;
-Landroid/location/IGeocodeProvider;->getFromLocation(DDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
-Landroid/location/IGeocodeProvider;->getFromLocationName(Ljava/lang/String;DDDDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
 Landroid/location/IGeofenceProvider$Stub;-><init>()V
-Landroid/location/IGeofenceProvider;->setGeofenceHardware(Landroid/hardware/location/IGeofenceHardware;)V
 Landroid/location/ILocationListener$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/location/ILocationListener$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/location/ILocationListener$Stub;-><init>()V
 Landroid/location/ILocationListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationListener;
-Landroid/location/ILocationListener;->onLocationChanged(Landroid/location/Location;)V
-Landroid/location/ILocationListener;->onProviderDisabled(Ljava/lang/String;)V
-Landroid/location/ILocationListener;->onProviderEnabled(Ljava/lang/String;)V
-Landroid/location/ILocationListener;->onStatusChanged(Ljava/lang/String;ILandroid/os/Bundle;)V
 Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
 Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
-Landroid/location/ILocationManager;->getAllProviders()Ljava/util/List;
 Landroid/location/INetInitiatedListener$Stub;-><init>()V
-Landroid/location/INetInitiatedListener;->sendNiResponse(II)Z
 Landroid/location/LocationManager$ListenerTransport;-><init>(Landroid/location/LocationManager;Landroid/location/LocationListener;Landroid/os/Looper;)V
 Landroid/Manifest$permission;->CAPTURE_SECURE_VIDEO_OUTPUT:Ljava/lang/String;
 Landroid/Manifest$permission;->CAPTURE_VIDEO_OUTPUT:Ljava/lang/String;
 Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String;
 Landroid/media/effect/SingleFilterEffect;-><init>(Landroid/media/effect/EffectContext;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
-Landroid/media/IAudioFocusDispatcher;->dispatchAudioFocusChange(ILjava/lang/String;)V
 Landroid/media/IAudioRoutesObserver$Stub;-><init>()V
 Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/media/IAudioService$Stub;-><init>()V
 Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IAudioService;
-Landroid/media/IAudioService;->getStreamMaxVolume(I)I
-Landroid/media/IAudioService;->getStreamVolume(I)I
-Landroid/media/IAudioService;->setStreamVolume(IIILjava/lang/String;)V
-Landroid/media/IAudioService;->startWatchingRoutes(Landroid/media/IAudioRoutesObserver;)Landroid/media/AudioRoutesInfo;
 Landroid/media/IMediaRouterService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaRouterService;
 Landroid/media/IMediaScannerListener$Stub;-><init>()V
 Landroid/media/IMediaScannerService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaScannerService;
-Landroid/media/IMediaScannerService;->requestScanFile(Ljava/lang/String;Ljava/lang/String;Landroid/media/IMediaScannerListener;)V
-Landroid/media/IMediaScannerService;->scanFile(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/media/IRemoteDisplayCallback;->onStateChanged(Landroid/media/RemoteDisplayState;)V
 Landroid/media/IRingtonePlayer;->play(Landroid/os/IBinder;Landroid/net/Uri;Landroid/media/AudioAttributes;FZ)V
 Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
 Landroid/media/MediaFile;-><init>()V
 Landroid/media/MediaScanner$MyMediaScannerClient;-><init>(Landroid/media/MediaScanner;)V
-Landroid/media/projection/IMediaProjectionManager;->hasProjectionPermission(ILjava/lang/String;)Z
 Landroid/media/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager;
 Landroid/media/tv/ITvRemoteProvider$Stub;-><init>()V
-Landroid/media/tv/ITvRemoteServiceInput;->clearInputBridge(Landroid/os/IBinder;)V
-Landroid/media/tv/ITvRemoteServiceInput;->closeInputBridge(Landroid/os/IBinder;)V
-Landroid/media/tv/ITvRemoteServiceInput;->openInputBridge(Landroid/os/IBinder;Ljava/lang/String;III)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendKeyDown(Landroid/os/IBinder;I)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendKeyUp(Landroid/os/IBinder;I)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendPointerDown(Landroid/os/IBinder;III)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendPointerSync(Landroid/os/IBinder;)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendPointerUp(Landroid/os/IBinder;I)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendTimestamp(Landroid/os/IBinder;J)V
 Landroid/net/ConnectivityManager$PacketKeepaliveCallback;-><init>()V
 Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveLinkProperties()Landroid/net/LinkProperties;
@@ -530,41 +499,13 @@
 Landroid/net/IConnectivityManager$Stub$Proxy;->getTetheredIfaces()[Ljava/lang/String;
 Landroid/net/IConnectivityManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/net/IConnectivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IConnectivityManager;
-Landroid/net/IConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties;
-Landroid/net/IConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo;
-Landroid/net/IConnectivityManager;->getAllNetworkInfo()[Landroid/net/NetworkInfo;
-Landroid/net/IConnectivityManager;->getAllNetworkState()[Landroid/net/NetworkState;
-Landroid/net/IConnectivityManager;->getLastTetherError(Ljava/lang/String;)I
-Landroid/net/IConnectivityManager;->getTetherableIfaces()[Ljava/lang/String;
-Landroid/net/IConnectivityManager;->getTetherableUsbRegexs()[Ljava/lang/String;
-Landroid/net/IConnectivityManager;->getTetherableWifiRegexs()[Ljava/lang/String;
-Landroid/net/IConnectivityManager;->getTetheredIfaces()[Ljava/lang/String;
-Landroid/net/IConnectivityManager;->getTetheringErroredIfaces()[Ljava/lang/String;
-Landroid/net/IConnectivityManager;->startLegacyVpn(Lcom/android/internal/net/VpnProfile;)V
 Landroid/net/INetworkManagementEventObserver$Stub;-><init>()V
 Landroid/net/INetworkPolicyListener$Stub;-><init>()V
 Landroid/net/INetworkPolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkPolicyManager;
-Landroid/net/INetworkPolicyManager;->getNetworkQuotaInfo(Landroid/net/NetworkState;)Landroid/net/NetworkQuotaInfo;
-Landroid/net/INetworkPolicyManager;->getRestrictBackground()Z
-Landroid/net/INetworkPolicyManager;->getUidPolicy(I)I
-Landroid/net/INetworkPolicyManager;->setNetworkPolicies([Landroid/net/NetworkPolicy;)V
-Landroid/net/INetworkPolicyManager;->setRestrictBackground(Z)V
-Landroid/net/INetworkPolicyManager;->setUidPolicy(II)V
-Landroid/net/INetworkPolicyManager;->snoozeLimit(Landroid/net/NetworkTemplate;)V
 Landroid/net/INetworkScoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkScoreService;
 Landroid/net/INetworkStatsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String;
 Landroid/net/INetworkStatsService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsService;
-Landroid/net/INetworkStatsService;->forceUpdate()V
-Landroid/net/INetworkStatsService;->getDataLayerSnapshotForUid(I)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsService;->getMobileIfaces()[Ljava/lang/String;
-Landroid/net/INetworkStatsService;->openSession()Landroid/net/INetworkStatsSession;
-Landroid/net/INetworkStatsService;->openSessionForUsageStats(ILjava/lang/String;)Landroid/net/INetworkStatsSession;
-Landroid/net/INetworkStatsSession;->close()V
-Landroid/net/INetworkStatsSession;->getHistoryForNetwork(Landroid/net/NetworkTemplate;I)Landroid/net/NetworkStatsHistory;
-Landroid/net/INetworkStatsSession;->getHistoryForUid(Landroid/net/NetworkTemplate;IIII)Landroid/net/NetworkStatsHistory;
-Landroid/net/INetworkStatsSession;->getSummaryForAllUid(Landroid/net/NetworkTemplate;JJZ)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsSession;->getSummaryForNetwork(Landroid/net/NetworkTemplate;JJ)Landroid/net/NetworkStats;
 Landroid/net/InterfaceConfiguration;-><init>()V
 Landroid/net/LinkProperties$ProvisioningChange;->values()[Landroid/net/LinkProperties$ProvisioningChange;
 Landroid/net/MobileLinkQualityInfo;-><init>()V
@@ -575,22 +516,12 @@
 Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
 Landroid/net/wifi/IWifiManager$Stub;->TRANSACTION_getScanResults:I
-Landroid/net/wifi/IWifiManager;->getCurrentNetwork()Landroid/net/Network;
-Landroid/net/wifi/IWifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration;
-Landroid/net/wifi/IWifiManager;->getWifiApEnabledState()I
 Landroid/net/wifi/IWifiScanner$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/wifi/IWifiScanner$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/net/wifi/IWifiScanner$Stub;-><init>()V
 Landroid/net/wifi/IWifiScanner$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiScanner;
 Landroid/net/wifi/p2p/IWifiP2pManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/p2p/IWifiP2pManager;
 Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
-Landroid/nfc/INfcAdapterExtras;->authenticate(Ljava/lang/String;[B)V
-Landroid/nfc/INfcAdapterExtras;->close(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle;
-Landroid/nfc/INfcAdapterExtras;->getCardEmulationRoute(Ljava/lang/String;)I
-Landroid/nfc/INfcAdapterExtras;->getDriverName(Ljava/lang/String;)Ljava/lang/String;
-Landroid/nfc/INfcAdapterExtras;->open(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle;
-Landroid/nfc/INfcAdapterExtras;->setCardEmulationRoute(Ljava/lang/String;I)V
-Landroid/nfc/INfcAdapterExtras;->transceive(Ljava/lang/String;[B)Landroid/os/Bundle;
 Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V
 Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable;
 Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;)Landroid/os/AsyncResult;
@@ -1360,9 +1291,7 @@
 Landroid/R$styleable;->Window:[I
 Landroid/R$styleable;->Window_windowBackground:I
 Landroid/R$styleable;->Window_windowFrame:I
-Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
 Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
-Landroid/security/IKeyChainService;->requestPrivateKey(Ljava/lang/String;)Ljava/lang/String;
 Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
 Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
 Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
@@ -1391,29 +1320,12 @@
 Landroid/service/dreams/IDreamManager;->getDreamComponents()[Landroid/content/ComponentName;
 Landroid/service/dreams/IDreamManager;->isDreaming()Z
 Landroid/service/dreams/IDreamManager;->setDreamComponents([Landroid/content/ComponentName;)V
-Landroid/service/euicc/IDeleteSubscriptionCallback;->onComplete(I)V
-Landroid/service/euicc/IEraseSubscriptionsCallback;->onComplete(I)V
 Landroid/service/euicc/IEuiccService$Stub;-><init>()V
-Landroid/service/euicc/IGetDefaultDownloadableSubscriptionListCallback;->onComplete(Landroid/service/euicc/GetDefaultDownloadableSubscriptionListResult;)V
-Landroid/service/euicc/IGetDownloadableSubscriptionMetadataCallback;->onComplete(Landroid/service/euicc/GetDownloadableSubscriptionMetadataResult;)V
-Landroid/service/euicc/IGetEidCallback;->onSuccess(Ljava/lang/String;)V
-Landroid/service/euicc/IGetEuiccInfoCallback;->onSuccess(Landroid/telephony/euicc/EuiccInfo;)V
-Landroid/service/euicc/IGetEuiccProfileInfoListCallback;->onComplete(Landroid/service/euicc/GetEuiccProfileInfoListResult;)V
-Landroid/service/euicc/IRetainSubscriptionsForFactoryResetCallback;->onComplete(I)V
-Landroid/service/euicc/ISwitchToSubscriptionCallback;->onComplete(I)V
-Landroid/service/euicc/IUpdateSubscriptionNicknameCallback;->onComplete(I)V
 Landroid/service/notification/INotificationListener$Stub;-><init>()V
 Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService;
 Landroid/service/vr/IVrManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/vr/IVrManager;
-Landroid/service/vr/IVrManager;->getVr2dDisplayId()I
-Landroid/service/vr/IVrManager;->getVrModeState()Z
 Landroid/service/wallpaper/IWallpaperConnection$Stub;-><init>()V
-Landroid/service/wallpaper/IWallpaperEngine;->destroy()V
-Landroid/service/wallpaper/IWallpaperEngine;->dispatchPointer(Landroid/view/MotionEvent;)V
-Landroid/service/wallpaper/IWallpaperEngine;->dispatchWallpaperCommand(Ljava/lang/String;IIILandroid/os/Bundle;)V
-Landroid/service/wallpaper/IWallpaperEngine;->setVisibility(Z)V
 Landroid/service/wallpaper/IWallpaperService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/wallpaper/IWallpaperService;
-Landroid/speech/IRecognitionListener;->onEvent(ILandroid/os/Bundle;)V
 Landroid/telecom/Log;->i(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
 Landroid/telecom/Log;->w(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
 Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V
@@ -1424,10 +1336,6 @@
 Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V
 Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V
 Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService;
-Landroid/telephony/mbms/vendor/IMbmsStreamingService;->getPlaybackUri(ILjava/lang/String;)Landroid/net/Uri;
-Landroid/telephony/mbms/vendor/IMbmsStreamingService;->initialize(Landroid/telephony/mbms/IMbmsStreamingSessionCallback;I)I
-Landroid/telephony/mbms/vendor/IMbmsStreamingService;->requestUpdateStreamingServices(ILjava/util/List;)I
-Landroid/telephony/mbms/vendor/IMbmsStreamingService;->startStreaming(ILjava/lang/String;Landroid/telephony/mbms/IStreamingServiceCallback;)I
 Landroid/telephony/SmsCbCmasInfo;->getCategory()I
 Landroid/telephony/SmsCbCmasInfo;->getCertainty()I
 Landroid/telephony/SmsCbCmasInfo;->getMessageClass()I
@@ -1470,17 +1378,8 @@
 Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager;
 Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V
 Landroid/view/IDockedStackListener$Stub;-><init>()V
-Landroid/view/IRecentsAnimationController;->finish(Z)V
-Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot;
-Landroid/view/IRecentsAnimationController;->setAnimationTargetsBehindSystemBars(Z)V
-Landroid/view/IRecentsAnimationController;->setInputConsumerEnabled(Z)V
 Landroid/view/IRecentsAnimationRunner$Stub;-><init>()V
-Landroid/view/IRecentsAnimationRunner;->onAnimationCanceled()V
-Landroid/view/IRecentsAnimationRunner;->onAnimationStart(Landroid/view/IRecentsAnimationController;[Landroid/view/RemoteAnimationTarget;Landroid/graphics/Rect;Landroid/graphics/Rect;)V
-Landroid/view/IRemoteAnimationFinishedCallback;->onAnimationFinished()V
 Landroid/view/IRemoteAnimationRunner$Stub;-><init>()V
-Landroid/view/IRemoteAnimationRunner;->onAnimationCancelled()V
-Landroid/view/IRemoteAnimationRunner;->onAnimationStart([Landroid/view/RemoteAnimationTarget;Landroid/view/IRemoteAnimationFinishedCallback;)V
 Landroid/view/IRotationWatcher$Stub;-><init>()V
 Landroid/view/IWindow$Stub;-><init>()V
 Landroid/view/IWindow$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindow;
@@ -1492,44 +1391,7 @@
 Landroid/view/IWindowManager$Stub$Proxy;->watchRotation(Landroid/view/IRotationWatcher;I)I
 Landroid/view/IWindowManager$Stub;-><init>()V
 Landroid/view/IWindowManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowManager;
-Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;ILandroid/view/InputChannel;)V
-Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;I)Z
-Landroid/view/IWindowManager;->endProlongedAnimations()V
-Landroid/view/IWindowManager;->executeAppTransition()V
-Landroid/view/IWindowManager;->freezeRotation(I)V
-Landroid/view/IWindowManager;->getAnimationScale(I)F
-Landroid/view/IWindowManager;->getAnimationScales()[F
-Landroid/view/IWindowManager;->getBaseDisplaySize(ILandroid/graphics/Point;)V
-Landroid/view/IWindowManager;->getDockedStackSide()I
-Landroid/view/IWindowManager;->getInitialDisplayDensity(I)I
-Landroid/view/IWindowManager;->getInitialDisplaySize(ILandroid/graphics/Point;)V
-Landroid/view/IWindowManager;->getStableInsets(ILandroid/graphics/Rect;)V
-Landroid/view/IWindowManager;->hasNavigationBar(I)Z
-Landroid/view/IWindowManager;->isKeyguardLocked()Z
-Landroid/view/IWindowManager;->isKeyguardSecure()Z
-Landroid/view/IWindowManager;->isSafeModeEnabled()Z
-Landroid/view/IWindowManager;->lockNow(Landroid/os/Bundle;)V
-Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;ZI)V
-Landroid/view/IWindowManager;->overridePendingAppTransitionRemote(Landroid/view/RemoteAnimationAdapter;I)V
-Landroid/view/IWindowManager;->registerDockedStackListener(Landroid/view/IDockedStackListener;)V
-Landroid/view/IWindowManager;->removeRotationWatcher(Landroid/view/IRotationWatcher;)V
-Landroid/view/IWindowManager;->setAnimationScale(IF)V
-Landroid/view/IWindowManager;->setAnimationScales([F)V
-Landroid/view/IWindowManager;->setNavBarVirtualKeyHapticFeedbackEnabled(Z)V
-Landroid/view/IWindowManager;->setShelfHeight(ZI)V
-Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V
-Landroid/view/IWindowManager;->thawRotation()V
 Landroid/view/IWindowSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowSession;
-Landroid/view/IWindowSession;->finishDrawing(Landroid/view/IWindow;)V
-Landroid/view/IWindowSession;->getInTouchMode()Z
-Landroid/view/IWindowSession;->performDrag(Landroid/view/IWindow;ILandroid/view/SurfaceControl;IFFFFLandroid/content/ClipData;)Landroid/os/IBinder;
-Landroid/view/IWindowSession;->performHapticFeedback(IZ)Z
-Landroid/view/IWindowSession;->remove(Landroid/view/IWindow;)V
-Landroid/view/IWindowSession;->setInTouchMode(Z)V
-Landroid/view/IWindowSession;->setTransparentRegion(Landroid/view/IWindow;Landroid/graphics/Region;)V
-Landroid/view/IWindowSession;->wallpaperCommandComplete(Landroid/os/IBinder;Landroid/os/Bundle;)V
-Landroid/view/IWindowSession;->wallpaperOffsetsComplete(Landroid/os/IBinder;)V
-Landroid/view/RenderNodeAnimator;->setDuration(J)Landroid/view/RenderNodeAnimator;
 Landroid/view/View$AttachInfo$InvalidateInfo;-><init>()V
 Landroid/view/View$CheckForLongPress;-><init>(Landroid/view/View;)V
 Landroid/view/View$ListenerInfo;-><init>()V
@@ -1538,9 +1400,6 @@
 Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/webkit/IWebViewUpdateService$Stub$Proxy;->waitForAndGetProvider()Landroid/webkit/WebViewProviderResponse;
 Landroid/webkit/IWebViewUpdateService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/webkit/IWebViewUpdateService;
-Landroid/webkit/IWebViewUpdateService;->getCurrentWebViewPackageName()Ljava/lang/String;
-Landroid/webkit/IWebViewUpdateService;->getValidWebViewPackages()[Landroid/webkit/WebViewProviderInfo;
-Landroid/webkit/IWebViewUpdateService;->isFallbackPackage(Ljava/lang/String;)Z
 Landroid/widget/DigitalClock$FormatChangeObserver;-><init>(Landroid/widget/DigitalClock;)V
 Landroid/widget/QuickContactBadge$QueryHandler;-><init>(Landroid/widget/QuickContactBadge;Landroid/content/ContentResolver;)V
 Landroid/widget/RelativeLayout$DependencyGraph$Node;-><init>()V
@@ -1550,7 +1409,6 @@
 Lcom/android/ims/ImsCall;->reject(I)V
 Lcom/android/ims/ImsCall;->terminate(I)V
 Lcom/android/ims/ImsConfigListener$Stub;-><init>()V
-Lcom/android/ims/ImsConfigListener;->onSetFeatureResponse(IIII)V
 Lcom/android/ims/ImsEcbm;->exitEmergencyCallbackMode()V
 Lcom/android/ims/ImsManager;->getConfigInterface()Lcom/android/ims/ImsConfig;
 Lcom/android/ims/ImsManager;->getInstance(Landroid/content/Context;I)Lcom/android/ims/ImsManager;
@@ -1560,104 +1418,17 @@
 Lcom/android/ims/ImsUtInterface;->queryCallForward(ILjava/lang/String;Landroid/os/Message;)V
 Lcom/android/ims/internal/IImsCallSession$Stub;-><init>()V
 Lcom/android/ims/internal/IImsCallSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsCallSession;
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionConferenceStateUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsConferenceState;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandover(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandoverFailed(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHeld(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestDelivered(Lcom/android/ims/internal/IImsCallSession;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeComplete(Lcom/android/ims/internal/IImsCallSession;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeStarted(Lcom/android/ims/internal/IImsCallSession;Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMultipartyStateChanged(Lcom/android/ims/internal/IImsCallSession;Z)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionProgressing(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsStreamMediaProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStarted(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStartFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionSuppServiceReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsSuppServiceNotification;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTerminated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTtyModeReceived(Lcom/android/ims/internal/IImsCallSession;I)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
 Lcom/android/ims/internal/IImsConfig$Stub;-><init>()V
 Lcom/android/ims/internal/IImsEcbm$Stub;-><init>()V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationAssociatedUriChanged([Landroid/net/Uri;)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationChangeFailed(ILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationConnected()V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationConnectedWithRadioTech(I)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationDisconnected(Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationFeatureCapabilityChanged(I[I[I)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationProgressingWithRadioTech(I)V
-Lcom/android/ims/internal/IImsRegistrationListener;->voiceMessageCountUpdate(I)V
 Lcom/android/ims/internal/IImsService$Stub;-><init>()V
 Lcom/android/ims/internal/IImsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsService;
 Lcom/android/ims/internal/IImsUt$Stub;-><init>()V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallBarringQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallForwardQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsCallForwardInfo;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallWaitingQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueried(Lcom/android/ims/internal/IImsUt;ILandroid/os/Bundle;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueryFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdated(Lcom/android/ims/internal/IImsUt;I)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdateFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsVideoCallCallback;->changeCallDataUsage(J)V
-Lcom/android/ims/internal/IImsVideoCallCallback;->changeCameraCapabilities(Landroid/telecom/VideoProfile$CameraCapabilities;)V
-Lcom/android/ims/internal/IImsVideoCallCallback;->changePeerDimensions(II)V
-Lcom/android/ims/internal/IImsVideoCallCallback;->changeVideoQuality(I)V
-Lcom/android/ims/internal/IImsVideoCallCallback;->handleCallSessionEvent(I)V
-Lcom/android/ims/internal/IImsVideoCallCallback;->receiveSessionModifyRequest(Landroid/telecom/VideoProfile;)V
-Lcom/android/ims/internal/IImsVideoCallCallback;->receiveSessionModifyResponse(ILandroid/telecom/VideoProfile;Landroid/telecom/VideoProfile;)V
 Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V
-Lcom/android/ims/internal/IImsVideoCallProvider;->setCallback(Lcom/android/ims/internal/IImsVideoCallCallback;)V
 Lcom/android/ims/internal/ImsVideoCallProviderWrapper;-><init>(Lcom/android/ims/internal/IImsVideoCallProvider;)V
-Lcom/android/ims/internal/uce/options/IOptionsListener;->cmdStatus(Lcom/android/ims/internal/uce/options/OptionsCmdStatus;)V
-Lcom/android/ims/internal/uce/options/IOptionsListener;->getVersionCb(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/options/IOptionsListener;->incomingOptions(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;I)V
-Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceUnavailable(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/options/IOptionsListener;->sipResponseReceived(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsSipResponse;Lcom/android/ims/internal/uce/options/OptionsCapInfo;)V
 Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V
-Lcom/android/ims/internal/uce/options/IOptionsService;->addListener(ILcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->getMyInfo(II)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->responseIncomingOptions(IIILjava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;Z)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->setMyInfo(ILcom/android/ims/internal/uce/common/CapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->capInfoReceived(Ljava/lang/String;[Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->cmdStatus(Lcom/android/ims/internal/uce/presence/PresCmdStatus;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->getVersionCb(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->listCapInfoReceived(Lcom/android/ims/internal/uce/presence/PresRlmiInfo;[Lcom/android/ims/internal/uce/presence/PresResInfo;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->publishTriggering(Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceUnAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->sipResponseReceived(Lcom/android/ims/internal/uce/presence/PresSipResponse;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->unpublishMessageSent()V
 Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V
-Lcom/android/ims/internal/uce/presence/IPresenceService;->addListener(ILcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->publishMyCap(ILcom/android/ims/internal/uce/presence/PresCapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->reenableService(II)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->setNewFeatureTag(ILjava/lang/String;Lcom/android/ims/internal/uce/presence/PresServiceInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
-Lcom/android/ims/internal/uce/uceservice/IUceListener;->setStatus(I)V
 Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V
-Lcom/android/ims/internal/uce/uceservice/IUceService;->createOptionsService(Lcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)I
-Lcom/android/ims/internal/uce/uceservice/IUceService;->createPresenceService(Lcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)I
-Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyOptionsService(I)V
-Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyPresenceService(I)V
-Lcom/android/ims/internal/uce/uceservice/IUceService;->getOptionsService()Lcom/android/ims/internal/uce/options/IOptionsService;
-Lcom/android/ims/internal/uce/uceservice/IUceService;->getPresenceService()Lcom/android/ims/internal/uce/presence/IPresenceService;
-Lcom/android/ims/internal/uce/uceservice/IUceService;->getServiceStatus()Z
-Lcom/android/ims/internal/uce/uceservice/IUceService;->isServiceStarted()Z
-Lcom/android/ims/internal/uce/uceservice/IUceService;->startService(Lcom/android/ims/internal/uce/uceservice/IUceListener;)Z
-Lcom/android/ims/internal/uce/uceservice/IUceService;->stopService()Z
 Lcom/android/internal/app/AlertActivity;-><init>()V
 Lcom/android/internal/app/AlertActivity;->mAlert:Lcom/android/internal/app/AlertController;
 Lcom/android/internal/app/AlertActivity;->mAlertParams:Lcom/android/internal/app/AlertController$AlertParams;
@@ -1688,22 +1459,12 @@
 Lcom/android/internal/app/IAppOpsService$Stub;->TRANSACTION_startOperation:I
 Lcom/android/internal/app/IAppOpsService$Stub;->TRANSACTION_startWatchingMode:I
 Lcom/android/internal/app/IAppOpsService$Stub;->TRANSACTION_stopWatchingMode:I
-Lcom/android/internal/app/IAppOpsService;->finishOperation(Landroid/os/IBinder;IILjava/lang/String;)V
-Lcom/android/internal/app/IAppOpsService;->getOpsForPackage(ILjava/lang/String;[I)Ljava/util/List;
-Lcom/android/internal/app/IAppOpsService;->getPackagesForOps([I)Ljava/util/List;
-Lcom/android/internal/app/IAppOpsService;->resetAllModes(ILjava/lang/String;)V
-Lcom/android/internal/app/IAppOpsService;->setMode(IILjava/lang/String;I)V
 Lcom/android/internal/app/IBatteryStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/app/IBatteryStats$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IBatteryStats;
-Lcom/android/internal/app/IBatteryStats;->computeChargeTimeRemaining()J
-Lcom/android/internal/app/IBatteryStats;->getAwakeTimeBattery()J
-Lcom/android/internal/app/IBatteryStats;->getStatistics()[B
-Lcom/android/internal/app/IBatteryStats;->isCharging()Z
 Lcom/android/internal/app/IMediaContainerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IMediaContainerService;
 Lcom/android/internal/app/IntentForwarderActivity;->TAG:Ljava/lang/String;
 Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
 Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
-Lcom/android/internal/app/IVoiceInteractionManagerService;->getKeyphraseSoundModel(ILjava/lang/String;)Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;
 Lcom/android/internal/app/LocaleHelper$LocaleInfoComparator;-><init>(Ljava/util/Locale;Z)V
 Lcom/android/internal/app/LocaleHelper$LocaleInfoComparator;->compare(Lcom/android/internal/app/LocaleStore$LocaleInfo;Lcom/android/internal/app/LocaleStore$LocaleInfo;)I
 Lcom/android/internal/app/LocaleHelper;->getDisplayCountry(Ljava/util/Locale;Ljava/util/Locale;)Ljava/lang/String;
@@ -1731,10 +1492,6 @@
 Lcom/android/internal/app/WindowDecorActionBar;->setShowHideAnimationEnabled(Z)V
 Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService;
 Lcom/android/internal/appwidget/IAppWidgetService$Stub;->TRANSACTION_bindAppWidgetId:I
-Lcom/android/internal/appwidget/IAppWidgetService;->bindAppWidgetId(Ljava/lang/String;IILandroid/content/ComponentName;Landroid/os/Bundle;)Z
-Lcom/android/internal/appwidget/IAppWidgetService;->bindRemoteViewsService(Ljava/lang/String;ILandroid/content/Intent;Landroid/app/IApplicationThread;Landroid/os/IBinder;Landroid/app/IServiceConnection;I)Z
-Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetIds(Landroid/content/ComponentName;)[I
-Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetViews(Ljava/lang/String;I)Landroid/widget/RemoteViews;
 Lcom/android/internal/backup/IBackupTransport$Stub;-><init>()V
 Lcom/android/internal/content/PackageMonitor;-><init>()V
 Lcom/android/internal/database/SortCursor;-><init>([Landroid/database/Cursor;Ljava/lang/String;)V
@@ -1751,16 +1508,11 @@
 Lcom/android/internal/location/GpsNetInitiatedHandler;->mIsHexInput:Z
 Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
 Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProvider;
-Lcom/android/internal/location/ILocationProvider;->getStatus(Landroid/os/Bundle;)I
-Lcom/android/internal/location/ILocationProvider;->getStatusUpdateTime()J
 Lcom/android/internal/location/ILocationProvider;->sendExtraCommand(Ljava/lang/String;Landroid/os/Bundle;)V
 Lcom/android/internal/location/ILocationProvider;->setLocationProviderManager(Lcom/android/internal/location/ILocationProviderManager;)V
 Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V
 Lcom/android/internal/location/ILocationProviderManager$Stub;-><init>()V
 Lcom/android/internal/location/ILocationProviderManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProviderManager;
-Lcom/android/internal/location/ILocationProviderManager;->onReportLocation(Landroid/location/Location;)V
-Lcom/android/internal/location/ILocationProviderManager;->onSetEnabled(Z)V
-Lcom/android/internal/location/ILocationProviderManager;->onSetProperties(Lcom/android/internal/location/ProviderProperties;)V
 Lcom/android/internal/logging/MetricsLogger;-><init>()V
 Lcom/android/internal/net/LegacyVpnInfo;-><init>()V
 Lcom/android/internal/net/VpnConfig;-><init>()V
@@ -1772,7 +1524,6 @@
 Lcom/android/internal/os/BinderInternal;->handleGc()V
 Lcom/android/internal/os/ClassLoaderFactory;->createClassloaderNamespace(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;
 Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
-Lcom/android/internal/os/IDropBoxManagerService;->getNextEntry(Ljava/lang/String;JLjava/lang/String;)Landroid/os/DropBoxManager$Entry;
 Lcom/android/internal/os/ProcessCpuTracker$Stats;->name:Ljava/lang/String;
 Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_stime:I
 Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_uptime:J
@@ -1798,8 +1549,6 @@
 Lcom/android/internal/policy/DecorView;->mLastRightInset:I
 Lcom/android/internal/policy/DecorView;->mWindow:Lcom/android/internal/policy/PhoneWindow;
 Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService;
-Lcom/android/internal/policy/IKeyguardService;->doKeyguardTimeout(Landroid/os/Bundle;)V
-Lcom/android/internal/policy/IKeyguardService;->setKeyguardEnabled(Z)V
 Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback;
 Lcom/android/internal/policy/PhoneFallbackEventHandler;-><init>(Landroid/content/Context;)V
 Lcom/android/internal/policy/PhoneFallbackEventHandler;->mContext:Landroid/content/Context;
@@ -2253,14 +2002,7 @@
 Lcom/android/internal/statusbar/IStatusBar$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBar;
 Lcom/android/internal/statusbar/IStatusBarService$Stub;-><init>()V
 Lcom/android/internal/statusbar/IStatusBarService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBarService;
-Lcom/android/internal/statusbar/IStatusBarService;->collapsePanels()V
-Lcom/android/internal/statusbar/IStatusBarService;->disable(ILandroid/os/IBinder;Ljava/lang/String;)V
-Lcom/android/internal/statusbar/IStatusBarService;->expandNotificationsPanel()V
-Lcom/android/internal/statusbar/IStatusBarService;->handleSystemKey(I)V
-Lcom/android/internal/statusbar/IStatusBarService;->removeIcon(Ljava/lang/String;)V
-Lcom/android/internal/statusbar/IStatusBarService;->setIconVisibility(Ljava/lang/String;Z)V
 Lcom/android/internal/telecom/ITelecomService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telecom/ITelecomService;
-Lcom/android/internal/telecom/ITelecomService;->getCallState()I
 Lcom/android/internal/telephony/BaseCommands;->mCallStateRegistrants:Landroid/os/RegistrantList;
 Lcom/android/internal/telephony/BaseCommands;->mCallWaitingInfoRegistrants:Landroid/os/RegistrantList;
 Lcom/android/internal/telephony/BaseCommands;->mCatCallSetUpRegistrant:Landroid/os/Registrant;
@@ -2887,7 +2629,6 @@
 Lcom/android/internal/telephony/GsmCdmaPhone;->notifyServiceStateChanged(Landroid/telephony/ServiceState;)V
 Lcom/android/internal/telephony/GsmCdmaPhone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
 Lcom/android/internal/telephony/GsmCdmaPhone;->syncClirSetting()V
-Lcom/android/internal/telephony/ICarrierConfigLoader;->getConfigForSubId(ILjava/lang/String;)Landroid/os/PersistableBundle;
 Lcom/android/internal/telephony/IccCard;->getState()Lcom/android/internal/telephony/IccCardConstants$State;
 Lcom/android/internal/telephony/IccCard;->registerForNetworkLocked(Landroid/os/Handler;ILjava/lang/Object;)V
 Lcom/android/internal/telephony/IccCard;->supplyNetworkDepersonalization(Ljava/lang/String;Landroid/os/Message;)V
@@ -3093,8 +2834,6 @@
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneSubInfo;
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->TRANSACTION_getDeviceId:I
-Lcom/android/internal/telephony/IPhoneSubInfo;->getIccSerialNumber(Ljava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/IPhoneSubInfo;->getSubscriberId(Ljava/lang/String;)Ljava/lang/String;
 Lcom/android/internal/telephony/ISms$Stub;-><init>()V
 Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms;
 Lcom/android/internal/telephony/ISub$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -3108,38 +2847,9 @@
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_call:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_dial:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
-Lcom/android/internal/telephony/ITelephony;->call(Ljava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/ITelephony;->dial(Ljava/lang/String;)V
-Lcom/android/internal/telephony/ITelephony;->disableDataConnectivity()Z
-Lcom/android/internal/telephony/ITelephony;->disableLocationUpdates()V
-Lcom/android/internal/telephony/ITelephony;->enableDataConnectivity()Z
-Lcom/android/internal/telephony/ITelephony;->enableLocationUpdates()V
-Lcom/android/internal/telephony/ITelephony;->getActivePhoneType()I
-Lcom/android/internal/telephony/ITelephony;->getCallState()I
-Lcom/android/internal/telephony/ITelephony;->getDataActivity()I
-Lcom/android/internal/telephony/ITelephony;->getDataEnabled(I)Z
-Lcom/android/internal/telephony/ITelephony;->getDataState()I
-Lcom/android/internal/telephony/ITelephony;->getNetworkType()I
-Lcom/android/internal/telephony/ITelephony;->handlePinMmi(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->handlePinMmiForSubscriber(ILjava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->hasIccCard()Z
-Lcom/android/internal/telephony/ITelephony;->iccCloseLogicalChannel(II)Z
-Lcom/android/internal/telephony/ITelephony;->iccTransmitApduLogicalChannel(IIIIIIILjava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/ITelephony;->isRadioOnForSubscriber(ILjava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->setRadio(Z)Z
-Lcom/android/internal/telephony/ITelephony;->supplyPin(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->toggleRadioOnOff()V
-Lcom/android/internal/telephony/ITelephony;->updateServiceLocation()V
 Lcom/android/internal/telephony/ITelephonyRegistry$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ITelephonyRegistry$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephonyRegistry;
-Lcom/android/internal/telephony/ITelephonyRegistry;->listen(Ljava/lang/String;Lcom/android/internal/telephony/IPhoneStateListener;IZ)V
-Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallState(ILjava/lang/String;)V
-Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCellInfo(Ljava/util/List;)V
-Lcom/android/internal/telephony/ITelephonyRegistry;->notifyDataConnectionFailed(Ljava/lang/String;)V
 Lcom/android/internal/telephony/IWapPushManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IWapPushManager;
-Lcom/android/internal/telephony/IWapPushManager;->addPackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
-Lcom/android/internal/telephony/IWapPushManager;->deletePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
-Lcom/android/internal/telephony/IWapPushManager;->updatePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
 Lcom/android/internal/telephony/MccTable$MccEntry;->mIso:Ljava/lang/String;
 Lcom/android/internal/telephony/MccTable;->countryCodeForMcc(I)Ljava/lang/String;
 Lcom/android/internal/telephony/MccTable;->defaultLanguageForMcc(I)Ljava/lang/String;
@@ -3934,23 +3644,7 @@
 Lcom/android/internal/widget/ActionBarOverlayLayout;->setWindowCallback(Landroid/view/Window$Callback;)V
 Lcom/android/internal/widget/EditableInputConnection;-><init>(Landroid/widget/TextView;)V
 Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings;
-Lcom/android/internal/widget/ILockSettings;->getBoolean(Ljava/lang/String;ZI)Z
-Lcom/android/internal/widget/ILockSettings;->getLong(Ljava/lang/String;JI)J
-Lcom/android/internal/widget/ILockSettings;->getString(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;
-Lcom/android/internal/widget/ILockSettings;->havePassword(I)Z
-Lcom/android/internal/widget/ILockSettings;->havePattern(I)Z
-Lcom/android/internal/widget/ILockSettings;->setBoolean(Ljava/lang/String;ZI)V
-Lcom/android/internal/widget/ILockSettings;->setLong(Ljava/lang/String;JI)V
-Lcom/android/internal/widget/ILockSettings;->setString(Ljava/lang/String;Ljava/lang/String;I)V
 Lcom/android/internal/widget/IRemoteViewsFactory$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/IRemoteViewsFactory;
-Lcom/android/internal/widget/IRemoteViewsFactory;->getCount()I
-Lcom/android/internal/widget/IRemoteViewsFactory;->getItemId(I)J
-Lcom/android/internal/widget/IRemoteViewsFactory;->getLoadingView()Landroid/widget/RemoteViews;
-Lcom/android/internal/widget/IRemoteViewsFactory;->getViewAt(I)Landroid/widget/RemoteViews;
-Lcom/android/internal/widget/IRemoteViewsFactory;->getViewTypeCount()I
-Lcom/android/internal/widget/IRemoteViewsFactory;->hasStableIds()Z
-Lcom/android/internal/widget/IRemoteViewsFactory;->isCreated()Z
-Lcom/android/internal/widget/IRemoteViewsFactory;->onDataSetChanged()V
 Lcom/android/internal/widget/LinearLayoutWithDefaultTouchRecepient;-><init>(Landroid/content/Context;)V
 Lcom/android/internal/widget/LinearLayoutWithDefaultTouchRecepient;->setDefaultTouchRecepient(Landroid/view/View;)V
 Lcom/android/internal/widget/LockPatternChecker;->checkPassword(Lcom/android/internal/widget/LockPatternUtils;Ljava/lang/String;ILcom/android/internal/widget/LockPatternChecker$OnCheckCallback;)Landroid/os/AsyncTask;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index dc8863a..68b2de4 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;
     }
 
@@ -3522,6 +3521,12 @@
      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
      * the event).
+     *
+     * To receive this callback, you must return true from onKeyDown for the current
+     * event stream.
+     *
+     * @see KeyEvent.Callback#onKeyLongPress()
+     * @see KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
      */
     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
         return false;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 92302c5..b18c4de 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6954,6 +6954,8 @@
                 fd.setInt$(cr.openFileDescriptor(uri,
                         FileUtils.translateModePosixToString(mode)).detachFd());
                 return fd;
+            } catch (SecurityException e) {
+                throw new ErrnoException(e.getMessage(), OsConstants.EACCES);
             } catch (FileNotFoundException e) {
                 throw new ErrnoException(e.getMessage(), OsConstants.ENOENT);
             }
diff --git a/core/java/android/app/AppComponentFactory.java b/core/java/android/app/AppComponentFactory.java
index ae63291..2cec7f0 100644
--- a/core/java/android/app/AppComponentFactory.java
+++ b/core/java/android/app/AppComponentFactory.java
@@ -27,6 +27,7 @@
  *
  * @see #instantiateApplication
  * @see #instantiateActivity
+ * @see #instantiateClassLoader
  * @see #instantiateService
  * @see #instantiateReceiver
  * @see #instantiateProvider
@@ -39,8 +40,10 @@
      * a custom class loader hierarchy.
      *
      * @param cl        The default classloader instantiated by platform.
+     * @param aInfo     Information about the application being loaded.
      */
-    public @NonNull ClassLoader instantiateClassLoader(@NonNull ClassLoader cl) {
+    public @NonNull ClassLoader instantiateClassLoader(@NonNull ClassLoader cl,
+            @NonNull ApplicationInfo aInfo) {
         return cl;
     }
 
@@ -133,19 +136,6 @@
         return (ContentProvider) cl.loadClass(className).newInstance();
     }
 
-    private ApplicationInfo mApplicationInfo = null;
-
-    void setApplicationInfo(ApplicationInfo info) {
-        mApplicationInfo = info;
-    }
-
-    /**
-     * Returns the ApplicationInfo associated with this package.
-     */
-    public ApplicationInfo getApplicationInfo() {
-        return mApplicationInfo;
-    }
-
     /**
      * @hide
      */
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 780dd63..5cbb599 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -204,6 +204,7 @@
     void setProcessImportant(in IBinder token, int pid, boolean isForeground, String reason);
     void setServiceForeground(in ComponentName className, in IBinder token,
             int id, in Notification notification, int flags, int foregroundServiceType);
+    int getForegroundServiceType(in ComponentName className, in IBinder token);
     boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
     void getMemoryInfo(out ActivityManager.MemoryInfo outInfo);
     List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState();
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 8615f00..8c85ad1 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -81,6 +81,16 @@
             int requestedDisplayId);
 
     /**
+     * Called when an activity was requested to be launched on a secondary display but was rerouted
+     * to default display.
+     *
+     * @param taskInfo info about the Activity's task
+     * @param requestedDisplayId the id of the requested launch display
+     */
+    void onActivityLaunchOnSecondaryDisplayRerouted(in ActivityManager.RunningTaskInfo taskInfo,
+                int requestedDisplayId);
+
+    /**
      * Called when a task is added.
      *
      * @param taskId id of the task.
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 5c4c005..5d186a2 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -232,7 +232,8 @@
         mResources = Resources.getSystem();
         mDefaultClassLoader = ClassLoader.getSystemClassLoader();
         mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
-        mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
+        mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
+                new ApplicationInfo(mApplicationInfo));
     }
 
     /**
@@ -243,19 +244,15 @@
         mApplicationInfo = info;
         mDefaultClassLoader = classLoader;
         mAppComponentFactory = createAppFactory(info, mDefaultClassLoader);
-        mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
+        mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
+                new ApplicationInfo(mApplicationInfo));
     }
 
     private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
         if (appInfo.appComponentFactory != null && cl != null) {
             try {
-                AppComponentFactory factory = (AppComponentFactory) cl.loadClass(
-                        appInfo.appComponentFactory).newInstance();
-                // Pass a copy of ApplicationInfo to the factory. Copying protects the framework
-                // from apps which would override the factory and change ApplicationInfo contents.
-                // ApplicationInfo is used to set up the default class loader.
-                factory.setApplicationInfo(new ApplicationInfo(appInfo));
-                return factory;
+                return (AppComponentFactory)
+                        cl.loadClass(appInfo.appComponentFactory).newInstance();
             } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                 Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
             }
@@ -729,8 +726,8 @@
                 mDefaultClassLoader = ClassLoader.getSystemClassLoader();
             }
             mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
-            mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
-
+            mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
+                    new ApplicationInfo(mApplicationInfo));
             return;
         }
 
@@ -821,7 +818,8 @@
             }
 
             if (mClassLoader == null) {
-                mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
+                mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
+                        new ApplicationInfo(mApplicationInfo));
             }
 
             return;
@@ -935,8 +933,10 @@
         // Call AppComponentFactory to select/create the main class loader of this app.
         // Since this may call code in the app, mDefaultClassLoader must be fully set up
         // before invoking the factory.
+        // Invoke with a copy of ApplicationInfo to protect against the app changing it.
         if (mClassLoader == null) {
-            mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader);
+            mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
+                    new ApplicationInfo(mApplicationInfo));
         }
     }
 
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 4a45150..8493fb2 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -47,8 +47,10 @@
 import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AutoCompleteTextView;
+import android.widget.Filterable;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.ListPopupWindow;
 import android.widget.SearchView;
 import android.widget.TextView;
 
@@ -370,7 +372,10 @@
             updateSearchAppIcon();
             updateSearchBadge();
             if (isLandscapeMode(getContext())) {
-                mSearchAutoComplete.ensureImeVisible(true);
+                mSearchAutoComplete.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED);
+                if (mSearchAutoComplete.isDropDownAlwaysVisible() || enoughToFilter()) {
+                    mSearchAutoComplete.showDropDown();
+                }
             }
         }
     }
@@ -381,6 +386,15 @@
                 == Configuration.ORIENTATION_LANDSCAPE;
     }
 
+    private boolean enoughToFilter() {
+        Filterable filterableAdapter = (Filterable) mSearchAutoComplete.getAdapter();
+        if (filterableAdapter == null || filterableAdapter.getFilter() == null) {
+            return false;
+        }
+
+        return mSearchAutoComplete.enoughToFilter();
+    }
+
     /**
      * Update the UI according to the info in the current value of {@link #mSearchable}.
      */
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index f116e13..1f91b3f 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -27,6 +27,7 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
+import android.content.pm.ServiceInfo;
 import android.content.pm.ServiceInfo.ForegroundServiceType;
 import android.content.res.Configuration;
 import android.os.Build;
@@ -733,7 +734,7 @@
    * {@link android.R.attr#foregroundServiceType} flags.
    * @throws IllegalArgumentException if param foregroundServiceType is not subset of manifest
    *     attribute {@link android.R.attr#foregroundServiceType}.
-   * @see {@link android.content.pm.ServiceInfo} for the set of FOREGROUND_SERVICE_TYPE flags.
+   * @see android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MANIFEST
    */
     public final void startForeground(int id, @NonNull Notification notification,
             @ForegroundServiceType int foregroundServiceType) {
@@ -775,6 +776,30 @@
     }
 
     /**
+     * If the service has become a foreground service by calling
+     * {@link #startForeground(int, Notification)}
+     * or {@link #startForeground(int, Notification, int)}, {@link #getForegroundServiceType()}
+     * returns the current foreground service type.
+     *
+     * <p>If there is no foregroundServiceType specified
+     * in manifest, {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE} is returned. </p>
+     *
+     * <p>If the service is not a foreground service,
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE} is returned.</p>
+     *
+     * @return current foreground service type flags.
+     */
+    public final @ForegroundServiceType int getForegroundServiceType() {
+        int ret = ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
+        try {
+            ret = mActivityManager.getForegroundServiceType(
+                    new ComponentName(this, mClassName), mToken);
+        } catch (RemoteException ex) {
+        }
+        return ret;
+    }
+
+    /**
      * Print the Service's state into the given stream.  This gets invoked if
      * you run "adb shell dumpsys activity service &lt;yourservicename&gt;"
      * (note that for this command to work, the service must be running, and
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 077652c..af03668 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -387,6 +388,7 @@
      * @hide
      */
     @SystemApi
+    @NonNull
     public DisableInfo getDisableInfo() {
         try {
             final int userId = Binder.getCallingUserHandle().getIdentifier();
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index fcc76ac..47ad6d7 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -85,6 +85,12 @@
     }
 
     @Override
+    @UnsupportedAppUsage
+    public void onActivityLaunchOnSecondaryDisplayRerouted(ActivityManager.RunningTaskInfo taskInfo,
+            int requestedDisplayId) throws RemoteException {
+    }
+
+    @Override
     public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
     }
 
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/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 6c6fcb2..dad1a1a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -662,6 +662,14 @@
      */
     public static final int PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE = 1 << 26;
 
+    /**
+     * Value for {@link #privateFlags}: true if the application allows its audio playback
+     * to be captured by other apps.
+     *
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE  = 1 << 27;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
             PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -688,7 +696,8 @@
             PRIVATE_FLAG_VENDOR,
             PRIVATE_FLAG_VIRTUAL_PRELOAD,
             PRIVATE_FLAG_HAS_FRAGILE_USER_DATA,
-            PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE
+            PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE,
+            PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApplicationInfoPrivateFlags {}
@@ -1342,6 +1351,8 @@
             }
             pw.println(prefix + "HiddenApiEnforcementPolicy=" + getHiddenApiEnforcementPolicy());
             pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi());
+            pw.println(prefix + "allowsPlaybackCapture="
+                        + (isAudioPlaybackCaptureAllowed() ? "true" : "false"));
         }
         super.dumpBack(pw, prefix);
     }
@@ -1790,6 +1801,17 @@
         return (privateFlags & PRIVATE_FLAG_HAS_FRAGILE_USER_DATA) != 0;
     }
 
+    /**
+     * Whether an app allows its playback audio to be captured by other apps.
+     *
+     * @return {@code true} if the app indicates that its audio can be captured by other apps.
+     *
+     * @hide
+     */
+    public boolean isAudioPlaybackCaptureAllowed() {
+        return (privateFlags & PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE) != 0;
+    }
+
     private boolean isAllowedToUseHiddenApis() {
         if (isSignedWithPlatformKey()) {
             return true;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4db7d0a..f899800 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3756,6 +3756,12 @@
             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE;
         }
 
+        if (sa.getBoolean(
+                R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture,
+                owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q)) {
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE;
+        }
+
         ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
         ai.minAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0);
 
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index 0cde6ba..9459ad3 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -17,12 +17,10 @@
 package android.content.rollback;
 
 import android.annotation.SystemApi;
-import android.content.pm.PackageInstaller;
 import android.content.pm.VersionedPackage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -44,13 +42,7 @@
     private final List<VersionedPackage> mCausePackages;
 
     private final boolean mIsStaged;
-    private final int mCommittedSessionId;
-
-    /** @hide */
-    public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages, boolean isStaged) {
-        this(rollbackId, packages, isStaged, Collections.emptyList(),
-                PackageInstaller.SessionInfo.INVALID_ID);
-    }
+    private int mCommittedSessionId;
 
     /** @hide */
     public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages, boolean isStaged,
@@ -101,6 +93,14 @@
     }
 
     /**
+     * Sets the session ID for the committed rollback for staged rollbacks.
+     * @hide
+     */
+    public void setCommittedSessionId(int sessionId) {
+        mCommittedSessionId = sessionId;
+    }
+
+    /**
      * Gets the list of package versions that motivated this rollback.
      * As provided to {@link #commitRollback} when the rollback was committed.
      * This is only applicable for rollbacks that have been committed.
diff --git a/core/java/android/database/BulkCursorNative.java b/core/java/android/database/BulkCursorNative.java
index d3c11e7..77a13cf 100644
--- a/core/java/android/database/BulkCursorNative.java
+++ b/core/java/android/database/BulkCursorNative.java
@@ -16,6 +16,7 @@
 
 package android.database;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -138,6 +139,7 @@
 
 
 final class BulkCursorProxy implements IBulkCursor {
+    @UnsupportedAppUsage
     private IBinder mRemote;
     private Bundle mExtras;
 
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/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index baf972b..8629210 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -616,8 +616,15 @@
             mExecutor = executor;
             mAuthenticationCallback = callback;
             final long sessionId = crypto != null ? crypto.getOpId() : 0;
-            mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver,
-                    mContext.getOpPackageName(), mBundle);
+            if (BiometricManager.hasBiometrics(mContext)) {
+                mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver,
+                        mContext.getOpPackageName(), mBundle);
+            } else {
+                mExecutor.execute(() -> {
+                    callback.onAuthenticationError(BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT,
+                            mContext.getString(R.string.biometric_error_hw_unavailable));
+                });
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Remote exception while authenticating", e);
             mExecutor.execute(() -> {
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/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 5ea8bd6..edd2051 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -30,6 +30,7 @@
 
 /** @hide */
 interface IDisplayManager {
+    @UnsupportedAppUsage
     DisplayInfo getDisplayInfo(int displayId);
     int[] getDisplayIds();
 
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 64448fd..2923bbf 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -45,6 +45,7 @@
 
     // Injects an input event into the system.  To inject into windows owned by other
     // applications, the caller must have the INJECT_EVENTS permission.
+    @UnsupportedAppUsage
     boolean injectInputEvent(in InputEvent ev, int mode);
 
     // Calibrate input device position
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
index 3fe645c..2dfaf60 100644
--- a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
+++ b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
@@ -32,5 +32,6 @@
      * @param isSupported whether the platform has hardware support for the feature
      * @param instance the available instance to provide access to the feature
      */
+    @UnsupportedAppUsage
     void onAvailabilityChanged(in boolean isSupported, in IActivityRecognitionHardware instance);
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c1bce5e..64ed322 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3684,7 +3684,8 @@
     /**
      * Registers to receive notifications about all networks which satisfy the given
      * {@link NetworkRequest}.  The callbacks will continue to be called until
-     * either the application exits or link #unregisterNetworkCallback(NetworkCallback)} is called.
+     * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is
+     * called.
      *
      * @param request {@link NetworkRequest} describing this request.
      * @param networkCallback The {@link NetworkCallback} that the system will call as suitable
@@ -3700,7 +3701,8 @@
     /**
      * Registers to receive notifications about all networks which satisfy the given
      * {@link NetworkRequest}.  The callbacks will continue to be called until
-     * either the application exits or link #unregisterNetworkCallback(NetworkCallback)} is called.
+     * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is
+     * called.
      *
      * @param request {@link NetworkRequest} describing this request.
      * @param networkCallback The {@link NetworkCallback} that the system will call as suitable
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 87c62d2..bd2b4eb 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -47,10 +47,12 @@
 {
     Network getActiveNetwork();
     Network getActiveNetworkForUid(int uid, boolean ignoreBlocked);
+    @UnsupportedAppUsage
     NetworkInfo getActiveNetworkInfo();
     NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked);
     NetworkInfo getNetworkInfo(int networkType);
     NetworkInfo getNetworkInfoForUid(in Network network, int uid, boolean ignoreBlocked);
+    @UnsupportedAppUsage
     NetworkInfo[] getAllNetworkInfo();
     Network getNetworkForType(int networkType);
     Network[] getAllNetworks();
@@ -58,12 +60,14 @@
 
     boolean isNetworkSupported(int networkType);
 
+    @UnsupportedAppUsage
     LinkProperties getActiveLinkProperties();
     LinkProperties getLinkPropertiesForType(int networkType);
     LinkProperties getLinkProperties(in Network network);
 
     NetworkCapabilities getNetworkCapabilities(in Network network);
 
+    @UnsupportedAppUsage
     NetworkState[] getAllNetworkState();
 
     NetworkQuotaInfo getActiveNetworkQuotaInfo();
@@ -75,6 +79,7 @@
 
     int untether(String iface, String callerPkg);
 
+    @UnsupportedAppUsage
     int getLastTetherError(String iface);
 
     boolean isTetheringSupported(String callerPkg);
@@ -84,16 +89,21 @@
 
     void stopTethering(int type, String callerPkg);
 
+    @UnsupportedAppUsage
     String[] getTetherableIfaces();
 
+    @UnsupportedAppUsage
     String[] getTetheredIfaces();
 
+    @UnsupportedAppUsage
     String[] getTetheringErroredIfaces();
 
     String[] getTetheredDhcpRanges();
 
+    @UnsupportedAppUsage
     String[] getTetherableUsbRegexs();
 
+    @UnsupportedAppUsage
     String[] getTetherableWifiRegexs();
 
     String[] getTetherableBluetoothRegexs();
@@ -118,6 +128,7 @@
 
     VpnConfig getVpnConfig(int userId);
 
+    @UnsupportedAppUsage
     void startLegacyVpn(in VpnProfile profile);
 
     LegacyVpnInfo getLegacyVpnInfo(int userId);
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index e92302a..385cb1d 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -31,9 +31,11 @@
 interface INetworkPolicyManager {
 
     /** Control UID policies. */
+    @UnsupportedAppUsage
     void setUidPolicy(int uid, int policy);
     void addUidPolicy(int uid, int policy);
     void removeUidPolicy(int uid, int policy);
+    @UnsupportedAppUsage
     int getUidPolicy(int uid);
     int[] getUidsWithPolicy(int policy);
 
@@ -41,14 +43,18 @@
     void unregisterListener(INetworkPolicyListener listener);
 
     /** Control network policies atomically. */
+    @UnsupportedAppUsage
     void setNetworkPolicies(in NetworkPolicy[] policies);
     NetworkPolicy[] getNetworkPolicies(String callingPackage);
 
     /** Snooze limit on policy matching given template. */
+    @UnsupportedAppUsage
     void snoozeLimit(in NetworkTemplate template);
 
     /** Control if background data is restricted system-wide. */
+    @UnsupportedAppUsage
     void setRestrictBackground(boolean restrictBackground);
+    @UnsupportedAppUsage
     boolean getRestrictBackground();
 
     /** Callback used to change internal state on tethering */
@@ -64,6 +70,7 @@
     void setDeviceIdleMode(boolean enabled);
     void setWifiMeteredOverride(String networkId, int meteredOverride);
 
+    @UnsupportedAppUsage
     NetworkQuotaInfo getNetworkQuotaInfo(in NetworkState state);
 
     SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 8e6f272..92b685c 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -29,6 +29,7 @@
 interface INetworkStatsService {
 
     /** Start a statistics query session. */
+    @UnsupportedAppUsage
     INetworkStatsSession openSession();
 
     /** Start a statistics query session. If calling package is profile or device owner then it is
@@ -37,9 +38,11 @@
      *  PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted
      *  READ_NETWORK_USAGE_STATS is checked for.
      */
+    @UnsupportedAppUsage
     INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage);
 
     /** Return data layer snapshot of UID network usage. */
+    @UnsupportedAppUsage
     NetworkStats getDataLayerSnapshotForUid(int uid);
 
     /** Get a detailed snapshot of stats since boot for all UIDs.
@@ -52,6 +55,7 @@
     NetworkStats getDetailedUidStats(in String[] requiredIfaces);
 
     /** Return set of any ifaces associated with mobile networks since boot. */
+    @UnsupportedAppUsage
     String[] getMobileIfaces();
 
     /** Increment data layer count of operations performed for UID and tag. */
@@ -60,6 +64,7 @@
     /** Force update of ifaces. */
     void forceUpdateIfaces(in Network[] defaultNetworks);
     /** Force update of statistics. */
+    @UnsupportedAppUsage
     void forceUpdate();
 
     /** Registers a callback on data usage. */
diff --git a/core/java/android/net/INetworkStatsSession.aidl b/core/java/android/net/INetworkStatsSession.aidl
index 5229a3b..f13f2cb 100644
--- a/core/java/android/net/INetworkStatsSession.aidl
+++ b/core/java/android/net/INetworkStatsSession.aidl
@@ -27,13 +27,17 @@
     NetworkStats getDeviceSummaryForNetwork(in NetworkTemplate template, long start, long end);
 
     /** Return network layer usage summary for traffic that matches template. */
+    @UnsupportedAppUsage
     NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
     /** Return historical network layer stats for traffic that matches template. */
+    @UnsupportedAppUsage
     NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
 
     /** Return network layer usage summary per UID for traffic that matches template. */
+    @UnsupportedAppUsage
     NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
     /** Return historical network layer stats for specific UID traffic that matches template. */
+    @UnsupportedAppUsage
     NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
     /** Return historical network layer stats for specific UID traffic that matches template. */
     NetworkStatsHistory getHistoryIntervalForUid(in NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end);
@@ -41,6 +45,7 @@
     /** Return array of uids that have stats and are accessible to the calling user */
     int[] getRelevantUids();
 
+    @UnsupportedAppUsage
     void close();
 
 }
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/nfc/INfcAdapterExtras.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl
index 41ebf63..dd260bc 100644
--- a/core/java/android/nfc/INfcAdapterExtras.aidl
+++ b/core/java/android/nfc/INfcAdapterExtras.aidl
@@ -23,11 +23,18 @@
  * {@hide}
  */
 interface INfcAdapterExtras {
+    @UnsupportedAppUsage
     Bundle open(in String pkg, IBinder b);
+    @UnsupportedAppUsage
     Bundle close(in String pkg, IBinder b);
+    @UnsupportedAppUsage
     Bundle transceive(in String pkg, in byte[] data_in);
+    @UnsupportedAppUsage
     int getCardEmulationRoute(in String pkg);
+    @UnsupportedAppUsage
     void setCardEmulationRoute(in String pkg, int route);
+    @UnsupportedAppUsage
     void authenticate(in String pkg, in byte[] token);
+    @UnsupportedAppUsage
     String getDriverName(in String pkg);
 }
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/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 99fb608..471ae30 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -240,7 +240,7 @@
      *
      * @return The desired effect.
      */
-    public static VibrationEffect createPrebaked(@EffectType int effectId) {
+    public static VibrationEffect createPredefined(@EffectType int effectId) {
         return get(effectId, true);
     }
 
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 90a5f76..27e3914 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -136,6 +136,8 @@
     public static final String PROP_ISOLATED_STORAGE = "persist.sys.isolated_storage";
     /** {@hide} */
     public static final String PROP_ISOLATED_STORAGE_SNAPSHOT = "sys.isolated_storage_snapshot";
+    /** {@hide} */
+    public static final String PROP_LEGACY_GREYLIST = "persist.sys.legacy_greylist";
 
     /** {@hide} */
     public static final String PROP_FORCE_AUDIO = "persist.fw.force_audio";
@@ -233,6 +235,8 @@
     public static final int DEBUG_ISOLATED_STORAGE_FORCE_ON = 1 << 6;
     /** {@hide} */
     public static final int DEBUG_ISOLATED_STORAGE_FORCE_OFF = 1 << 7;
+    /** {@hide} */
+    public static final int DEBUG_LEGACY_GREYLIST = 1 << 8;
 
     /** {@hide} */
     public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index ce28c30..a57d292e 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -100,27 +100,12 @@
     public static final String NAMESPACE_NETD_NATIVE = "netd_native";
 
     /**
-     * Namespace for features related to the ExtServices Notification Assistant.
-     * These features are applied immediately.
+     * Namespace for System UI related features.
      *
      * @hide
      */
     @SystemApi
-    public interface NotificationAssistant {
-        String NAMESPACE = "notification_assistant";
-        /**
-         * Whether the Notification Assistant should generate replies for notifications.
-         */
-        String GENERATE_REPLIES = "generate_replies";
-        /**
-         * Whether the Notification Assistant should generate contextual actions for notifications.
-         */
-        String GENERATE_ACTIONS = "generate_actions";
-
-        String MAX_MESSAGES_TO_EXTRACT = "max_messages_to_extract";
-
-        String MAX_SUGGESTIONS = "max_suggestions";
-    }
+    public static final String NAMESPACE_SYSTEMUI = "systemui";
 
     /**
      * Namespace for all runtime related features.
@@ -427,6 +412,100 @@
     }
 
     /**
+     * Look up the String value of a property for a particular namespace.
+     *
+     * @param namespace The namespace containing the property to look up.
+     * @param name      The name of the property to look up.
+     * @return the corresponding value, or defaultValue if none exists.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(READ_DEVICE_CONFIG)
+    public static String getString(String namespace, String name, String defaultValue) {
+        String value = getProperty(namespace, name);
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * Look up the boolean value of a property for a particular namespace.
+     *
+     * @param namespace The namespace containing the property to look up.
+     * @param name      The name of the property to look up.
+     * @return the corresponding value, or defaultValue if none exists.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(READ_DEVICE_CONFIG)
+    public static boolean getBoolean(String namespace, String name, boolean defaultValue) {
+        String value = getProperty(namespace, name);
+        return value != null ? Boolean.parseBoolean(value) : defaultValue;
+    }
+
+    /**
+     * Look up the int value of a property for a particular namespace.
+     *
+     * @param namespace The namespace containing the property to look up.
+     * @param name      The name of the property to look up.
+     * @return the corresponding value, or defaultValue if either none exists or it does not parse.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(READ_DEVICE_CONFIG)
+    public static int getInt(String namespace, String name, int defaultValue) {
+        String value = getProperty(namespace, name);
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Look up the long value of a property for a particular namespace.
+     *
+     * @param namespace The namespace containing the property to look up.
+     * @param name      The name of the property to look up.
+     * @return the corresponding value, or defaultValue if either none exists or it does not parse.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(READ_DEVICE_CONFIG)
+    public static long getLong(String namespace, String name, long defaultValue) {
+        String value = getProperty(namespace, name);
+        try {
+            return Long.parseLong(value);
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Look up the float value of a property for a particular namespace.
+     *
+     * @param namespace The namespace containing the property to look up.
+     * @param name      The name of the property to look up.
+     * @return the corresponding value, or defaultValue if either none exists or it does not parse.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(READ_DEVICE_CONFIG)
+    public static float getFloat(String namespace, String name, float defaultValue) {
+        String value = getProperty(namespace, name);
+        try {
+            return Float.parseFloat(value);
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        } catch (NullPointerException e) {
+            return defaultValue;
+        }
+    }
+
+    /**
      * Create a new property with the the provided name and value in the provided namespace, or
      * update the value of such a property if it already exists. The same name can exist in multiple
      * namespaces and might have different values in any or all namespaces.
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 643307e..758db49 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -529,7 +529,6 @@
      *
      * @see MediaColumns#IS_PENDING
      * @see MediaStore#setIncludePending(Uri)
-     * @see MediaStore#createPending(Context, PendingParams)
      */
     public static @NonNull Uri setIncludePending(@NonNull Uri uri) {
         return setIncludePending(uri.buildUpon()).build();
@@ -586,7 +585,9 @@
      * @see MediaColumns#IS_PENDING
      * @see MediaStore#setIncludePending(Uri)
      * @see MediaStore#createPending(Context, PendingParams)
+     * @removed
      */
+    @Deprecated
     public static @NonNull Uri createPending(@NonNull Context context,
             @NonNull PendingParams params) {
         return context.getContentResolver().insert(params.insertUri, params.insertValues);
@@ -599,14 +600,19 @@
      *
      * @param uri token which was previously returned from
      *            {@link #createPending(Context, PendingParams)}.
+     * @removed
      */
+    @Deprecated
     public static @NonNull PendingSession openPending(@NonNull Context context, @NonNull Uri uri) {
         return new PendingSession(context, uri);
     }
 
     /**
      * Parameters that describe a pending media item.
+     *
+     * @removed
      */
+    @Deprecated
     public static class PendingParams {
         /** {@hide} */
         public final Uri insertUri;
@@ -711,7 +717,10 @@
      * expected to have a short lifetime, and owners should either
      * {@link PendingSession#publish()} or {@link PendingSession#abandon()} a
      * pending item within a few hours after first creating it.
+     *
+     * @removed
      */
+    @Deprecated
     public static class PendingSession implements AutoCloseable {
         /** {@hide} */
         private final Context mContext;
@@ -976,9 +985,7 @@
          * Flag indicating if a media item is pending, and still being inserted
          * by its owner.
          *
-         * @see MediaColumns#IS_PENDING
          * @see MediaStore#setIncludePending(Uri)
-         * @see MediaStore#createPending(Context, PendingParams)
          */
         @Column(Cursor.FIELD_TYPE_INTEGER)
         public static final String IS_PENDING = "is_pending";
@@ -998,12 +1005,8 @@
 
         /**
          * The time the media item should be considered expired. Typically only
-         * meaningful in the context of {@link #IS_PENDING} or
-         * {@link #IS_TRASHED}.
-         *
-         * @removed
+         * meaningful in the context of {@link #IS_PENDING}.
          */
-        @Deprecated
         @CurrentTimeSecondsLong
         @Column(Cursor.FIELD_TYPE_INTEGER)
         public static final String DATE_EXPIRES = "date_expires";
@@ -1030,8 +1033,6 @@
         /**
          * The primary directory name this media exists under. The value may be
          * {@code NULL} if the media doesn't have a primary directory name.
-         *
-         * @see PendingParams#setPrimaryDirectory(String)
          */
         @Column(Cursor.FIELD_TYPE_STRING)
         public static final String PRIMARY_DIRECTORY = "primary_directory";
@@ -1039,8 +1040,6 @@
         /**
          * The secondary directory name this media exists under. The value may
          * be {@code NULL} if the media doesn't have a secondary directory name.
-         *
-         * @see PendingParams#setSecondaryDirectory(String)
          */
         @Column(Cursor.FIELD_TYPE_STRING)
         public static final String SECONDARY_DIRECTORY = "secondary_directory";
@@ -1292,12 +1291,7 @@
     }
 
     /**
-     * Container for downloaded files.
-     *
-     * <p>
-     * Querying for downloads from this table will return files contributed via
-     * {@link PendingSession} and also ones which were downloaded using
-     * {@link android.app.DownloadManager} APIs.
+     * Collection of downloaded items.
      */
     public static final class Downloads implements DownloadColumns {
         private Downloads() {}
@@ -1620,9 +1614,9 @@
              * @param name The name of the image
              * @param description The description of the image
              * @return The URL to the newly created image
-             * @deprecated inserting of images should be performed through
-             *             {@link MediaStore#createPending(Context, PendingParams)},
-             *             which offers richer control over lifecycle.
+             * @deprecated inserting of images should be performed using
+             *             {@link MediaColumns#IS_PENDING}, which offers richer
+             *             control over lifecycle.
              */
             @Deprecated
             public static final String insertImage(ContentResolver cr, String imagePath,
@@ -1651,9 +1645,9 @@
              * @param description The description of the image
              * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
              *              for any reason.
-             * @deprecated inserting of images should be performed through
-             *             {@link MediaStore#createPending(Context, PendingParams)},
-             *             which offers richer control over lifecycle.
+             * @deprecated inserting of images should be performed using
+             *             {@link MediaColumns#IS_PENDING}, which offers richer
+             *             control over lifecycle.
              */
             @Deprecated
             public static final String insertImage(ContentResolver cr, Bitmap source,
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/service/contentsuggestions/ContentSuggestionsService.java b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
index 333f4be..40333bf 100644
--- a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
+++ b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
@@ -60,11 +60,17 @@
         @Override
         public void provideContextImage(int taskId, GraphicBuffer contextImage,
                 Bundle imageContextRequestExtras) {
+
+            Bitmap wrappedBuffer = null;
+            if (contextImage != null) {
+                wrappedBuffer = Bitmap.wrapHardwareBuffer(
+                        HardwareBuffer.createFromGraphicBuffer(contextImage), null);
+            }
+
             mHandler.sendMessage(
                     obtainMessage(ContentSuggestionsService::processContextImage,
                             ContentSuggestionsService.this, taskId,
-                            Bitmap.wrapHardwareBuffer(
-                                    HardwareBuffer.createFromGraphicBuffer(contextImage), null),
+                            wrappedBuffer,
                             imageContextRequestExtras));
         }
 
diff --git a/core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl b/core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl
index 4667066..aff8f1b 100644
--- a/core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl
+++ b/core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl
@@ -18,5 +18,6 @@
 
 /** @hide */
 oneway interface IDeleteSubscriptionCallback {
+    @UnsupportedAppUsage
     void onComplete(int result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl b/core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl
index c975f18..34b53cc 100644
--- a/core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl
+++ b/core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl
@@ -18,5 +18,6 @@
 
 /** @hide */
 oneway interface IEraseSubscriptionsCallback {
+    @UnsupportedAppUsage
     void onComplete(int result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl b/core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl
index 0c5a0c6..ad69ef1 100644
--- a/core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl
+++ b/core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl
@@ -20,5 +20,6 @@
 
 /** @hide */
 oneway interface IGetDefaultDownloadableSubscriptionListCallback {
+    @UnsupportedAppUsage
     void onComplete(in GetDefaultDownloadableSubscriptionListResult result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl b/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl
index 3353061..01f187e 100644
--- a/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl
+++ b/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl
@@ -20,5 +20,6 @@
 
 /** @hide */
 oneway interface IGetDownloadableSubscriptionMetadataCallback {
+    @UnsupportedAppUsage
     void onComplete(in GetDownloadableSubscriptionMetadataResult result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetEidCallback.aidl b/core/java/android/service/euicc/IGetEidCallback.aidl
index 35ee9c2..e405a98 100644
--- a/core/java/android/service/euicc/IGetEidCallback.aidl
+++ b/core/java/android/service/euicc/IGetEidCallback.aidl
@@ -18,5 +18,6 @@
 
 /** @hide */
 oneway interface IGetEidCallback {
+    @UnsupportedAppUsage
     void onSuccess(String eid);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetEuiccInfoCallback.aidl b/core/java/android/service/euicc/IGetEuiccInfoCallback.aidl
index 6d28148..c061182 100644
--- a/core/java/android/service/euicc/IGetEuiccInfoCallback.aidl
+++ b/core/java/android/service/euicc/IGetEuiccInfoCallback.aidl
@@ -20,5 +20,6 @@
 
 /** @hide */
 oneway interface IGetEuiccInfoCallback {
+    @UnsupportedAppUsage
     void onSuccess(in EuiccInfo euiccInfo);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl b/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl
index 761ec1f..0485f7b 100644
--- a/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl
+++ b/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl
@@ -20,5 +20,6 @@
 
 /** @hide */
 oneway interface IGetEuiccProfileInfoListCallback {
+    @UnsupportedAppUsage
     void onComplete(in GetEuiccProfileInfoListResult result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl b/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl
index 1276830..340401f 100644
--- a/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl
+++ b/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl
@@ -18,5 +18,6 @@
 
 /** @hide */
 oneway interface IRetainSubscriptionsForFactoryResetCallback {
+    @UnsupportedAppUsage
     void onComplete(int result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl b/core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl
index 0f91a6b..b8f984d 100644
--- a/core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl
+++ b/core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl
@@ -18,5 +18,6 @@
 
 /** @hide */
 oneway interface ISwitchToSubscriptionCallback {
+    @UnsupportedAppUsage
     void onComplete(int result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl b/core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl
index 6666933..0aa6697 100644
--- a/core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl
+++ b/core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl
@@ -18,5 +18,6 @@
 
 /** @hide */
 oneway interface IUpdateSubscriptionNicknameCallback {
+    @UnsupportedAppUsage
     void onComplete(int result);
 }
\ No newline at end of file
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
index b0269e3..a8293b4 100644
--- a/core/java/android/service/vr/IVrManager.aidl
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -57,6 +57,7 @@
      *
      * @return {@code true} if VR mode is enabled.
      */
+    @UnsupportedAppUsage
     boolean getVrModeState();
 
     /**
@@ -93,6 +94,7 @@
      * @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display
      * currently, else return the display id of the virtual display
      */
+    @UnsupportedAppUsage
     int getVr2dDisplayId();
 
     /**
diff --git a/core/java/android/service/wallpaper/IWallpaperEngine.aidl b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
index ebce484..00e0b7c 100644
--- a/core/java/android/service/wallpaper/IWallpaperEngine.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
@@ -26,11 +26,15 @@
 oneway interface IWallpaperEngine {
     void setDesiredSize(int width, int height);
     void setDisplayPadding(in Rect padding);
+    @UnsupportedAppUsage
     void setVisibility(boolean visible);
     void setInAmbientMode(boolean inAmbientDisplay, long animationDuration);
+    @UnsupportedAppUsage
     void dispatchPointer(in MotionEvent event);
+    @UnsupportedAppUsage
     void dispatchWallpaperCommand(String action, int x, int y,
             int z, in Bundle extras);
     void requestWallpaperColors();
+    @UnsupportedAppUsage
     void destroy();
 }
diff --git a/core/java/android/speech/IRecognitionListener.aidl b/core/java/android/speech/IRecognitionListener.aidl
index 3d3c44b..e77851b 100644
--- a/core/java/android/speech/IRecognitionListener.aidl
+++ b/core/java/android/speech/IRecognitionListener.aidl
@@ -83,5 +83,6 @@
      * @param eventType the type of the occurred event
      * @param params a Bundle containing the passed parameters
      */
+    @UnsupportedAppUsage
     void onEvent(in int eventType, in Bundle params);
 }
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 140c34f..fac699e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -45,13 +45,12 @@
     static {
         DEFAULT_FLAGS = new HashMap<>();
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
-        DEFAULT_FLAGS.put("settings_dynamic_homepage", "true");
         DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
         DEFAULT_FLAGS.put("settings_network_and_internet_v2", "false");
         DEFAULT_FLAGS.put("settings_slice_injection", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
         DEFAULT_FLAGS.put("settings_wifi_mac_randomization", "true");
-        DEFAULT_FLAGS.put("settings_mainline_module", "true");
+        DEFAULT_FLAGS.put("settings_mainline_module", "false");
         DEFAULT_FLAGS.put("settings_dynamic_android", "false");
         DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 94b9bc0..b1f934a 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -33,6 +33,7 @@
      * Takes a screenshot of the task associated with the given {@param taskId}. Only valid for the
      * current set of task ids provided to the handler.
      */
+    @UnsupportedAppUsage
     ActivityManager.TaskSnapshot screenshotTask(int taskId);
 
     /**
@@ -41,6 +42,7 @@
      * the home activity should be moved to the top. Otherwise, the home activity is hidden and the
      * user is returned to the app.
      */
+    @UnsupportedAppUsage
     void finish(boolean moveHomeToTop);
 
     /**
@@ -50,6 +52,7 @@
      * may register the recents animation input consumer prior to starting the recents animation
      * and then enable it mid-animation to start receiving touch events.
      */
+    @UnsupportedAppUsage
     void setInputConsumerEnabled(boolean enabled);
 
     /**
@@ -58,6 +61,7 @@
     * they can control the SystemUI flags, otherwise the SystemUI flags from home activity will be
     * taken.
     */
+    @UnsupportedAppUsage
     void setAnimationTargetsBehindSystemBars(boolean behindSystemBars);
 
     /**
diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl
index 4cdf664..6e382f4 100644
--- a/core/java/android/view/IRecentsAnimationRunner.aidl
+++ b/core/java/android/view/IRecentsAnimationRunner.aidl
@@ -33,6 +33,7 @@
      * wallpaper not drawing in time, or the handler not finishing the animation within a predefined
      * amount of time.
      */
+    @UnsupportedAppUsage
     void onAnimationCanceled() = 1;
 
     /**
@@ -42,6 +43,7 @@
      * @param minimizedHomeBounds Specifies the bounds of the minimized home app, will be
      *                            {@code null} if the device is not currently in split screen
      */
+    @UnsupportedAppUsage
     void onAnimationStart(in IRecentsAnimationController controller,
             in RemoteAnimationTarget[] apps, in Rect homeContentInsets,
             in Rect minimizedHomeBounds) = 2;
diff --git a/core/java/android/view/IRemoteAnimationFinishedCallback.aidl b/core/java/android/view/IRemoteAnimationFinishedCallback.aidl
index ae58b22..a99162b 100644
--- a/core/java/android/view/IRemoteAnimationFinishedCallback.aidl
+++ b/core/java/android/view/IRemoteAnimationFinishedCallback.aidl
@@ -23,5 +23,6 @@
  * {@hide}
  */
 interface IRemoteAnimationFinishedCallback {
+    @UnsupportedAppUsage
     void onAnimationFinished();
 }
diff --git a/core/java/android/view/IRemoteAnimationRunner.aidl b/core/java/android/view/IRemoteAnimationRunner.aidl
index 1350ebf..73b023c 100644
--- a/core/java/android/view/IRemoteAnimationRunner.aidl
+++ b/core/java/android/view/IRemoteAnimationRunner.aidl
@@ -33,6 +33,7 @@
      * @param apps The list of apps to animate.
      * @param finishedCallback The callback to invoke when the animation is finished.
      */
+    @UnsupportedAppUsage
     void onAnimationStart(in RemoteAnimationTarget[] apps,
             in IRemoteAnimationFinishedCallback finishedCallback);
 
@@ -40,5 +41,6 @@
      * Called when the animation was cancelled. From this point on, any updates onto the leashes
      * won't have any effect anymore.
      */
+    @UnsupportedAppUsage
     void onAnimationCancelled();
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5dc54a5..e32c4e1 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -74,10 +74,13 @@
 
     IWindowSession openSession(in IWindowSessionCallback callback);
 
+    @UnsupportedAppUsage
     void getInitialDisplaySize(int displayId, out Point size);
+    @UnsupportedAppUsage
     void getBaseDisplaySize(int displayId, out Point size);
     void setForcedDisplaySize(int displayId, int width, int height);
     void clearForcedDisplaySize(int displayId);
+    @UnsupportedAppUsage
     int getInitialDisplayDensity(int displayId);
     int getBaseDisplayDensity(int displayId);
     void setForcedDisplayDensityForUser(int displayId, int density, int userId);
@@ -97,17 +100,21 @@
      * used for recents, where generating the thumbnails of the specs takes a non-trivial amount of
      * time, so we want to move that off the critical path for starting the new activity.
      */
+    @UnsupportedAppUsage
     void overridePendingAppTransitionMultiThumbFuture(
             IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback startedCallback,
             boolean scaleUp, int displayId);
+    @UnsupportedAppUsage
     void overridePendingAppTransitionRemote(in RemoteAnimationAdapter remoteAnimationAdapter,
             int displayId);
+    @UnsupportedAppUsage
     void executeAppTransition();
 
     /**
       * Used by system ui to report that recents has shown itself.
       * @deprecated to be removed once prebuilts are updated
       */
+    @UnsupportedAppUsage
     void endProlongedAnimations();
 
     void startFreezingScreen(int exitAnim, int enterAnim);
@@ -119,7 +126,9 @@
     /** @deprecated use Activity.setShowWhenLocked instead. */
     void reenableKeyguard(IBinder token, int userId);
     void exitKeyguardSecurely(IOnKeyguardExitResult callback);
+    @UnsupportedAppUsage
     boolean isKeyguardLocked();
+    @UnsupportedAppUsage
     boolean isKeyguardSecure();
     void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message);
 
@@ -129,9 +138,13 @@
     void closeSystemDialogs(String reason);
 
     // These can only be called with the SET_ANIMATON_SCALE permission.
+    @UnsupportedAppUsage
     float getAnimationScale(int which);
+    @UnsupportedAppUsage
     float[] getAnimationScales();
+    @UnsupportedAppUsage
     void setAnimationScale(int which, float scale);
+    @UnsupportedAppUsage
     void setAnimationScales(in float[] scales);
 
     float getCurrentAnimatorScale();
@@ -150,6 +163,7 @@
     // should be enabled.  The 'enabled' value is null or blank for
     // the system default (differs per build variant) or any valid
     // boolean string as parsed by SystemProperties.getBoolean().
+    @UnsupportedAppUsage
     void setStrictModeVisualIndicatorPreference(String enabled);
 
     /**
@@ -188,6 +202,7 @@
      * Remove a rotation watcher set using watchRotation.
      * @hide
      */
+    @UnsupportedAppUsage
     void removeRotationWatcher(IRotationWatcher watcher);
 
     /**
@@ -203,12 +218,14 @@
      * Equivalent to calling {@link #freezeDisplayRotation(int, int)} with {@link
      * android.view.Display#DEFAULT_DISPLAY} and given rotation.
      */
+    @UnsupportedAppUsage
     void freezeRotation(int rotation);
 
     /**
      * Equivalent to calling {@link #thawDisplayRotation(int)} with {@link
      * android.view.Display#DEFAULT_DISPLAY}.
      */
+    @UnsupportedAppUsage
     void thawRotation();
 
     /**
@@ -286,11 +303,13 @@
     /**
      * Called by System UI to notify of changes to the visibility and height of the shelf.
      */
+    @UnsupportedAppUsage
     void setShelfHeight(boolean visible, int shelfHeight);
 
     /**
      * Called by System UI to enable or disable haptic feedback on the navigation bar buttons.
      */
+    @UnsupportedAppUsage
     void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled);
 
     /**
@@ -298,6 +317,7 @@
      *
      * @param displayId the id of display to check if there is a software navigation bar.
      */
+    @UnsupportedAppUsage
     boolean hasNavigationBar(int displayId);
 
     /**
@@ -308,11 +328,13 @@
     /**
      * Lock the device immediately with the specified options (can be null).
      */
+    @UnsupportedAppUsage
     void lockNow(in Bundle options);
 
     /**
      * Device is in safe mode.
      */
+    @UnsupportedAppUsage
     boolean isSafeModeEnabled();
 
     /**
@@ -340,6 +362,7 @@
      * @return the dock side the current docked stack is at; must be one of the
      *         WindowManagerGlobal.DOCKED_* values
      */
+    @UnsupportedAppUsage
     int getDockedStackSide();
 
     /**
@@ -352,6 +375,7 @@
      * Registers a listener that will be called when the dock divider changes its visibility or when
      * the docked stack gets added/removed.
      */
+    @UnsupportedAppUsage
     void registerDockedStackListener(IDockedStackListener listener);
 
     /**
@@ -378,6 +402,7 @@
     /**
      * Retrieves the current stable insets from the primary display.
      */
+    @UnsupportedAppUsage
     void getStableInsets(int displayId, out Rect outInsets);
 
     /**
@@ -400,6 +425,7 @@
     /**
      * Create an input consumer by name and display id.
      */
+    @UnsupportedAppUsage
     void createInputConsumer(IBinder token, String name, int displayId,
         out InputChannel inputChannel);
 
@@ -407,6 +433,7 @@
      * Destroy an input consumer by name and display id.
      * This method will also dispose the input channels associated with that InputConsumer.
      */
+    @UnsupportedAppUsage
     boolean destroyInputConsumer(String name, int displayId);
 
     /**
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 240aad5..1fcd432 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -46,6 +46,7 @@
     int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             in int viewVisibility, in int layerStackId, out Rect outContentInsets,
             out Rect outStableInsets, out InsetsState insetsState);
+    @UnsupportedAppUsage
     void remove(IWindow window);
 
     /**
@@ -122,6 +123,7 @@
      * completely transparent, allowing it to work with the surface flinger
      * to optimize compositing of this part of the window.
      */
+    @UnsupportedAppUsage
     void setTransparentRegion(IWindow window, in Region region);
 
     /**
@@ -143,11 +145,15 @@
      */
     void getDisplayFrame(IWindow window, out Rect outDisplayFrame);
 
+    @UnsupportedAppUsage
     void finishDrawing(IWindow window);
 
+    @UnsupportedAppUsage
     void setInTouchMode(boolean showFocus);
+    @UnsupportedAppUsage
     boolean getInTouchMode();
 
+    @UnsupportedAppUsage
     boolean performHapticFeedback(int effectId, boolean always);
 
     /**
@@ -166,6 +172,7 @@
      * @param data Data transferred by drag and drop
      * @return Token of drag operation which will be passed to cancelDragAndDrop.
      */
+    @UnsupportedAppUsage
     IBinder performDrag(IWindow window, int flags, in SurfaceControl surface, int touchSource,
             float touchX, float touchY, float thumbCenterX, float thumbCenterY, in ClipData data);
 
@@ -199,6 +206,7 @@
      */
     void setWallpaperPosition(IBinder windowToken, float x, float y, float xstep, float ystep);
 
+    @UnsupportedAppUsage
     void wallpaperOffsetsComplete(IBinder window);
 
     /**
@@ -209,6 +217,7 @@
     Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
             int z, in Bundle extras, boolean sync);
 
+    @UnsupportedAppUsage
     void wallpaperCommandComplete(IBinder window, in Bundle result);
 
     /**
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/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 23f2b8a..7ab9534 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -336,6 +336,7 @@
         return mUnscaledStartDelay;
     }
 
+    @UnsupportedAppUsage
     @Override
     public RenderNodeAnimator setDuration(long duration) {
         checkMutable();
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 ea7f31d..3768aca 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -160,6 +160,7 @@
     private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
     private static native boolean nativeSetAllowedDisplayConfigs(IBinder displayToken,
                                                                  int[] allowedConfigs);
+    private static native int[] nativeGetAllowedDisplayConfigs(IBinder displayToken);
     private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
     private static native SurfaceControl.DisplayPrimaries nativeGetDisplayNativePrimaries(
             IBinder displayToken);
@@ -1538,6 +1539,16 @@
     /**
      * @hide
      */
+    public static int[] getAllowedDisplayConfigs(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        return nativeGetAllowedDisplayConfigs(displayToken);
+    }
+
+    /**
+     * @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..2d452a6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -881,12 +881,6 @@
     private static boolean sAlwaysRemeasureExactly = false;
 
     /**
-     * Relax constraints around whether setLayoutParams() must be called after
-     * modifying the layout params.
-     */
-    private static boolean sLayoutParamsAlwaysChanged = false;
-
-    /**
      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
      * without throwing
      */
@@ -5170,11 +5164,6 @@
             // modes, so we always need to run an additional EXACTLY pass.
             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
 
-            // Prior to N, layout params could change without requiring a
-            // subsequent call to setLayoutParams() and they would usually
-            // work. Partial layout breaks this assumption.
-            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
-
             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
             // On N+, we throw, but that breaks compatibility with apps that use these methods.
             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
@@ -10968,7 +10957,7 @@
     }
 
     void dispatchWindowInsetsAnimationFinished(InsetsAnimation animation) {
-        if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
+        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
             mListenerInfo.mWindowInsetsAnimationListener.onFinished(animation);
         }
     }
@@ -17988,21 +17977,6 @@
     }
 
     /**
-     * Utility method to transform a given Rect by the current matrix of this view.
-     */
-    void transformRect(final Rect rect) {
-        if (!getMatrix().isIdentity()) {
-            RectF boundingRect = mAttachInfo.mTmpTransformRect;
-            boundingRect.set(rect);
-            getMatrix().mapRect(boundingRect);
-            rect.set((int) Math.floor(boundingRect.left),
-                    (int) Math.floor(boundingRect.top),
-                    (int) Math.ceil(boundingRect.right),
-                    (int) Math.ceil(boundingRect.bottom));
-        }
-    }
-
-    /**
      * Used to indicate that the parent of this view should clear its caches. This functionality
      * is used to force the parent to rebuild its display list (when hardware-accelerated),
      * which is necessary when various parent-managed properties of the view change, such as
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/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index e095094..3b60aee 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -207,6 +207,7 @@
     private float mScaleFactor = 1f;
 
     private boolean mShowWallpaper;
+    private boolean mHasRoundedCorners;
 
     private boolean mMore = true;
     private boolean mOneMoreTime = true;
@@ -263,6 +264,8 @@
                 a.getBoolean(com.android.internal.R.styleable.Animation_detachWallpaper, false));
         setShowWallpaper(
                 a.getBoolean(com.android.internal.R.styleable.Animation_showWallpaper, false));
+        setHasRoundedCorners(
+                a.getBoolean(com.android.internal.R.styleable.Animation_hasRoundedCorners, false));
 
         final int resID = a.getResourceId(com.android.internal.R.styleable.Animation_interpolator, 0);
 
@@ -678,6 +681,19 @@
     }
 
     /**
+     * If this is a window animation, the window will have rounded corners matching the display
+     * corner radius.
+     *
+     * @param hasRoundedCorners Whether the window should have rounded corners or not.
+     * @attr ref android.R.styleable#Animation_hasRoundedCorners
+     * @see com.android.internal.policy.ScreenDecorationsUtils#getWindowCornerRadius(Resources)
+     * @hide
+     */
+    public void setHasRoundedCorners(boolean hasRoundedCorners) {
+        mHasRoundedCorners = hasRoundedCorners;
+    }
+
+    /**
      * Gets the acceleration curve type for this animation.
      *
      * @return the {@link Interpolator} associated to this animation
@@ -804,6 +820,16 @@
     }
 
     /**
+     * @return if a window animation should have rounded corners or not.
+     *
+     * @attr ref android.R.styleable#Animation_hasRoundedCorners
+     * @hide
+     */
+    public boolean hasRoundedCorners() {
+        return mHasRoundedCorners;
+    }
+
+    /**
      * <p>Indicates whether or not this animation will affect the transformation
      * matrix. For instance, a fade animation will not affect the matrix whereas
      * a scale animation will.</p>
diff --git a/core/java/android/webkit/IWebViewUpdateService.aidl b/core/java/android/webkit/IWebViewUpdateService.aidl
index dbca7ff..10cfea1 100644
--- a/core/java/android/webkit/IWebViewUpdateService.aidl
+++ b/core/java/android/webkit/IWebViewUpdateService.aidl
@@ -51,6 +51,7 @@
      * DevelopmentSettings uses this to get the current available WebView
      * providers (to display as choices to the user).
      */
+    @UnsupportedAppUsage
     WebViewProviderInfo[] getValidWebViewPackages();
 
     /**
@@ -61,6 +62,7 @@
     /**
      * Used by DevelopmentSetting to get the name of the WebView provider currently in use.
      */
+    @UnsupportedAppUsage
     String getCurrentWebViewPackageName();
 
     /**
@@ -72,6 +74,7 @@
      * Used by Settings to determine whether a certain package can be enabled/disabled by the user -
      * the package should not be modifiable in this way if it is a fallback package.
      */
+    @UnsupportedAppUsage
     boolean isFallbackPackage(String packageName);
 
     /**
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/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java
index dd6a27b8f..7a5b7e8 100644
--- a/core/java/android/widget/ZoomControls.java
+++ b/core/java/android/widget/ZoomControls.java
@@ -30,7 +30,11 @@
 
 /**
  * The {@code ZoomControls} class displays a simple set of controls used for zooming and
- * provides callbacks to register for events. */
+ * provides callbacks to register for events.
+ * @deprecated This functionality and UI is better handled with custom views and layouts
+ * rather than a dedicated zoom-control widget
+ */
+@Deprecated
 @Widget
 public class ZoomControls extends LinearLayout {
 
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 8a90cad..c096961 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -32,6 +32,7 @@
     int noteOperation(int code, int uid, String packageName);
     int startOperation(IBinder token, int code, int uid, String packageName,
             boolean startIfModeDefault);
+    @UnsupportedAppUsage
     void finishOperation(IBinder token, int code, int uid, String packageName);
     void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
     void stopWatchingMode(IAppOpsCallback callback);
@@ -42,7 +43,9 @@
 
     // Remaining methods are only used in Java.
     int checkPackage(int uid, String packageName);
+    @UnsupportedAppUsage
     List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
+    @UnsupportedAppUsage
     List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
     void getHistoricalOps(int uid, String packageName, in List<String> ops, long beginTimeMillis,
             long endTimeMillis, in RemoteCallback callback);
@@ -55,7 +58,9 @@
     void clearHistory();
     List<AppOpsManager.PackageOps> getUidOps(int uid, in int[] ops);
     void setUidMode(int code, int uid, int mode);
+    @UnsupportedAppUsage
     void setMode(int code, int uid, String packageName, int mode);
+    @UnsupportedAppUsage
     void resetAllModes(int reqUserId, String reqPackageName);
     int checkAudioOperation(int code, int usage, int uid, String packageName);
     void setAudioRestriction(int code, int usage, int uid, int mode, in String[] exceptionPackages);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index d7514d1..114d31f 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -49,11 +49,13 @@
     void noteResetFlashlight();
 
     // Remaining methods are only used in Java.
+    @UnsupportedAppUsage
     byte[] getStatistics();
 
     ParcelFileDescriptor getStatisticsStream();
 
     // Return true if we see the battery as currently charging.
+    @UnsupportedAppUsage
     boolean isCharging();
 
     // Return the computed amount of time remaining on battery, in milliseconds.
@@ -62,6 +64,7 @@
 
     // Return the computed amount of time remaining to fully charge, in milliseconds.
     // Returns -1 if nothing could be computed.
+    @UnsupportedAppUsage
     long computeChargeTimeRemaining();
 
     void noteEvent(int code, String name, int uid);
@@ -131,6 +134,7 @@
     void noteDeviceIdleMode(int mode, String activeReason, int activeUid);
     void setBatteryState(int status, int health, int plugType, int level, int temp, int volt,
             int chargeUAh, int chargeFullUAh);
+    @UnsupportedAppUsage
     long getAwakeTimeBattery();
     long getAwakeTimePlugged();
 
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 9ce7ed1..420749e 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -51,6 +51,7 @@
      * @param keyphraseId The unique identifier for the keyphrase.
      * @param bcp47Locale The BCP47 language tag  for the keyphrase's locale.
      */
+    @UnsupportedAppUsage
     SoundTrigger.KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, in String bcp47Locale);
     /**
      * Add/Update the given keyphrase sound model.
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index f9bf373..6d1d1ab 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -42,6 +42,7 @@
     void deleteAppWidgetId(String callingPackage, int appWidgetId);
     void deleteHost(String packageName, int hostId);
     void deleteAllHosts();
+    @UnsupportedAppUsage
     RemoteViews getAppWidgetViews(String callingPackage, int appWidgetId);
     int[] getAppWidgetIdsForHost(String callingPackage, int hostId);
     IntentSender createAppWidgetConfigIntentSender(String callingPackage, int appWidgetId,
@@ -63,11 +64,14 @@
     AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId);
     boolean hasBindAppWidgetPermission(in String packageName, int userId);
     void setBindAppWidgetPermission(in String packageName, int userId, in boolean permission);
+    @UnsupportedAppUsage
     boolean bindAppWidgetId(in String callingPackage, int appWidgetId,
             int providerProfileId, in ComponentName providerComponent, in Bundle options);
+    @UnsupportedAppUsage
     boolean bindRemoteViewsService(String callingPackage, int appWidgetId, in Intent intent,
             IApplicationThread caller, IBinder token, IServiceConnection connection, int flags);
 
+    @UnsupportedAppUsage
     int[] getAppWidgetIds(in ComponentName providerComponent);
     boolean isBoundWidgetPackage(String packageName, int userId);
     boolean requestPinAppWidget(String packageName, in ComponentName providerComponent,
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
new file mode 100644
index 0000000..74c6651
--- /dev/null
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -0,0 +1,85 @@
+/**
+ * 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.internal.config.sysui;
+
+/**
+ * Keeps the flags related to the SystemUI namespace in {@link DeviceConfig}.
+ *
+ * @hide
+ */
+public final class SystemUiDeviceConfigFlags {
+
+    // Flags related to NotificationAssistant
+
+    /**
+     * Whether the Notification Assistant should generate replies for notifications.
+     */
+    public static final String NAS_GENERATE_REPLIES = "nas_generate_replies";
+
+    /**
+     * Whether the Notification Assistant should generate contextual actions for notifications.
+     */
+    public static final String NAS_GENERATE_ACTIONS = "nas_generate_actions";
+
+    /**
+     * The maximum number of messages the Notification Assistant should extract from a
+     * conversation when constructing responses for that conversation.
+     */
+    public static final String NAS_MAX_MESSAGES_TO_EXTRACT = "nas_max_messages_to_extract";
+
+    /**
+     * The maximum number of suggestions the Notification Assistant should provide for a
+     * messaging conversation.
+     */
+    public static final String NAS_MAX_SUGGESTIONS = "nas_max_suggestions";
+
+    // Flags related to Smart Suggestions - these are read in SmartReplyConstants.
+
+    /** (boolean) Whether to enable smart suggestions in notifications. */
+    public static final String SSIN_ENABLED = "ssin_enabled";
+
+    /**
+     * (boolean) Whether apps need to target at least P to provide their own smart replies (this
+     * doesn't apply to actions!).
+     */
+    public static final String SSIN_REQUIRES_TARGETING_P = "ssin_requires_targeting_p";
+
+    /**
+     * (int) The number of times we'll try to find a better line-break for double-line smart
+     * suggestion buttons.
+     */
+    public static final String SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS =
+            "ssin_max_squeeze_remeasure_attempts";
+
+    /** (boolean) Whether to let the user edit smart replies before sending. */
+    public static final String SSIN_EDIT_CHOICES_BEFORE_SENDING =
+            "ssin_edit_choices_before_sending";
+
+    /** (boolean) Whether smart suggestions should be enabled in heads-up notifications. */
+    public static final String SSIN_SHOW_IN_HEADS_UP = "ssin_show_in_heads_up";
+
+    /** (int) Minimum number of system generated replies to show in a notification. */
+    public static final String SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES =
+            "ssin_min_num_system_generated_replies";
+
+    /**
+     * (int) Maximum number of actions to show in a notification, -1 if there shouldn't be a limit
+     */
+    public static final String SSIN_MAX_NUM_ACTIONS = "ssin_max_num_actions";
+
+    private SystemUiDeviceConfigFlags() { }
+}
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/os/IDropBoxManagerService.aidl b/core/java/com/android/internal/os/IDropBoxManagerService.aidl
index 70844ee..5e60394 100644
--- a/core/java/com/android/internal/os/IDropBoxManagerService.aidl
+++ b/core/java/com/android/internal/os/IDropBoxManagerService.aidl
@@ -37,5 +37,6 @@
     boolean isTagEnabled(String tag);
 
     /** @see DropBoxManager#getNextEntry */
+    @UnsupportedAppUsage
     DropBoxManager.Entry getNextEntry(String tag, long millis, String packageName);
 }
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index e5d5685..54f31f9 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -88,8 +88,10 @@
      */
     void onScreenTurnedOff();
 
+    @UnsupportedAppUsage
     void setKeyguardEnabled(boolean enabled);
     void onSystemReady();
+    @UnsupportedAppUsage
     void doKeyguardTimeout(in Bundle options);
     void setSwitchingUser(boolean switching);
     void setCurrentUser(int userId);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index bfb5084..3437614 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -31,16 +31,21 @@
 /** @hide */
 interface IStatusBarService
 {
+    @UnsupportedAppUsage
     void expandNotificationsPanel();
+    @UnsupportedAppUsage
     void collapsePanels();
     void togglePanel();
+    @UnsupportedAppUsage
     void disable(int what, IBinder token, String pkg);
     void disableForUser(int what, IBinder token, String pkg, int userId);
     void disable2(int what, IBinder token, String pkg);
     void disable2ForUser(int what, IBinder token, String pkg, int userId);
     int[] getDisableFlags(IBinder token, int userId);
     void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription);
+    @UnsupportedAppUsage
     void setIconVisibility(String slot, boolean visible);
+    @UnsupportedAppUsage
     void removeIcon(String slot);
     // TODO(b/117478341): support back button change when IME is showing on a external display.
     void setImeWindowStatus(in IBinder token, int vis, int backDisposition,
@@ -87,6 +92,7 @@
     void addTile(in ComponentName tile);
     void remTile(in ComponentName tile);
     void clickTile(in ComponentName tile);
+    @UnsupportedAppUsage
     void handleSystemKey(in int key);
 
     /**
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 9a77802..3be7c3e 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -30,23 +30,31 @@
 
 /** {@hide} */
 interface ILockSettings {
+    @UnsupportedAppUsage
     void setBoolean(in String key, in boolean value, in int userId);
+    @UnsupportedAppUsage
     void setLong(in String key, in long value, in int userId);
+    @UnsupportedAppUsage
     void setString(in String key, in String value, in int userId);
+    @UnsupportedAppUsage
     boolean getBoolean(in String key, in boolean defaultValue, in int userId);
+    @UnsupportedAppUsage
     long getLong(in String key, in long defaultValue, in int userId);
+    @UnsupportedAppUsage
     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);
+    @UnsupportedAppUsage
     boolean havePattern(int userId);
+    @UnsupportedAppUsage
     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/IRemoteViewsFactory.aidl b/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
index 7317ecf..d6efca5 100644
--- a/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
+++ b/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
@@ -21,15 +21,23 @@
 
 /** {@hide} */
 interface IRemoteViewsFactory {
+    @UnsupportedAppUsage
     void onDataSetChanged();
     oneway void onDataSetChangedAsync();
     oneway void onDestroy(in Intent intent);
+    @UnsupportedAppUsage
     int getCount();
+    @UnsupportedAppUsage
     RemoteViews getViewAt(int position);
+    @UnsupportedAppUsage
     RemoteViews getLoadingView();
+    @UnsupportedAppUsage
     int getViewTypeCount();
+    @UnsupportedAppUsage
     long getItemId(int position);
+    @UnsupportedAppUsage
     boolean hasStableIds();
+    @UnsupportedAppUsage
     boolean isCreated();
 }
 
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.bp b/core/jni/Android.bp
index c309f27..cd34d2e 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -165,6 +165,8 @@
         "android_media_AudioTrack.cpp",
         "android_media_AudioAttributes.cpp",
         "android_media_AudioProductStrategies.cpp",
+        "android_media_AudioVolumeGroups.cpp",
+        "android_media_AudioVolumeGroupCallback.cpp",
         "android_media_DeviceCallback.cpp",
         "android_media_JetPlayer.cpp",
         "android_media_MediaMetricsJNI.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 16517bf..da27852 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -110,6 +110,8 @@
 extern int register_android_media_AudioTrack(JNIEnv *env);
 extern int register_android_media_AudioAttributes(JNIEnv *env);
 extern int register_android_media_AudioProductStrategies(JNIEnv *env);
+extern int register_android_media_AudioVolumeGroups(JNIEnv *env);
+extern int register_android_media_AudioVolumeGroupChangeHandler(JNIEnv *env);
 extern int register_android_media_MicrophoneInfo(JNIEnv *env);
 extern int register_android_media_JetPlayer(JNIEnv *env);
 extern int register_android_media_ToneGenerator(JNIEnv *env);
@@ -1524,6 +1526,8 @@
     REG_JNI(register_android_media_AudioTrack),
     REG_JNI(register_android_media_AudioAttributes),
     REG_JNI(register_android_media_AudioProductStrategies),
+    REG_JNI(register_android_media_AudioVolumeGroups),
+    REG_JNI(register_android_media_AudioVolumeGroupChangeHandler),
     REG_JNI(register_android_media_JetPlayer),
     REG_JNI(register_android_media_MicrophoneInfo),
     REG_JNI(register_android_media_RemoteDisplay),
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 8a28034..c7805ea 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -221,12 +221,23 @@
 
     jobject jAudioFormat = NULL;
     if (event->trigger_in_data || event->capture_available) {
+        jint channelMask = (jint)audio_channel_mask_get_bits(event->audio_config.channel_mask);
+        jint channelIndexMask = (jint)AUDIO_CHANNEL_NONE;
+
+        switch (audio_channel_mask_get_representation(event->audio_config.channel_mask)) {
+        case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+            channelIndexMask = channelMask;
+            channelMask = (jint)AUDIO_CHANNEL_NONE;
+            break;
+        default:
+            break;
+        }
         jAudioFormat = env->NewObject(gAudioFormatClass,
                                     gAudioFormatCstor,
                                     audioFormatFromNative(event->audio_config.format),
                                     event->audio_config.sample_rate,
-                                    inChannelMaskFromNative(event->audio_config.channel_mask),
-                                    (jint)0 /* channelIndexMask */);
+                                    channelMask,
+                                    channelIndexMask);
 
     }
     if (event->type == SOUND_MODEL_TYPE_KEYPHRASE) {
diff --git a/core/jni/android_media_AudioProductStrategies.cpp b/core/jni/android_media_AudioProductStrategies.cpp
index a18e80a..822b74a 100644
--- a/core/jni/android_media_AudioProductStrategies.cpp
+++ b/core/jni/android_media_AudioProductStrategies.cpp
@@ -57,7 +57,7 @@
 static jclass gAudioAttributesGroupClass;
 static jmethodID gAudioAttributesGroupCstor;
 static struct {
-    jfieldID    mGroupId;
+    jfieldID    mVolumeGroupId;
     jfieldID    mLegacyStreamType;
     jfieldID    mAudioAttributes;
 } gAudioAttributesGroupsFields;
@@ -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)
@@ -227,8 +249,8 @@
     gAudioAttributesGroupClass = MakeGlobalRefOrDie(env, audioAttributesGroupClass);
     gAudioAttributesGroupCstor = GetMethodIDOrDie(env, audioAttributesGroupClass, "<init>",
                                                   "(II[Landroid/media/AudioAttributes;)V");
-    gAudioAttributesGroupsFields.mGroupId = GetFieldIDOrDie(
-                env, audioAttributesGroupClass, "mGroupId", "I");
+    gAudioAttributesGroupsFields.mVolumeGroupId = GetFieldIDOrDie(
+                env, audioAttributesGroupClass, "mVolumeGroupId", "I");
     gAudioAttributesGroupsFields.mLegacyStreamType = GetFieldIDOrDie(
                 env, audioAttributesGroupClass, "mLegacyStreamType", "I");
     gAudioAttributesGroupsFields.mAudioAttributes = GetFieldIDOrDie(
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index bd998999..1a90ebf 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -573,6 +573,81 @@
 }
 
 static jint
+android_media_AudioSystem_setVolumeIndexForAttributes(JNIEnv *env,
+                                                      jobject thiz,
+                                                      jobject jaa,
+                                                      jint index,
+                                                      jint device)
+{
+    // read the AudioAttributes values
+    JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
+    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
+    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+        return jStatus;
+    }
+    return (jint) check_AudioSystem_Command(
+            AudioSystem::setVolumeIndexForAttributes(*(paa.get()), index, (audio_devices_t)device));
+}
+
+static jint
+android_media_AudioSystem_getVolumeIndexForAttributes(JNIEnv *env,
+                                                      jobject thiz,
+                                                      jobject jaa,
+                                                      jint device)
+{
+    // read the AudioAttributes values
+    JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
+    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
+    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+        return jStatus;
+    }
+    int index;
+    if (AudioSystem::getVolumeIndexForAttributes(*(paa.get()), index, (audio_devices_t)device)
+            != NO_ERROR) {
+        index = -1;
+    }
+    return (jint) index;
+}
+
+static jint
+android_media_AudioSystem_getMinVolumeIndexForAttributes(JNIEnv *env,
+                                                         jobject thiz,
+                                                         jobject jaa)
+{
+    // read the AudioAttributes values
+    JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
+    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
+    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+        return jStatus;
+    }
+    int index;
+    if (AudioSystem::getMinVolumeIndexForAttributes(*(paa.get()), index)
+            != NO_ERROR) {
+        index = -1;
+    }
+    return (jint) index;
+}
+
+static jint
+android_media_AudioSystem_getMaxVolumeIndexForAttributes(JNIEnv *env,
+                                                         jobject thiz,
+                                                         jobject jaa)
+{
+    // read the AudioAttributes values
+    JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
+    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
+    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+        return jStatus;
+    }
+    int index;
+    if (AudioSystem::getMaxVolumeIndexForAttributes(*(paa.get()), index)
+            != NO_ERROR) {
+        index = -1;
+    }
+    return (jint) index;
+}
+
+static jint
 android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
 {
     return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
@@ -2172,6 +2247,10 @@
     {"initStreamVolume",    "(III)I",   (void *)android_media_AudioSystem_initStreamVolume},
     {"setStreamVolumeIndex","(III)I",   (void *)android_media_AudioSystem_setStreamVolumeIndex},
     {"getStreamVolumeIndex","(II)I",    (void *)android_media_AudioSystem_getStreamVolumeIndex},
+    {"setVolumeIndexForAttributes","(Landroid/media/AudioAttributes;II)I",   (void *)android_media_AudioSystem_setVolumeIndexForAttributes},
+    {"getVolumeIndexForAttributes","(Landroid/media/AudioAttributes;I)I",    (void *)android_media_AudioSystem_getVolumeIndexForAttributes},
+    {"getMinVolumeIndexForAttributes","(Landroid/media/AudioAttributes;)I",    (void *)android_media_AudioSystem_getMinVolumeIndexForAttributes},
+    {"getMaxVolumeIndexForAttributes","(Landroid/media/AudioAttributes;)I",    (void *)android_media_AudioSystem_getMaxVolumeIndexForAttributes},
     {"setMasterVolume",     "(F)I",     (void *)android_media_AudioSystem_setMasterVolume},
     {"getMasterVolume",     "()F",      (void *)android_media_AudioSystem_getMasterVolume},
     {"setMasterMute",       "(Z)I",     (void *)android_media_AudioSystem_setMasterMute},
diff --git a/core/jni/android_media_AudioVolumeGroupCallback.cpp b/core/jni/android_media_AudioVolumeGroupCallback.cpp
new file mode 100644
index 0000000..cb4ddbd
--- /dev/null
+++ b/core/jni/android_media_AudioVolumeGroupCallback.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "AudioVolumeGroupCallback-JNI"
+
+#include <utils/Log.h>
+#include <nativehelper/JNIHelp.h>
+#include "core_jni_helpers.h"
+
+#include "android_media_AudioVolumeGroupCallback.h"
+
+
+// ----------------------------------------------------------------------------
+using namespace android;
+
+static const char* const kAudioVolumeGroupChangeHandlerClassPathName =
+        "android/media/audiopolicy/AudioVolumeGroupChangeHandler";
+
+static struct {
+    jfieldID    mJniCallback;
+} gAudioVolumeGroupChangeHandlerFields;
+
+static struct {
+    jmethodID    postEventFromNative;
+} gAudioVolumeGroupChangeHandlerMethods;
+
+static Mutex gLock;
+
+JNIAudioVolumeGroupCallback::JNIAudioVolumeGroupCallback(JNIEnv* env,
+                                                         jobject thiz,
+                                                         jobject weak_thiz)
+{
+    jclass clazz = env->GetObjectClass(thiz);
+    if (clazz == NULL) {
+        ALOGE("Can't find class %s", kAudioVolumeGroupChangeHandlerClassPathName);
+        return;
+    }
+    mClass = (jclass)env->NewGlobalRef(clazz);
+
+    // We use a weak reference so the AudioVolumeGroupChangeHandler object can be garbage collected.
+    // The reference is only used as a proxy for callbacks.
+    mObject  = env->NewGlobalRef(weak_thiz);
+}
+
+JNIAudioVolumeGroupCallback::~JNIAudioVolumeGroupCallback()
+{
+    // remove global references
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (env == NULL) {
+        return;
+    }
+    env->DeleteGlobalRef(mObject);
+    env->DeleteGlobalRef(mClass);
+}
+
+void JNIAudioVolumeGroupCallback::onAudioVolumeGroupChanged(volume_group_t group, int flags)
+{
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (env == NULL) {
+        return;
+    }
+    ALOGV("%s volume group id %d", __FUNCTION__, group);
+    env->CallStaticVoidMethod(mClass,
+                              gAudioVolumeGroupChangeHandlerMethods.postEventFromNative,
+                              mObject,
+                              AUDIOVOLUMEGROUP_EVENT_VOLUME_CHANGED, group, flags, NULL);
+    if (env->ExceptionCheck()) {
+        ALOGW("An exception occurred while notifying an event.");
+        env->ExceptionClear();
+    }
+}
+
+void JNIAudioVolumeGroupCallback::onServiceDied()
+{
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (env == NULL) {
+        return;
+    }
+    env->CallStaticVoidMethod(mClass,
+                              gAudioVolumeGroupChangeHandlerMethods.postEventFromNative,
+                              mObject,
+                              AUDIOVOLUMEGROUP_EVENT_SERVICE_DIED, 0, 0, NULL);
+    if (env->ExceptionCheck()) {
+        ALOGW("An exception occurred while notifying an event.");
+        env->ExceptionClear();
+    }
+}
+
+static
+sp<JNIAudioVolumeGroupCallback> setJniCallback(JNIEnv* env,
+                                               jobject thiz,
+                                               const sp<JNIAudioVolumeGroupCallback>& callback)
+{
+    Mutex::Autolock l(gLock);
+    sp<JNIAudioVolumeGroupCallback> old = (JNIAudioVolumeGroupCallback*)env->GetLongField(
+                thiz, gAudioVolumeGroupChangeHandlerFields.mJniCallback);
+    if (callback.get()) {
+        callback->incStrong((void*)setJniCallback);
+    }
+    if (old != 0) {
+        old->decStrong((void*)setJniCallback);
+    }
+    env->SetLongField(thiz, gAudioVolumeGroupChangeHandlerFields.mJniCallback,
+                      (jlong)callback.get());
+    return old;
+}
+
+static void
+android_media_AudioVolumeGroupChangeHandler_eventHandlerSetup(JNIEnv *env,
+                                                              jobject thiz,
+                                                              jobject weak_this)
+{
+    ALOGV("%s", __FUNCTION__);
+    sp<JNIAudioVolumeGroupCallback> callback =
+            new JNIAudioVolumeGroupCallback(env, thiz, weak_this);
+
+    if (AudioSystem::addAudioVolumeGroupCallback(callback) == NO_ERROR) {
+        setJniCallback(env, thiz, callback);
+    }
+}
+
+static void
+android_media_AudioVolumeGroupChangeHandler_eventHandlerFinalize(JNIEnv *env, jobject thiz)
+{
+    ALOGV("%s", __FUNCTION__);
+    sp<JNIAudioVolumeGroupCallback> callback = setJniCallback(env, thiz, 0);
+    if (callback != 0) {
+        AudioSystem::removeAudioVolumeGroupCallback(callback);
+    }
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+    {"native_setup", "(Ljava/lang/Object;)V",
+        (void *)android_media_AudioVolumeGroupChangeHandler_eventHandlerSetup},
+    {"native_finalize",  "()V",
+        (void *)android_media_AudioVolumeGroupChangeHandler_eventHandlerFinalize},
+};
+
+int register_android_media_AudioVolumeGroupChangeHandler(JNIEnv *env)
+{
+    jclass audioVolumeGroupChangeHandlerClass =
+            FindClassOrDie(env, kAudioVolumeGroupChangeHandlerClassPathName);
+    gAudioVolumeGroupChangeHandlerMethods.postEventFromNative =
+            GetStaticMethodIDOrDie(env, audioVolumeGroupChangeHandlerClass, "postEventFromNative",
+                                   "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+
+    gAudioVolumeGroupChangeHandlerFields.mJniCallback =
+            GetFieldIDOrDie(env, audioVolumeGroupChangeHandlerClass, "mJniCallback", "J");
+
+    env->DeleteLocalRef(audioVolumeGroupChangeHandlerClass);
+
+    return RegisterMethodsOrDie(env,
+                                kAudioVolumeGroupChangeHandlerClassPathName,
+                                gMethods,
+                                NELEM(gMethods));
+}
+
diff --git a/core/jni/android_media_AudioVolumeGroupCallback.h b/core/jni/android_media_AudioVolumeGroupCallback.h
new file mode 100644
index 0000000..de06549
--- /dev/null
+++ b/core/jni/android_media_AudioVolumeGroupCallback.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <system/audio.h>
+#include <media/AudioSystem.h>
+
+namespace android {
+
+// keep in sync with AudioManager.AudioVolumeGroupChangeHandler.java
+#define AUDIOVOLUMEGROUP_EVENT_VOLUME_CHANGED      1000
+#define AUDIOVOLUMEGROUP_EVENT_SERVICE_DIED        1001
+
+class JNIAudioVolumeGroupCallback: public AudioSystem::AudioVolumeGroupCallback
+{
+public:
+    JNIAudioVolumeGroupCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
+    ~JNIAudioVolumeGroupCallback();
+
+    void onAudioVolumeGroupChanged(volume_group_t group, int flags) override;
+    void onServiceDied() override;
+
+private:
+    void sendEvent(int event);
+
+    jclass      mClass; /**< Reference to AudioVolumeGroupChangeHandler class. */
+    jobject     mObject; /**< Weak ref to AudioVolumeGroupChangeHandler object to call on. */
+};
+
+} // namespace android
diff --git a/core/jni/android_media_AudioVolumeGroups.cpp b/core/jni/android_media_AudioVolumeGroups.cpp
new file mode 100644
index 0000000..64f0c1e
--- /dev/null
+++ b/core/jni/android_media_AudioVolumeGroups.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "AudioVolumeGroups-JNI"
+
+#include <inttypes.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include "core_jni_helpers.h"
+
+#include <utils/Log.h>
+#include <vector>
+
+#include <media/AudioSystem.h>
+#include <media/AudioPolicy.h>
+
+#include <nativehelper/ScopedUtfChars.h>
+
+#include "android_media_AudioAttributes.h"
+#include "android_media_AudioErrors.h"
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+static const char* const kClassPathName = "android/media/audiopolicy/AudioVolumeGroups";
+static const char* const kAudioVolumeGroupClassPathName =
+        "android/media/audiopolicy/AudioVolumeGroup";
+
+static jclass gAudioVolumeGroupClass;
+static jmethodID gAudioVolumeGroupCstor;
+static struct {
+    jfieldID    mName;
+    jfieldID    mId;
+} gAudioVolumeGroupFields;
+
+static jclass gArrayListClass;
+static jmethodID gArrayListCstor;
+static struct {
+    jmethodID    add;
+    jmethodID    toArray;
+} gArrayListMethods;
+
+
+static jint convertAudioVolumeGroupsFromNative(
+        JNIEnv *env, jobject *jGroup, const AudioVolumeGroup &group)
+{
+    jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
+    jstring jName = NULL;
+    jint Id = NULL;
+
+    jintArray jLegacyStreamTypes = NULL;
+    jobjectArray jAudioAttributes = NULL;
+    jint numAttributes;
+    jobject jAudioAttribute = NULL;
+
+    jName = env->NewStringUTF(group.getName().c_str());
+    Id = static_cast<jint>(group.getId());
+
+    // Legacy stream types array
+    jLegacyStreamTypes = env->NewIntArray(group.getStreamTypes().size());
+    if (jLegacyStreamTypes == NULL) {
+        jStatus = (jint)AUDIO_JAVA_ERROR;
+        goto exit;
+    }
+    for (size_t streamIndex = 0; streamIndex < group.getStreamTypes().size(); streamIndex++) {
+        jint jStream = group.getStreamTypes()[streamIndex];
+        env->SetIntArrayRegion(jLegacyStreamTypes, streamIndex, 1, &jStream);
+    }
+
+    // Audio Attributes array
+    numAttributes = group.getAudioAttributes().size();
+    jStatus = JNIAudioAttributeHelper::getJavaArray(env, &jAudioAttributes, numAttributes);
+    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+        goto exit;
+    }
+
+    for (size_t j = 0; j < static_cast<size_t>(numAttributes); j++) {
+        auto attributes = group.getAudioAttributes()[j];
+
+        jStatus = JNIAudioAttributeHelper::nativeToJava(env, &jAudioAttribute, attributes);
+        if (jStatus != AUDIO_JAVA_SUCCESS) {
+            goto exit;
+        }
+        env->SetObjectArrayElement(jAudioAttributes, j, jAudioAttribute);
+    }
+
+    *jGroup = env->NewObject(gAudioVolumeGroupClass, gAudioVolumeGroupCstor,
+                             jName, Id, jAudioAttributes, jLegacyStreamTypes);
+exit:
+    if (jName != NULL) {
+        env->DeleteLocalRef(jName);
+    }
+    return jStatus;
+}
+
+static jint
+android_media_AudioSystem_listAudioVolumeGroups(JNIEnv *env, jobject clazz, jobject jVolumeGroups)
+{
+    if (env == NULL) {
+        return AUDIO_JAVA_DEAD_OBJECT;
+    }
+    if (jVolumeGroups == NULL) {
+        ALOGE("listAudioVolumeGroups NULL AudioVolumeGroups");
+        return (jint)AUDIO_JAVA_BAD_VALUE;
+    }
+    if (!env->IsInstanceOf(jVolumeGroups, gArrayListClass)) {
+        ALOGE("listAudioVolumeGroups not an arraylist");
+        return (jint)AUDIO_JAVA_BAD_VALUE;
+    }
+
+    status_t status;
+    AudioVolumeGroupVector groups;
+    jint jStatus;
+    jobject jGroup = NULL;
+
+    status = AudioSystem::listAudioVolumeGroups(groups);
+    if (status != NO_ERROR) {
+        ALOGE("AudioSystem::listAudioVolumeGroups error %d", status);
+        return nativeToJavaStatus(status);
+    }
+    for (const auto &group : groups) {
+        jStatus = convertAudioVolumeGroupsFromNative(env, &jGroup, group);
+        if (jStatus != AUDIO_JAVA_SUCCESS) {
+            goto exit;
+        }
+        env->CallBooleanMethod(jVolumeGroups, gArrayListMethods.add, jGroup);
+    }
+exit:
+    if (jGroup != NULL) {
+        env->DeleteLocalRef(jGroup);
+    }
+    return jStatus;
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+    {"native_list_audio_volume_groups", "(Ljava/util/ArrayList;)I",
+                        (void *)android_media_AudioSystem_listAudioVolumeGroups},
+};
+
+int register_android_media_AudioVolumeGroups(JNIEnv *env)
+{
+    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
+    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
+    gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V");
+    gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
+    gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass,
+                                                 "toArray", "()[Ljava/lang/Object;");
+
+    jclass audioVolumeGroupClass = FindClassOrDie(env, kAudioVolumeGroupClassPathName);
+    gAudioVolumeGroupClass = MakeGlobalRefOrDie(env, audioVolumeGroupClass);
+    gAudioVolumeGroupCstor = GetMethodIDOrDie(
+                env, audioVolumeGroupClass, "<init>",
+                "(Ljava/lang/String;I[Landroid/media/AudioAttributes;[I)V");
+
+    gAudioVolumeGroupFields.mName = GetFieldIDOrDie(
+                env, audioVolumeGroupClass, "mName", "Ljava/lang/String;");
+    gAudioVolumeGroupFields.mId = GetFieldIDOrDie(
+                env, audioVolumeGroupClass, "mId", "I");
+
+    env->DeleteLocalRef(audioVolumeGroupClass);
+
+    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
+}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 464f249..a900294 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -58,8 +58,6 @@
 
 namespace android {
 
-using ui::Dataspace;
-
 static const char* const OutOfResourcesException =
     "android/view/Surface$OutOfResourcesException";
 
@@ -129,135 +127,17 @@
 }
 
 int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) {
-
-    switch(f) {
-        case PublicFormat::JPEG:
-        case PublicFormat::DEPTH_POINT_CLOUD:
-        case PublicFormat::DEPTH_JPEG:
-        case PublicFormat::HEIC:
-            return HAL_PIXEL_FORMAT_BLOB;
-        case PublicFormat::DEPTH16:
-            return HAL_PIXEL_FORMAT_Y16;
-        case PublicFormat::RAW_SENSOR:
-        case PublicFormat::RAW_DEPTH:
-            return HAL_PIXEL_FORMAT_RAW16;
-        default:
-            // Most formats map 1:1
-            return static_cast<int>(f);
-    }
+    return mapPublicFormatToHalFormat(f);
 }
 
 android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
         PublicFormat f) {
-    Dataspace dataspace;
-    switch(f) {
-        case PublicFormat::JPEG:
-            dataspace = Dataspace::V0_JFIF;
-            break;
-        case PublicFormat::DEPTH_POINT_CLOUD:
-        case PublicFormat::DEPTH16:
-        case PublicFormat::RAW_DEPTH:
-            dataspace = Dataspace::DEPTH;
-            break;
-        case PublicFormat::RAW_SENSOR:
-        case PublicFormat::RAW_PRIVATE:
-        case PublicFormat::RAW10:
-        case PublicFormat::RAW12:
-            dataspace = Dataspace::ARBITRARY;
-            break;
-        case PublicFormat::YUV_420_888:
-        case PublicFormat::NV21:
-        case PublicFormat::YV12:
-            dataspace = Dataspace::V0_JFIF;
-            break;
-        case PublicFormat::DEPTH_JPEG:
-            dataspace = Dataspace::DYNAMIC_DEPTH;
-            break;
-        case PublicFormat::HEIC:
-            dataspace = Dataspace::HEIF;
-            break;
-        default:
-            // Most formats map to UNKNOWN
-            dataspace = Dataspace::UNKNOWN;
-            break;
-    }
-    return static_cast<android_dataspace>(dataspace);
+    return mapPublicFormatToHalDataspace(f);
 }
 
 PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
         int format, android_dataspace dataSpace) {
-    Dataspace ds = static_cast<Dataspace>(dataSpace);
-    switch(format) {
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-        case HAL_PIXEL_FORMAT_RGBA_FP16:
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-        case HAL_PIXEL_FORMAT_RGB_888:
-        case HAL_PIXEL_FORMAT_RGB_565:
-        case HAL_PIXEL_FORMAT_Y8:
-        case HAL_PIXEL_FORMAT_RAW10:
-        case HAL_PIXEL_FORMAT_RAW12:
-        case HAL_PIXEL_FORMAT_YCbCr_420_888:
-        case HAL_PIXEL_FORMAT_YV12:
-            // Enums overlap in both name and value
-            return static_cast<PublicFormat>(format);
-        case HAL_PIXEL_FORMAT_RAW16:
-            switch (ds) {
-                case Dataspace::DEPTH:
-                  return PublicFormat::RAW_DEPTH;
-                default:
-                  return PublicFormat::RAW_SENSOR;
-            }
-        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
-            // Name differs, though value is the same
-            return PublicFormat::RAW_PRIVATE;
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-            // Name differs, though the value is the same
-            return PublicFormat::NV16;
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            // Name differs, though the value is the same
-            return PublicFormat::NV21;
-        case HAL_PIXEL_FORMAT_YCbCr_422_I:
-            // Name differs, though the value is the same
-            return PublicFormat::YUY2;
-        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-            // Name differs, though the value is the same
-            return PublicFormat::PRIVATE;
-        case HAL_PIXEL_FORMAT_Y16:
-            // Dataspace-dependent
-            switch (ds) {
-                case Dataspace::DEPTH:
-                    return PublicFormat::DEPTH16;
-                default:
-                    // Assume non-depth Y16 is just Y16.
-                    return PublicFormat::Y16;
-            }
-            break;
-        case HAL_PIXEL_FORMAT_BLOB:
-            // Dataspace-dependent
-            switch (ds) {
-                case Dataspace::DEPTH:
-                    return PublicFormat::DEPTH_POINT_CLOUD;
-                case Dataspace::V0_JFIF:
-                    return PublicFormat::JPEG;
-                case Dataspace::HEIF:
-                    return PublicFormat::HEIC;
-                default:
-                    if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) {
-                        return PublicFormat::DEPTH_JPEG;
-                    } else {
-                        // Assume otherwise-marked blobs are also JPEG
-                        return PublicFormat::JPEG;
-                    }
-            }
-            break;
-        case HAL_PIXEL_FORMAT_BGRA_8888:
-            // Not defined in public API
-            return PublicFormat::UNKNOWN;
-
-        default:
-            return PublicFormat::UNKNOWN;
-    }
+    return mapHalFormatDataspaceToPublicFormat(format, dataSpace);
 }
 // ----------------------------------------------------------------------------
 
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 4c25fd4..af2bf2d 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -717,6 +717,29 @@
     return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
 }
 
+static jintArray nativeGetAllowedDisplayConfigs(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == nullptr) return JNI_FALSE;
+
+    std::vector<int32_t> allowedConfigs;
+    size_t result = SurfaceComposerClient::getAllowedDisplayConfigs(token, &allowedConfigs);
+    if (result != NO_ERROR) {
+        return nullptr;
+    }
+
+    jintArray allowedConfigsArray = env->NewIntArray(allowedConfigs.size());
+    if (allowedConfigsArray == nullptr) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+        return nullptr;
+    }
+    jint* allowedConfigsArrayValues = env->GetIntArrayElements(allowedConfigsArray, 0);
+    for (size_t i = 0; i < allowedConfigs.size(); i++) {
+        allowedConfigsArrayValues[i] = static_cast<jint>(allowedConfigs[i]);
+    }
+    env->ReleaseIntArrayElements(allowedConfigsArray, allowedConfigsArrayValues, 0);
+    return allowedConfigsArray;
+}
+
 static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
     if (token == NULL) return -1;
@@ -1215,6 +1238,8 @@
             (void*)nativeSetActiveConfig },
     {"nativeSetAllowedDisplayConfigs", "(Landroid/os/IBinder;[I)Z",
             (void*)nativeSetAllowedDisplayConfigs },
+    {"nativeGetAllowedDisplayConfigs", "(Landroid/os/IBinder;)[I",
+            (void*)nativeGetAllowedDisplayConfigs },
     {"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
             (void*)nativeGetDisplayColorModes},
     {"nativeGetDisplayNativePrimaries", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayPrimaries;",
diff --git a/core/jni/include/android_runtime/android_view_Surface.h b/core/jni/include/android_runtime/android_view_Surface.h
index 3f7c00c..04718cd 100644
--- a/core/jni/include/android_runtime/android_view_Surface.h
+++ b/core/jni/include/android_runtime/android_view_Surface.h
@@ -19,6 +19,7 @@
 
 #include <android/native_window.h>
 #include <system/graphics.h>
+#include <ui/PublicFormat.h>
 
 #include "jni.h"
 
@@ -27,41 +28,6 @@
 class Surface;
 class IGraphicBufferProducer;
 
-/**
- * Enum mirroring the public API definitions for image and pixel formats.
- * Some of these are hidden in the public API
- *
- * Keep up to date with android.graphics.ImageFormat and
- * android.graphics.PixelFormat
- */
-enum class PublicFormat {
-    UNKNOWN           = 0x0,
-    RGBA_8888         = 0x1,
-    RGBX_8888         = 0x2,
-    RGB_888           = 0x3,
-    RGB_565           = 0x4,
-    NV16              = 0x10,
-    NV21              = 0x11,
-    YUY2              = 0x14,
-    RGBA_FP16         = 0x16,
-    RAW_SENSOR        = 0x20,
-    PRIVATE           = 0x22,
-    YUV_420_888       = 0x23,
-    RAW_PRIVATE       = 0x24,
-    RAW10             = 0x25,
-    RAW12             = 0x26,
-    RGBA_1010102      = 0x2b,
-    JPEG              = 0x100,
-    DEPTH_POINT_CLOUD = 0x101,
-    RAW_DEPTH         = 0x1002, // @hide
-    YV12              = 0x32315659,
-    Y8                = 0x20203859,
-    Y16               = 0x20363159, // @hide
-    DEPTH16           = 0x44363159,
-    DEPTH_JPEG        = 0x69656963,
-    HEIC              = 0x48454946,
-};
-
 /* Gets the underlying ANativeWindow for a Surface. */
 extern sp<ANativeWindow> android_view_Surface_getNativeWindow(
         JNIEnv* env, jobject surfaceObj);
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 6f9a564..79a5dd7 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -132,6 +132,7 @@
 
     optional bool keyguard_showing = 1;
     repeated KeyguardOccludedProto keyguard_occluded_states= 2;
+    optional bool aod_showing = 3;
 }
 
 message KeyguardOccludedProto {
diff --git a/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml
index 6f3dc8c..5add19b 100644
--- a/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml
+++ b/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml
@@ -18,7 +18,9 @@
 -->
 <!-- This should be kept in sync with task_open_enter.xml -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false" android:zAdjustment="top">
+     android:hasRoundedCorners="true"
+     android:shareInterpolator="false"
+     android:zAdjustment="top">
 
     <alpha
         android:fromAlpha="1"
diff --git a/core/res/res/anim-ldrtl/task_close_enter.xml b/core/res/res/anim-ldrtl/task_close_enter.xml
index 7abada3..e00141a 100644
--- a/core/res/res/anim-ldrtl/task_close_enter.xml
+++ b/core/res/res/anim-ldrtl/task_close_enter.xml
@@ -16,6 +16,7 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
     android:zAdjustment="top"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim-ldrtl/task_close_exit.xml b/core/res/res/anim-ldrtl/task_close_exit.xml
index a017820..71a44ae 100644
--- a/core/res/res/anim-ldrtl/task_close_exit.xml
+++ b/core/res/res/anim-ldrtl/task_close_exit.xml
@@ -16,6 +16,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim-ldrtl/task_open_enter.xml b/core/res/res/anim-ldrtl/task_open_enter.xml
index 0433664..7815f7d 100644
--- a/core/res/res/anim-ldrtl/task_open_enter.xml
+++ b/core/res/res/anim-ldrtl/task_open_enter.xml
@@ -18,6 +18,7 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
     android:zAdjustment="top"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml b/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml
index 45ca80e..5fccd6df 100644
--- a/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml
+++ b/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml
@@ -18,6 +18,7 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
     android:zAdjustment="top"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim-ldrtl/task_open_exit.xml b/core/res/res/anim-ldrtl/task_open_exit.xml
index f50494d..025e1bd 100644
--- a/core/res/res/anim-ldrtl/task_open_exit.xml
+++ b/core/res/res/anim-ldrtl/task_open_exit.xml
@@ -16,6 +16,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml
index 4c2559f..2cfeecf 100644
--- a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml
+++ b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml
@@ -18,7 +18,9 @@
 -->
 <!-- This should be kept in sync with task_open_enter.xml -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false" android:zAdjustment="top">
+     android:shareInterpolator="false"
+     android:hasRoundedCorners="true"
+     android:zAdjustment="top">
 
     <alpha
         android:fromAlpha="1"
diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
index b059aa9..487ff5c 100644
--- a/core/res/res/anim/task_close_enter.xml
+++ b/core/res/res/anim/task_close_enter.xml
@@ -18,6 +18,7 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
     android:zAdjustment="top"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
index c9ade22..afc3256c 100644
--- a/core/res/res/anim/task_close_exit.xml
+++ b/core/res/res/anim/task_close_exit.xml
@@ -18,6 +18,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
index 5c61859..0aafc1c 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -20,6 +20,7 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
     android:zAdjustment="top"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim/task_open_enter_cross_profile_apps.xml b/core/res/res/anim/task_open_enter_cross_profile_apps.xml
index 6441047..702f7ba 100644
--- a/core/res/res/anim/task_open_enter_cross_profile_apps.xml
+++ b/core/res/res/anim/task_open_enter_cross_profile_apps.xml
@@ -20,6 +20,7 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
     android:zAdjustment="top"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
index 9394c57..691317d 100644
--- a/core/res/res/anim/task_open_exit.xml
+++ b/core/res/res/anim/task_open_exit.xml
@@ -18,6 +18,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
+    android:hasRoundedCorners="true"
     android:showWallpaper="true">
 
     <alpha
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/attrs.xml b/core/res/res/values/attrs.xml
index 088669d..743496f 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6488,6 +6488,9 @@
         <!-- Special option for window animations: show the wallpaper behind when running this
              animation. -->
         <attr name="showWallpaper" format="boolean" />
+        <!-- Special option for window animations: whether window should have rounded corners.
+             @see ScreenDecorationsUtils#getWindowCornerRadius(Resources) -->
+        <attr name="hasRoundedCorners" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="AnimationSet">
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 1053184..6b8e000 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1667,6 +1667,9 @@
              This flag is turned on by default. <em>This attribute is usable only by system apps.
              </em> -->
         <attr name="allowClearUserDataOnFailedRestore"/>
+        <!-- If {@code true} the app's non sensitive audio can be capture by other apps.
+             The default value is true. -->
+        <attr name="allowAudioPlaybackCapture" format="boolean" />
     </declare-styleable>
     <!-- The <code>permission</code> tag declares a security permission that can be
          used to control access from other packages to specific components or
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 824b4b5..7209103 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -26,6 +26,8 @@
     <color name="primary_dark_device_default_settings">@color/primary_dark_material_settings</color>
     <color name="primary_dark_device_default_settings_light">@color/primary_dark_material_settings_light</color>
 
+    <color name="navigation_bar_divider_device_default_settings">#1f000000</color>
+
     <color name="secondary_device_default_settings">@color/secondary_material_settings</color>
     <color name="secondary_device_default_settings_light">@color/secondary_material_settings_light</color>
     <color name="tertiary_device_default_settings">@color/tertiary_material_settings</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0041bfc..f1a7059 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. -->
@@ -2272,7 +2267,7 @@
 
     <!-- If the sensor that wakes up the lock screen is available or not. -->
     <bool name="config_dozeWakeLockScreenSensorAvailable">false</bool>
-    <integer name="config_dozeWakeLockScreenDebounce">3000</integer>
+    <integer name="config_dozeWakeLockScreenDebounce">1500</integer>
 
     <!-- Control whether the always on display mode is available. This should only be enabled on
          devices where the display has been tuned to be power efficient in DOZE and/or DOZE_SUSPEND
@@ -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/public.xml b/core/res/res/values/public.xml
index 5a3c536..61d53002 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2941,6 +2941,7 @@
         <public name="forceUriPermissions" />
         <!-- @hide @SystemApi -->
         <public name="allowClearUserDataOnFailedRestore"/>
+        <public name="allowAudioPlaybackCapture"/>
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b4">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index dbdc763..4e47b1f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -779,7 +779,7 @@
         &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to make and manage phone calls?</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgrouplab_sensors">Body Sensors</string>
+    <string name="permgrouplab_sensors">Body sensors</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_sensors">access sensor data about your vital signs</string>
     <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
@@ -795,12 +795,12 @@
         &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your music?</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgrouplab_visual">Photos &amp; Videos</string>
+    <string name="permgrouplab_visual">Photos &amp; videos</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_visual">access your photos &amp; videos</string>
     <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
     <string name="permgrouprequest_visual">Allow
-        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your photos &amp; videos?</string>
+        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your photos and videos, including tagged locations?</string>
 
     <!-- Title for the capability of an accessibility service to retrieve window content. -->
     <string name="capability_title_canRetrieveWindowContent">Retrieve window content</string>
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/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 194c86c..9a95ecc 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1468,7 +1468,7 @@
         <item name="colorEdgeEffect">@android:color/black</item>
 
         <!-- Add white nav bar with divider that matches material -->
-        <item name="navigationBarDividerColor">#1f000000</item>
+        <item name="navigationBarDividerColor">@color/navigation_bar_divider_device_default_settings</item>
         <item name="navigationBarColor">@android:color/white</item>
         <item name="windowLightNavigationBar">true</item>
 
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/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 5d5754b..de1453a 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -59,6 +59,131 @@
     }
 
     @Test
+    public void getString_empty() {
+        final String default_value = "default_value";
+        final String result = DeviceConfig.getString(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(default_value);
+    }
+
+    @Test
+    public void getString_nonEmpty() {
+        final String value = "new_value";
+        final String default_value = "default";
+        DeviceConfig.setProperty(sNamespace, sKey, value, false);
+
+        final String result = DeviceConfig.getString(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(value);
+    }
+
+    @Test
+    public void getBoolean_empty() {
+        final boolean default_value = true;
+        final boolean result = DeviceConfig.getBoolean(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(default_value);
+    }
+
+    @Test
+    public void getBoolean_valid() {
+        final boolean value = true;
+        final boolean default_value = false;
+        DeviceConfig.setProperty(sNamespace, sKey, String.valueOf(value), false);
+
+        final boolean result = DeviceConfig.getBoolean(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(value);
+    }
+
+    @Test
+    public void getBoolean_invalid() {
+        final boolean default_value = true;
+        DeviceConfig.setProperty(sNamespace, sKey, "not_a_boolean", false);
+
+        final boolean result = DeviceConfig.getBoolean(sNamespace, sKey, default_value);
+        // Anything non-null other than case insensitive "true" parses to false.
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void getInt_empty() {
+        final int default_value = 999;
+        final int result = DeviceConfig.getInt(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(default_value);
+    }
+
+    @Test
+    public void getInt_valid() {
+        final int value = 123;
+        final int default_value = 999;
+        DeviceConfig.setProperty(sNamespace, sKey, String.valueOf(value), false);
+
+        final int result = DeviceConfig.getInt(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(value);
+    }
+
+    @Test
+    public void getInt_invalid() {
+        final int default_value = 999;
+        DeviceConfig.setProperty(sNamespace, sKey, "not_an_int", false);
+
+        final int result = DeviceConfig.getInt(sNamespace, sKey, default_value);
+        // Failure to parse results in using the default value
+        assertThat(result).isEqualTo(default_value);
+    }
+
+    @Test
+    public void getLong_empty() {
+        final long default_value = 123456;
+        final long result = DeviceConfig.getLong(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(default_value);
+    }
+
+    @Test
+    public void getLong_valid() {
+        final long value = 456789;
+        final long default_value = 123456;
+        DeviceConfig.setProperty(sNamespace, sKey, String.valueOf(value), false);
+
+        final long result = DeviceConfig.getLong(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(value);
+    }
+
+    @Test
+    public void getLong_invalid() {
+        final long default_value = 123456;
+        DeviceConfig.setProperty(sNamespace, sKey, "not_a_long", false);
+
+        final long result = DeviceConfig.getLong(sNamespace, sKey, default_value);
+        // Failure to parse results in using the default value
+        assertThat(result).isEqualTo(default_value);
+    }
+
+    @Test
+    public void getFloat_empty() {
+        final float default_value = 123.456f;
+        final float result = DeviceConfig.getFloat(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(default_value);
+    }
+
+    @Test
+    public void getFloat_valid() {
+        final float value = 456.789f;
+        final float default_value = 123.456f;
+        DeviceConfig.setProperty(sNamespace, sKey, String.valueOf(value), false);
+
+        final float result = DeviceConfig.getFloat(sNamespace, sKey, default_value);
+        assertThat(result).isEqualTo(value);
+    }
+
+    @Test
+    public void getFloat_invalid() {
+        final float default_value = 123.456f;
+        DeviceConfig.setProperty(sNamespace, sKey, "not_a_float", false);
+
+        final float result = DeviceConfig.getFloat(sNamespace, sKey, default_value);
+        // Failure to parse results in using the default value
+        assertThat(result).isEqualTo(default_value);
+    }
+
+    @Test
     public void setAndGetProperty_sameNamespace() {
         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
         String result = DeviceConfig.getProperty(sNamespace, sKey);
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/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 2ae28f5..08f4176 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -20,6 +20,7 @@
 import com.android.org.bouncycastle.util.io.pem.PemReader;
 import com.android.org.bouncycastle.util.io.pem.PemWriter;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -122,6 +123,7 @@
      * Convert objects to a PEM format which is used for
      * CA_CERTIFICATE and USER_CERTIFICATE entries.
      */
+    @UnsupportedAppUsage
     public static byte[] convertToPem(Certificate... objects)
             throws IOException, CertificateEncodingException {
         ByteArrayOutputStream bao = new ByteArrayOutputStream();
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index 0d32075..b3cdff7 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -27,6 +27,7 @@
  */
 interface IKeyChainService {
     // APIs used by KeyChain
+    @UnsupportedAppUsage
     String requestPrivateKey(String alias);
     byte[] getCertificate(String alias);
     byte[] getCaCertificates(String alias);
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index d7b84ff..117d05e 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -35,6 +35,12 @@
 #endif
 #endif
 
+#ifdef __ANDROID__
+#define ANDROID_LOG(x) LOG(x)
+#else
+#define ANDROID_LOG(x) std::stringstream()
+#endif
+
 #include "androidfw/ResourceUtils.h"
 
 namespace android {
@@ -380,7 +386,8 @@
 
   const uint8_t package_idx = package_ids_[package_id];
   if (package_idx == 0xff) {
-    LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid);
+    ANDROID_LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.",
+                                             package_id, resid);
     return kInvalidCookie;
   }
 
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 6da8062..6c04232 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -117,6 +117,7 @@
     auto& cache = skiapipeline::ShaderCache::get();
     cache.initShaderDiskCache(identity, size);
     contextOptions->fPersistentCache = &cache;
+    contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
 }
 
 void CacheManager::trimMemory(TrimMemoryMode mode) {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 3b43f12..5af660c 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -254,10 +254,36 @@
 
     float queuePriorities[1] = { 0.0 };
 
+    void* queueNextPtr = nullptr;
+
+    VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo;
+
+    if (Properties::contextPriority != 0
+            && grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
+        memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT));
+        queuePriorityCreateInfo.sType =
+            VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
+        queuePriorityCreateInfo.pNext = nullptr;
+        switch (Properties::contextPriority) {
+            case EGL_CONTEXT_PRIORITY_LOW_IMG:
+                queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT;
+                break;
+            case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
+                queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT;
+                break;
+            case EGL_CONTEXT_PRIORITY_HIGH_IMG:
+                queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT;
+                break;
+            default:
+                LOG_ALWAYS_FATAL("Unsupported context priority");
+         }
+         queueNextPtr = &queuePriorityCreateInfo;
+    }
+
     const VkDeviceQueueCreateInfo queueInfo[2] = {
         {
             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
-            nullptr,                                    // pNext
+            queueNextPtr,                               // pNext
             0,                                          // VkDeviceQueueCreateFlags
             mGraphicsQueueIndex,                        // queueFamilyIndex
             1,                                          // queueCount
@@ -265,7 +291,7 @@
         },
         {
             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
-            nullptr,                                    // pNext
+            queueNextPtr,                               // pNext
             0,                                          // VkDeviceQueueCreateFlags
             mPresentQueueIndex,                         // queueFamilyIndex
             1,                                          // queueCount
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/java/android/location/IGeocodeProvider.aidl b/location/java/android/location/IGeocodeProvider.aidl
index aaa70c7..7eaf7b8 100644
--- a/location/java/android/location/IGeocodeProvider.aidl
+++ b/location/java/android/location/IGeocodeProvider.aidl
@@ -26,9 +26,11 @@
  */
 interface IGeocodeProvider {
 
+    @UnsupportedAppUsage
     String getFromLocation(double latitude, double longitude, int maxResults,
         in GeocoderParams params, out List<Address> addrs);
 
+    @UnsupportedAppUsage
     String getFromLocationName(String locationName,
         double lowerLeftLatitude, double lowerLeftLongitude,
         double upperRightLatitude, double upperRightLongitude, int maxResults,
diff --git a/location/java/android/location/IGeofenceProvider.aidl b/location/java/android/location/IGeofenceProvider.aidl
index d4ff0dd..426ebef 100644
--- a/location/java/android/location/IGeofenceProvider.aidl
+++ b/location/java/android/location/IGeofenceProvider.aidl
@@ -24,5 +24,6 @@
  * {@hide}
  */
 oneway interface IGeofenceProvider {
+    @UnsupportedAppUsage
     void setGeofenceHardware(in IGeofenceHardware proxy);
 }
diff --git a/location/java/android/location/ILocationListener.aidl b/location/java/android/location/ILocationListener.aidl
index 180183e..ec11345 100644
--- a/location/java/android/location/ILocationListener.aidl
+++ b/location/java/android/location/ILocationListener.aidl
@@ -25,10 +25,14 @@
  */
 oneway interface ILocationListener
 {
+    @UnsupportedAppUsage
     void onLocationChanged(in Location location);
+    @UnsupportedAppUsage
     void onProviderEnabled(String provider);
+    @UnsupportedAppUsage
     void onProviderDisabled(String provider);
 
     // --- deprecated ---
+    @UnsupportedAppUsage
     void onStatusChanged(String provider, int status, in Bundle extras);
 }
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 57a0a72..bb75c77 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -85,6 +85,7 @@
     boolean stopGnssBatch();
     boolean injectLocation(in Location location);
 
+    @UnsupportedAppUsage
     List<String> getAllProviders();
     List<String> getProviders(in Criteria criteria, boolean enabledOnly);
     String getBestProvider(in Criteria criteria, boolean enabledOnly);
diff --git a/location/java/android/location/INetInitiatedListener.aidl b/location/java/android/location/INetInitiatedListener.aidl
index fc64dd6..a9e9136 100644
--- a/location/java/android/location/INetInitiatedListener.aidl
+++ b/location/java/android/location/INetInitiatedListener.aidl
@@ -22,5 +22,6 @@
  */
 interface INetInitiatedListener
 {
+    @UnsupportedAppUsage
     boolean sendNiResponse(int notifId, int userResponse);
 }
diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl
index 71b54fb..a571630 100644
--- a/location/java/com/android/internal/location/ILocationProvider.aidl
+++ b/location/java/com/android/internal/location/ILocationProvider.aidl
@@ -36,6 +36,8 @@
     oneway void sendExtraCommand(String command, in Bundle extras);
 
     // --- deprecated and will be removed the future ---
+    @UnsupportedAppUsage
     int getStatus(out Bundle extras);
+    @UnsupportedAppUsage
     long getStatusUpdateTime();
 }
diff --git a/location/java/com/android/internal/location/ILocationProviderManager.aidl b/location/java/com/android/internal/location/ILocationProviderManager.aidl
index 79166ae..85e18ba 100644
--- a/location/java/com/android/internal/location/ILocationProviderManager.aidl
+++ b/location/java/com/android/internal/location/ILocationProviderManager.aidl
@@ -28,9 +28,12 @@
 
     void onSetAdditionalProviderPackages(in List<String> packageNames);
 
+    @UnsupportedAppUsage
     void onSetEnabled(boolean enabled);
 
+    @UnsupportedAppUsage
     void onSetProperties(in ProviderProperties properties);
 
+    @UnsupportedAppUsage
     void onReportLocation(in Location location);
 }
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..15f9b47 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -36,6 +36,9 @@
 import android.content.Intent;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
+import android.media.audiopolicy.AudioProductStrategies;
+import android.media.audiopolicy.AudioVolumeGroupChangeHandler;
+import android.media.audiopolicy.AudioVolumeGroups;
 import android.media.projection.MediaProjection;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
@@ -60,6 +63,7 @@
 import android.view.KeyEvent;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -89,6 +93,8 @@
     private static final String TAG = "AudioManager";
     private static final boolean DEBUG = false;
     private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler();
+    private static final AudioVolumeGroupChangeHandler sAudioAudioVolumeGroupChangedHandler =
+            new AudioVolumeGroupChangeHandler();
 
     /**
      * Broadcast intent, a hint for applications that audio is about to become
@@ -1163,6 +1169,93 @@
     }
 
     /**
+     * Sets the volume index for a particular {@link AudioAttributes}.
+     * @param attr The {@link AudioAttributes} whose volume index should be set.
+     * @param index The volume index to set. See
+     *          {@link #getMaxVolumeIndexForAttributes(AudioAttributes)} for the largest valid value
+     *          {@link #getMinVolumeIndexForAttributes(AudioAttributes)} for the lowest valid value.
+     * @param flags One or more flags.
+     * @see #getMaxVolumeIndexForAttributes(AudioAttributes)
+     * @see #getMinVolumeIndexForAttributes(AudioAttributes)
+     * @see #isVolumeFixed()
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public void setVolumeIndexForAttributes(@NonNull AudioAttributes attr, int index, int flags) {
+        Preconditions.checkNotNull(attr, "attr must not be null");
+        final IAudioService service = getService();
+        try {
+            service.setVolumeIndexForAttributes(attr, index, flags,
+                                                getContext().getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the current volume index for a particular {@link AudioAttributes}.
+     *
+     * @param attr The {@link AudioAttributes} whose volume index is returned.
+     * @return The current volume index for the stream.
+     * @see #getMaxVolumeIndexForAttributes(AudioAttributes)
+     * @see #getMinVolumeIndexForAttributes(AudioAttributes)
+     * @see #setVolumeForAttributes(AudioAttributes, int, int)
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
+        Preconditions.checkNotNull(attr, "attr must not be null");
+        final IAudioService service = getService();
+        try {
+            return service.getVolumeIndexForAttributes(attr);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the maximum volume index for a particular {@link AudioAttributes}.
+     *
+     * @param attr The {@link AudioAttributes} whose maximum volume index is returned.
+     * @return The maximum valid volume index for the {@link AudioAttributes}.
+     * @see #getVolumeIndexForAttributes(AudioAttributes)
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
+        Preconditions.checkNotNull(attr, "attr must not be null");
+        final IAudioService service = getService();
+        try {
+            return service.getMaxVolumeIndexForAttributes(attr);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the minimum volume index for a particular {@link AudioAttributes}.
+     *
+     * @param attr The {@link AudioAttributes} whose minimum volume index is returned.
+     * @return The minimum valid volume index for the {@link AudioAttributes}.
+     * @see #getVolumeIndexForAttributes(AudioAttributes)
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
+        Preconditions.checkNotNull(attr, "attr must not be null");
+        final IAudioService service = getService();
+        try {
+            return service.getMinVolumeIndexForAttributes(attr);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Solo or unsolo a particular stream.
      * <p>
      * Do not use. This method has been deprecated and is now a no-op.
@@ -5221,6 +5314,89 @@
         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();
+        }
+    }
+
+    /**
+     * @hide
+     * Introspection API to retrieve audio volume groups.
+     * When implementing {Car|Oem}AudioManager, use this method  to retrieve the collection of
+     * audio volume groups.
+     * @return a (possibly zero-length) array of
+     *         {@see android.media.audiopolicy.AudioVolumeGroups} objects.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public @NonNull AudioVolumeGroups getAudioVolumeGroups() {
+        final IAudioService service = getService();
+        try {
+            return service.listAudioVolumeGroups();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @hide
+     * Callback registered by client to be notified upon volume group change.
+     */
+    @SystemApi
+    public abstract static class VolumeGroupCallback {
+        /**
+         * Callback method called upon audio volume group change.
+         * @param group the group for which the volume has changed
+         */
+        public void onAudioVolumeGroupChanged(int group, int flags) {}
+    }
+
+   /**
+    * @hide
+    * Register an audio volume group change listener.
+    * @param callback the {@link VolumeGroupCallback} to register
+    */
+    @SystemApi
+    public void registerVolumeGroupCallback(
+            @NonNull Executor executor,
+            @NonNull VolumeGroupCallback callback) {
+        Preconditions.checkNotNull(executor, "executor must not be null");
+        Preconditions.checkNotNull(callback, "volume group change cb must not be null");
+        sAudioAudioVolumeGroupChangedHandler.init();
+        // TODO: make use of executor
+        sAudioAudioVolumeGroupChangedHandler.registerListener(callback);
+    }
+
+   /**
+    * @hide
+    * Unregister an audio volume group change listener.
+    * @param callback the {@link VolumeGroupCallback} to unregister
+    */
+    @SystemApi
+    public void unregisterVolumeGroupCallback(
+            @NonNull VolumeGroupCallback callback) {
+        Preconditions.checkNotNull(callback, "volume group change cb must not be null");
+        sAudioAudioVolumeGroupChangedHandler.unregisterListener(callback);
+    }
 
     //---------------------------------------------------------
     // Inner classes
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
index d714dc7..9a16aea 100644
--- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -33,7 +33,7 @@
  *  - played by apps that MUST be in the same user profile as the capturing app
  *    (eg work profile can not capture user profile apps and vice-versa).
  *  - played by apps that MUST NOT have in their manifest.xml the application
- *    attribute android:allowPlaybackCapture="false"
+ *    attribute android:allowAudioPlaybackCapture="false"
  *  - played by apps that MUST have a targetSdkVersion higher or equal to 29 (Q).
  *
  * <p>An example for creating a capture configuration for capturing all media playback:
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index ec1a854..3d5120f 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -653,7 +653,16 @@
             AudioPolicy audioPolicy = new AudioPolicy.Builder(/*context=*/ null)
                     .setMediaProjection(projection)
                     .addMix(audioMix).build();
+
+            int error = AudioManager.registerAudioPolicyStatic(audioPolicy);
+            if (error != 0) {
+                throw new UnsupportedOperationException("Error: could not register audio policy");
+            }
+
             AudioRecord record = audioPolicy.createAudioRecordSink(audioMix);
+            if (record == null) {
+                throw new UnsupportedOperationException("Cannot create AudioRecord");
+            }
             record.unregisterAudioPolicyOnRelease(audioPolicy);
             return record;
         }
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 9218e92..a976d70 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -40,7 +40,7 @@
  */
 public class AudioSystem
 {
-    private static final boolean DEBUG_VOLUME = true;
+    private static final boolean DEBUG_VOLUME = false;
 
     private static final String TAG = "AudioSystem";
     /* These values must be kept in sync with system/audio.h */
@@ -920,6 +920,41 @@
     @UnsupportedAppUsage
     private static native int setStreamVolumeIndex(int stream, int index, int device);
     public static native int getStreamVolumeIndex(int stream, int device);
+    /**
+     * @hide
+     * set a volume for the given {@link AudioAttributes} and for all other stream that belong to
+     * the same volume group.
+     * @param attributes the {@link AudioAttributes} to be considered
+     * @param index to be applied
+     * @param device the volume device to be considered
+     * @return command completion status.
+     */
+    public static native int setVolumeIndexForAttributes(@NonNull AudioAttributes attributes,
+                                                         int index, int device);
+   /**
+    * @hide
+    * get the volume index for the given {@link AudioAttributes}.
+    * @param attributes the {@link AudioAttributes} to be considered
+    * @param device the volume device to be considered
+    * @return volume index for the given {@link AudioAttributes} and volume device.
+    */
+    public static native int getVolumeIndexForAttributes(@NonNull AudioAttributes attributes,
+                                                         int device);
+    /**
+     * @hide
+     * get the minimum volume index for the given {@link AudioAttributes}.
+     * @param attributes the {@link AudioAttributes} to be considered
+     * @return minimum volume index for the given {@link AudioAttributes}.
+     */
+    public static native int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attributes);
+    /**
+     * @hide
+     * get the maximum volume index for the given {@link AudioAttributes}.
+     * @param attributes the {@link AudioAttributes} to be considered
+     * @return maximum volume index for the given {@link AudioAttributes}.
+     */
+    public static native int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attributes);
+
     public static native int setMasterVolume(float value);
     public static native float getMasterVolume();
     @UnsupportedAppUsage
diff --git a/media/java/android/media/IAudioFocusDispatcher.aidl b/media/java/android/media/IAudioFocusDispatcher.aidl
index 3b33c5b..e3512fa 100644
--- a/media/java/android/media/IAudioFocusDispatcher.aidl
+++ b/media/java/android/media/IAudioFocusDispatcher.aidl
@@ -23,6 +23,7 @@
  */
 oneway interface IAudioFocusDispatcher {
 
+    @UnsupportedAppUsage
     void dispatchAudioFocusChange(int focusChange, String clientId);
 
     void dispatchFocusResultFromExtPolicy(int requestResult, String clientId);
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 571e67e..1b82fcc 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -33,6 +33,8 @@
 import android.media.PlayerBase;
 import android.media.VolumePolicy;
 import android.media.audiopolicy.AudioPolicyConfig;
+import android.media.audiopolicy.AudioProductStrategies;
+import android.media.audiopolicy.AudioVolumeGroups;
 import android.media.audiopolicy.IAudioPolicyCallback;
 import android.media.projection.IMediaProjection;
 
@@ -64,6 +66,7 @@
 
     void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage);
 
+    @UnsupportedAppUsage
     void setStreamVolume(int streamType, int index, int flags, String callingPackage);
 
     boolean isStreamMute(int streamType);
@@ -74,14 +77,28 @@
 
     void setMasterMute(boolean mute, int flags, String callingPackage, int userId);
 
+    @UnsupportedAppUsage
     int getStreamVolume(int streamType);
 
     int getStreamMinVolume(int streamType);
 
+    @UnsupportedAppUsage
     int getStreamMaxVolume(int streamType);
 
+    AudioVolumeGroups listAudioVolumeGroups();
+
+    void setVolumeIndexForAttributes(in AudioAttributes aa, int index, int flags, String callingPackage);
+
+    int getVolumeIndexForAttributes(in AudioAttributes aa);
+
+    int getMaxVolumeIndexForAttributes(in AudioAttributes aa);
+
+    int getMinVolumeIndexForAttributes(in AudioAttributes aa);
+
     int getLastAudibleStreamVolume(int streamType);
 
+    AudioProductStrategies getAudioProductStrategies();
+
     void setMicrophoneMute(boolean on, String callingPackage, int userId);
 
     void setRingerModeExternal(int ringerMode, String caller);
@@ -157,6 +174,7 @@
     int handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device,
             int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
 
+    @UnsupportedAppUsage
     AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
 
     boolean isCameraSoundForced();
diff --git a/media/java/android/media/IMediaScannerService.aidl b/media/java/android/media/IMediaScannerService.aidl
index c531646..24b5595 100644
--- a/media/java/android/media/IMediaScannerService.aidl
+++ b/media/java/android/media/IMediaScannerService.aidl
@@ -31,6 +31,7 @@
      * @param listener an optional IMediaScannerListener. 
      * If specified, the caller will be notified when scanning is complete via the listener.
      */
+    @UnsupportedAppUsage
     void requestScanFile(String path, String mimeType, in IMediaScannerListener listener);
 
     /**
@@ -40,5 +41,6 @@
      * @param mimeType  an optional mimeType for the file.
      * If mimeType is null, then the mimeType will be inferred from the file extension.
      */
+    @UnsupportedAppUsage
     void scanFile(String path, String mimeType);
 }
diff --git a/media/java/android/media/IRemoteDisplayCallback.aidl b/media/java/android/media/IRemoteDisplayCallback.aidl
index 19cf070..584417d 100644
--- a/media/java/android/media/IRemoteDisplayCallback.aidl
+++ b/media/java/android/media/IRemoteDisplayCallback.aidl
@@ -22,5 +22,6 @@
  * {@hide}
  */
 oneway interface IRemoteDisplayCallback {
+    @UnsupportedAppUsage
     void onStateChanged(in RemoteDisplayState state);
 }
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.java b/media/java/android/media/audiopolicy/AudioProductStrategies.java
index b836409..d593885 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,62 @@
         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");
+        int productStrategyId =  native_get_product_strategies_from_audio_attributes(aa);
+        if (productStrategyId < 0) {
+            Log.w(TAG, "no strategy found for Attributes " + aa.toString());
+            return null;
+        }
+        return getById(productStrategyId);
+    }
+
+   /**
+    * @hide
+    * @param attributes the {@link AudioAttributes} to be considered
+    * @return volume group associated to the given {@link AudioAttributes}.
+    *         If no group supports the given {@link AudioAttributes}, it returns the volume group
+    *         for the default attributes.
+    *         If no group supports the default attributes, it returns {@link #DEFAULT_VOLUME_GROUP}
+    */
+    @SystemApi
+    public int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) {
+        Preconditions.checkNotNull(attributes, "attributes must not be null");
+        int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes);
+        if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
+            return volumeGroupId;
+        }
+        // The default volume group is the one hosted by default product strategy, i.e.
+        // supporting Default Attributes
+        return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes);
+    }
+
+   /**
+    * @hide
+    * @param streamType to be considered
+    * @return volume group associated to the given stream type.
+    */
+    @SystemApi
+    public int getVolumeGroupIdForLegacyStreamType(int streamType) {
+        for (final AudioProductStrategy productStrategy : this) {
+            int volumeGroupId = productStrategy.getVolumeGroupIdForLegacyStreamType(streamType);
+            if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
+                return volumeGroupId;
+            }
+        }
+        // The default volume group is the one hosted by default product strategy, i.e.
+        // supporting Default Attributes
+        return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes);
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -178,6 +236,21 @@
         }
     }
 
+    /**
+     * @param attributes to be considered
+     * @return volume group associated to the given {@link AudioAttributes}.
+     */
+    private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) {
+        Preconditions.checkNotNull(attributes, "attributes must not be null");
+        for (final AudioProductStrategy productStrategy : this) {
+            int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes);
+            if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) {
+                return volumeGroupId;
+            }
+        }
+        return AudioVolumeGroups.DEFAULT_VOLUME_GROUP;
+    }
+
     public static final Parcelable.Creator<AudioProductStrategies> CREATOR =
             new Parcelable.Creator<AudioProductStrategies>() {
                 @Override
@@ -198,4 +271,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/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
index af6e8bf..169484b 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategy.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -157,32 +157,32 @@
     /**
      * @hide
      * @param streamType legacy stream type used for volume operation only
-     * @return the {@link AudioAttributes} relevant for the given streamType.
-     *         If none is found, it builds the default attributes.
+     * @return the volume group id relevant for the given streamType.
+     *         If none is found, {@link AudioVolumeGroups#DEFAULT_VOLUME_GROUP} is returned.
      */
-    public int getGroupIdForLegacyStreamType(int streamType) {
+    public int getVolumeGroupIdForLegacyStreamType(int streamType) {
         for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
             if (aag.supportsStreamType(streamType)) {
-                return aag.getGroupId();
+                return aag.getVolumeGroupId();
             }
         }
-        return DEFAULT_GROUP;
+        return AudioVolumeGroups.DEFAULT_VOLUME_GROUP;
     }
 
     /**
      * @hide
      * @param aa the {@link AudioAttributes} to be considered
-     * @return the group id associated with the given audio attributes if found,
-     *         default value otherwise.
+     * @return the volume group id associated with the given audio attributes if found,
+     *         {@link AudioVolumeGroups#DEFAULT_VOLUME_GROUP} otherwise.
      */
-    public int getGroupIdForAudioAttributes(@NonNull AudioAttributes aa) {
+    public int getVolumeGroupIdForAudioAttributes(@NonNull AudioAttributes aa) {
         Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
         for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
             if (aag.supportsAttributes(aa)) {
-                return aag.getGroupId();
+                return aag.getVolumeGroupId();
             }
         }
-        return DEFAULT_GROUP;
+        return AudioVolumeGroups.DEFAULT_VOLUME_GROUP;
     }
 
     @Override
@@ -266,15 +266,14 @@
             && ((refFormattedTags.length() == 0) || refFormattedTags.equals(cliFormattedTags));
     }
 
-
     private static final class AudioAttributesGroup implements Parcelable {
-        private int mGroupId;
+        private int mVolumeGroupId;
         private int mLegacyStreamType;
         private final AudioAttributes[] mAudioAttributes;
 
-        AudioAttributesGroup(int groupId, int streamType,
+        AudioAttributesGroup(int volumeGroupId, int streamType,
                 @NonNull AudioAttributes[] audioAttributes) {
-            mGroupId = groupId;
+            mVolumeGroupId = volumeGroupId;
             mLegacyStreamType = streamType;
             mAudioAttributes = audioAttributes;
         }
@@ -286,7 +285,7 @@
 
             AudioAttributesGroup thatAag = (AudioAttributesGroup) o;
 
-            return mGroupId == thatAag.mGroupId
+            return mVolumeGroupId == thatAag.mVolumeGroupId
                     && mLegacyStreamType == thatAag.mLegacyStreamType
                     && mAudioAttributes.equals(thatAag.mAudioAttributes);
         }
@@ -295,8 +294,8 @@
             return mLegacyStreamType;
         }
 
-        public int getGroupId() {
-            return mGroupId;
+        public int getVolumeGroupId() {
+            return mVolumeGroupId;
         }
 
         public @NonNull AudioAttributes getAudioAttributes() {
@@ -331,7 +330,7 @@
 
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
-            dest.writeInt(mGroupId);
+            dest.writeInt(mVolumeGroupId);
             dest.writeInt(mLegacyStreamType);
             dest.writeInt(mAudioAttributes.length);
             for (AudioAttributes attributes : mAudioAttributes) {
@@ -343,14 +342,14 @@
                 new Parcelable.Creator<AudioAttributesGroup>() {
                     @Override
                     public AudioAttributesGroup createFromParcel(@NonNull Parcel in) {
-                        int groupId = in.readInt();
+                        int volumeGroupId = in.readInt();
                         int streamType = in.readInt();
                         int nbAttributes = in.readInt();
                         AudioAttributes[] aa = new AudioAttributes[nbAttributes];
                         for (int index = 0; index < nbAttributes; index++) {
                             aa[index] = AudioAttributes.CREATOR.createFromParcel(in);
                         }
-                        return new AudioAttributesGroup(groupId, streamType, aa);
+                        return new AudioAttributesGroup(volumeGroupId, streamType, aa);
                     }
 
                     @Override
@@ -365,8 +364,8 @@
             StringBuilder s = new StringBuilder();
             s.append("\n    Legacy Stream Type: ");
             s.append(Integer.toString(mLegacyStreamType));
-            s.append(" Group Id: ");
-            s.append(Integer.toString(mGroupId));
+            s.append(" Volume Group Id: ");
+            s.append(Integer.toString(mVolumeGroupId));
 
             for (AudioAttributes attribute : mAudioAttributes) {
                 s.append("\n    -");
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroup.aidl b/media/java/android/media/audiopolicy/AudioVolumeGroup.aidl
new file mode 100644
index 0000000..caf1e0d
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroup.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2018, 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.media.audiopolicy;
+
+parcelable AudioVolumeGroup;
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroup.java b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
new file mode 100644
index 0000000..0b4ba93
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 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.media.audiopolicy;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.media.AudioAttributes;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A class to create the association between different playback attributes
+ * (e.g. media, mapping direction) to a single volume control.
+ * @hide
+ */
+@SystemApi
+public final class AudioVolumeGroup implements Parcelable {
+    /**
+     * Unique identifier of a volume group.
+     */
+    private int mId;
+    /**
+     * human-readable name of this volume group.
+     */
+    private final String mName;
+
+    private final AudioAttributes[] mAudioAttributes;
+    private int[] mLegacyStreamTypes;
+
+    /**
+     * @param name of the volume group
+     * @param id of the volume group
+     * @param followers {@link AudioProductStrategies} strategy following this volume group
+     */
+    AudioVolumeGroup(@NonNull String name, int id,
+                     @NonNull AudioAttributes[] audioAttributes,
+                     @NonNull int[] legacyStreamTypes) {
+        Preconditions.checkNotNull(name, "name must not be null");
+        Preconditions.checkNotNull(audioAttributes, "audioAttributes must not be null");
+        Preconditions.checkNotNull(legacyStreamTypes, "legacyStreamTypes must not be null");
+        mName = name;
+        mId = id;
+        mAudioAttributes = audioAttributes;
+        mLegacyStreamTypes = legacyStreamTypes;
+    }
+
+    @Override
+    public boolean equals(@NonNull Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        AudioVolumeGroup thatAvg = (AudioVolumeGroup) o;
+
+        return mName == thatAvg.mName && mId == thatAvg.mId
+                && mAudioAttributes.equals(thatAvg.mAudioAttributes);
+    }
+
+    /**
+     * @return List of {@link AudioAttributes} involved in this {@link AudioVolumeGroup}.
+     */
+    public List<AudioAttributes> getAudioAttributes() {
+        return Arrays.asList(mAudioAttributes);
+    }
+
+    /**
+     * @return the stream types involved in this {@link AudioVolumeGroup}.
+     */
+    public @NonNull int[] getLegacyStreamTypes() {
+        return mLegacyStreamTypes;
+    }
+
+    /**
+     * @return human-readable name of this volume group.
+     */
+    public @NonNull String name() {
+        return mName;
+    }
+
+    /**
+     * @return the volume group unique identifier id.
+     */
+    public int getId() {
+        return mId;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mName);
+        dest.writeInt(mId);
+        dest.writeInt(mAudioAttributes.length);
+        for (AudioAttributes attributes : mAudioAttributes) {
+            attributes.writeToParcel(dest, flags | AudioAttributes.FLATTEN_TAGS/*flags*/);
+        }
+        dest.writeInt(mLegacyStreamTypes.length);
+        for (int streamType : mLegacyStreamTypes) {
+            dest.writeInt(streamType);
+        }
+    }
+
+    public static final Parcelable.Creator<AudioVolumeGroup> CREATOR =
+            new Parcelable.Creator<AudioVolumeGroup>() {
+                @Override
+                public @NonNull AudioVolumeGroup createFromParcel(@NonNull Parcel in) {
+                    Preconditions.checkNotNull(in, "in Parcel must not be null");
+                    String name = in.readString();
+                    int id = in.readInt();
+                    int nbAttributes = in.readInt();
+                    AudioAttributes[] audioAttributes = new AudioAttributes[nbAttributes];
+                    for (int index = 0; index < nbAttributes; index++) {
+                        audioAttributes[index] = AudioAttributes.CREATOR.createFromParcel(in);
+                    }
+                    int nbStreamTypes = in.readInt();
+                    int[] streamTypes = new int[nbStreamTypes];
+                    for (int index = 0; index < nbStreamTypes; index++) {
+                        streamTypes[index] = in.readInt();
+                    }
+                    return new AudioVolumeGroup(name, id, audioAttributes, streamTypes);
+                }
+
+                @Override
+                public @NonNull AudioVolumeGroup[] newArray(int size) {
+                    return new AudioVolumeGroup[size];
+                }
+            };
+
+    @Override
+    public @NonNull String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("\n Name: ");
+        s.append(mName);
+        s.append(" Id: ");
+        s.append(Integer.toString(mId));
+
+        s.append("\n     Supported Audio Attributes:");
+        for (AudioAttributes attribute : mAudioAttributes) {
+            s.append("\n       -");
+            s.append(attribute.toString());
+        }
+        s.append("\n     Supported Legacy Stream Types: { ");
+        for (int legacyStreamType : mLegacyStreamTypes) {
+            s.append(Integer.toString(legacyStreamType));
+            s.append(" ");
+        }
+        s.append("}");
+        return s.toString();
+    }
+}
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java b/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java
new file mode 100644
index 0000000..074188e
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2018 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.media.audiopolicy;
+
+import android.annotation.NonNull;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+/**
+ * The AudioVolumeGroupChangeHandler handles AudioManager.OnAudioVolumeGroupChangedListener
+ * callbacks posted from JNI
+ *
+ * TODO: Make use of Executor of callbacks.
+ * @hide
+ */
+public class AudioVolumeGroupChangeHandler {
+    private Handler mHandler;
+    private HandlerThread mHandlerThread;
+    private final ArrayList<AudioManager.VolumeGroupCallback> mListeners =
+            new ArrayList<AudioManager.VolumeGroupCallback>();
+
+    private static final String TAG = "AudioVolumeGroupChangeHandler";
+
+    private static final int AUDIOVOLUMEGROUP_EVENT_VOLUME_CHANGED = 1000;
+    private static final int AUDIOVOLUMEGROUP_EVENT_NEW_LISTENER = 4;
+
+    /**
+     * Accessed by native methods: JNI Callback context.
+     */
+    @SuppressWarnings("unused")
+    private long mJniCallback;
+
+    /**
+     * Initialization
+     */
+    public void init() {
+        synchronized (this) {
+            if (mHandler != null) {
+                return;
+            }
+            // create a new thread for our new event handler
+            mHandlerThread = new HandlerThread(TAG);
+            mHandlerThread.start();
+
+            if (mHandlerThread.getLooper() == null) {
+                mHandler = null;
+                return;
+            }
+            mHandler = new Handler(mHandlerThread.getLooper()) {
+                @Override
+                public void handleMessage(Message msg) {
+                    ArrayList<AudioManager.VolumeGroupCallback> listeners;
+                    synchronized (this) {
+                        if (msg.what == AUDIOVOLUMEGROUP_EVENT_NEW_LISTENER) {
+                            listeners =
+                                    new ArrayList<AudioManager.VolumeGroupCallback>();
+                            if (mListeners.contains(msg.obj)) {
+                                listeners.add(
+                                        (AudioManager.VolumeGroupCallback) msg.obj);
+                            }
+                        } else {
+                            listeners = mListeners;
+                        }
+                    }
+                    if (listeners.isEmpty()) {
+                        return;
+                    }
+
+                    switch (msg.what) {
+                        case AUDIOVOLUMEGROUP_EVENT_VOLUME_CHANGED:
+                            for (int i = 0; i < listeners.size(); i++) {
+                                listeners.get(i).onAudioVolumeGroupChanged((int) msg.arg1,
+                                                                           (int) msg.arg2);
+                            }
+                            break;
+
+                        default:
+                            break;
+                    }
+                }
+            };
+            native_setup(new WeakReference<AudioVolumeGroupChangeHandler>(this));
+        }
+    }
+
+    private native void native_setup(Object moduleThis);
+
+    @Override
+    protected void finalize() {
+        native_finalize();
+        if (mHandlerThread.isAlive()) {
+            mHandlerThread.quit();
+        }
+    }
+    private native void native_finalize();
+
+   /**
+    * @param cb the {@link AudioManager.VolumeGroupCallback} to register
+    */
+    public void registerListener(@NonNull AudioManager.VolumeGroupCallback cb) {
+        Preconditions.checkNotNull(cb, "volume group callback shall not be null");
+        synchronized (this) {
+            mListeners.add(cb);
+        }
+        if (mHandler != null) {
+            Message m = mHandler.obtainMessage(
+                    AUDIOVOLUMEGROUP_EVENT_NEW_LISTENER, 0, 0, cb);
+            mHandler.sendMessage(m);
+        }
+    }
+
+   /**
+    * @param cb the {@link AudioManager.VolumeGroupCallback} to unregister
+    */
+    public void unregisterListener(@NonNull AudioManager.VolumeGroupCallback cb) {
+        Preconditions.checkNotNull(cb, "volume group callback shall not be null");
+        synchronized (this) {
+            mListeners.remove(cb);
+        }
+    }
+
+    Handler handler() {
+        return mHandler;
+    }
+
+    @SuppressWarnings("unused")
+    private static void postEventFromNative(Object moduleRef,
+                                            int what, int arg1, int arg2, Object obj) {
+        AudioVolumeGroupChangeHandler eventHandler =
+                (AudioVolumeGroupChangeHandler) ((WeakReference) moduleRef).get();
+        if (eventHandler == null) {
+            return;
+        }
+
+        if (eventHandler != null) {
+            Handler handler = eventHandler.handler();
+            if (handler != null) {
+                Message m = handler.obtainMessage(what, arg1, arg2, obj);
+                if (what != AUDIOVOLUMEGROUP_EVENT_NEW_LISTENER) {
+                    handler.removeMessages(what);
+                }
+                handler.sendMessage(m);
+            }
+        }
+    }
+}
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl b/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl
new file mode 100644
index 0000000..918cac3
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2018, 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.media.audiopolicy;
+
+parcelable AudioVolumeGroups;
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroups.java b/media/java/android/media/audiopolicy/AudioVolumeGroups.java
new file mode 100644
index 0000000..301bec7
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroups.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 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.media.audiopolicy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.media.AudioSystem;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * @hide
+ * A class to encapsulate a collection of {@link AudioVolumeGroup}.
+ */
+@SystemApi
+public final class AudioVolumeGroups implements Iterable<AudioVolumeGroup>, Parcelable {
+
+    private final ArrayList<AudioVolumeGroup> mAudioVolumeGroupList;
+
+    private static final String TAG = "AudioVolumeGroups";
+
+    /**
+     * Volume group value to use when introspection API fails.
+     */
+    public static final int DEFAULT_VOLUME_GROUP = -1;
+
+    public AudioVolumeGroups() {
+        ArrayList<AudioVolumeGroup> avgList = new ArrayList<AudioVolumeGroup>();
+        int status = native_list_audio_volume_groups(avgList);
+        if (status != AudioSystem.SUCCESS) {
+            Log.w(TAG, ": listAudioVolumeGroups failed");
+        }
+        mAudioVolumeGroupList = avgList;
+    }
+
+    private AudioVolumeGroups(@NonNull ArrayList<AudioVolumeGroup> audioVolumeGroupList) {
+        Preconditions.checkNotNull(audioVolumeGroupList, "audioVolumeGroupList must not be null");
+        mAudioVolumeGroupList = audioVolumeGroupList;
+    }
+
+    /**
+     * @return number of {@link AudioProductStrategy} objects
+     */
+    public int size() {
+        return mAudioVolumeGroupList.size();
+    }
+
+    /**
+     * Returns an {@link Iterator}
+     */
+    @Override
+    public Iterator<AudioVolumeGroup> iterator() {
+        return mAudioVolumeGroupList.iterator();
+    }
+
+    @Override
+    public boolean equals(@NonNull Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        AudioVolumeGroups that = (AudioVolumeGroups) o;
+
+        return mAudioVolumeGroupList.equals(that.mAudioVolumeGroupList);
+    }
+
+    /**
+     * @return the matching {@link AudioVolumeGroup} objects with the given id,
+     *         null object if not found.
+     */
+    public @Nullable AudioVolumeGroup getById(int volumeGroupId) {
+        for (final AudioVolumeGroup avg : this) {
+            if (avg.getId() == volumeGroupId) {
+                return avg;
+            }
+        }
+        Log.e(TAG, ": invalid volume group id: " + volumeGroupId + " requested");
+        return null;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(size());
+        for (final AudioVolumeGroup volumeGroup : this) {
+            volumeGroup.writeToParcel(dest, flags);
+        }
+    }
+
+    private static native int native_list_audio_volume_groups(
+            ArrayList<AudioVolumeGroup> groups);
+
+    public static final Parcelable.Creator<AudioVolumeGroups> CREATOR =
+            new Parcelable.Creator<AudioVolumeGroups>() {
+                @Override
+                public @NonNull AudioVolumeGroups createFromParcel(@NonNull Parcel in) {
+                    Preconditions.checkNotNull(in, "in Parcel must not be null");
+                    ArrayList<AudioVolumeGroup> avgList = new ArrayList<AudioVolumeGroup>();
+                    int size = in.readInt();
+                    for (int index = 0; index < size; index++) {
+                        avgList.add(AudioVolumeGroup.CREATOR.createFromParcel(in));
+                    }
+                    return new AudioVolumeGroups(avgList);
+                }
+
+                @Override
+                public @NonNull AudioVolumeGroups[] newArray(int size) {
+                    return new AudioVolumeGroups[size];
+                }
+            };
+}
diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl
index 7e10c51..d190fce 100644
--- a/media/java/android/media/projection/IMediaProjectionManager.aidl
+++ b/media/java/android/media/projection/IMediaProjectionManager.aidl
@@ -24,6 +24,7 @@
 
 /** {@hide} */
 interface IMediaProjectionManager {
+    @UnsupportedAppUsage
     boolean hasProjectionPermission(int uid, String packageName);
     IMediaProjection createProjection(int uid, String packageName, int type,
             boolean permanentGrant);
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index f9c5b8d..632cfb0 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
-import android.media.AudioRecord;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionCallback;
 import android.os.Handler;
@@ -140,16 +139,6 @@
     }
 
     /**
-     * Creates an AudioRecord to capture audio played back by the system.
-     * @hide
-     */
-    public AudioRecord createAudioRecord(
-            int sampleRateInHz, int channelConfig,
-            int audioFormat, int bufferSizeInBytes) {
-        return null;
-    }
-
-    /**
      * Stops projection.
      */
     public void stop() {
diff --git a/media/java/android/media/tv/ITvRemoteServiceInput.aidl b/media/java/android/media/tv/ITvRemoteServiceInput.aidl
index df39299..a0b6c9b 100644
--- a/media/java/android/media/tv/ITvRemoteServiceInput.aidl
+++ b/media/java/android/media/tv/ITvRemoteServiceInput.aidl
@@ -21,13 +21,22 @@
  */
 oneway interface ITvRemoteServiceInput {
     // InputBridge related
+    @UnsupportedAppUsage
     void openInputBridge(IBinder token, String name, int width, int height, int maxPointers);
+    @UnsupportedAppUsage
     void closeInputBridge(IBinder token);
+    @UnsupportedAppUsage
     void clearInputBridge(IBinder token);
+    @UnsupportedAppUsage
     void sendTimestamp(IBinder token, long timestamp);
+    @UnsupportedAppUsage
     void sendKeyDown(IBinder token, int keyCode);
+    @UnsupportedAppUsage
     void sendKeyUp(IBinder token, int keyCode);
+    @UnsupportedAppUsage
     void sendPointerDown(IBinder token, int pointerId, int x, int y);
+    @UnsupportedAppUsage
     void sendPointerUp(IBinder token, int pointerId);
+    @UnsupportedAppUsage
     void sendPointerSync(IBinder token);
 }
\ No newline at end of file
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 031e373..cfcba76 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -18,8 +18,11 @@
 #define LOG_TAG "ImageWriter_JNI"
 #include "android_media_Utils.h"
 
+#include <utils/Condition.h>
 #include <utils/Log.h>
+#include <utils/Mutex.h>
 #include <utils/String8.h>
+#include <utils/Thread.h>
 
 #include <gui/IProducerListener.h>
 #include <gui/Surface.h>
@@ -34,6 +37,8 @@
 #include <inttypes.h>
 #include <android/hardware_buffer_jni.h>
 
+#include <deque>
+
 #define IMAGE_BUFFER_JNI_ID           "mNativeBuffer"
 #define IMAGE_FORMAT_UNKNOWN          0 // This is the same value as ImageFormat#UNKNOWN.
 // ----------------------------------------------------------------------------
@@ -90,14 +95,124 @@
     int mFormat;
     int mWidth;
     int mHeight;
+
+    // Class for a shared thread used to detach buffers from buffer queues
+    // to discard buffers after consumers are done using them.
+    // This is needed because detaching buffers in onBufferReleased callback
+    // can lead to deadlock when consumer/producer are on the same process.
+    class BufferDetacher {
+    public:
+        // Called by JNIImageWriterContext ctor. Will start the thread for first ref.
+        void addRef();
+        // Called by JNIImageWriterContext dtor. Will stop the thread after ref goes to 0.
+        void removeRef();
+        // Called by onBufferReleased to signal this thread to detach a buffer
+        void detach(wp<Surface>);
+
+    private:
+
+        class DetachThread : public Thread {
+        public:
+            DetachThread() : Thread(/*canCallJava*/false) {};
+
+            void detach(wp<Surface>);
+
+            virtual void requestExit() override;
+
+        private:
+            virtual bool threadLoop() override;
+
+            Mutex     mLock;
+            Condition mCondition;
+            std::deque<wp<Surface>> mQueue;
+
+            static const nsecs_t kWaitDuration = 20000000; // 20 ms
+        };
+        sp<DetachThread> mThread;
+
+        Mutex     mLock;
+        int       mRefCount = 0;
+    };
+
+    static BufferDetacher sBufferDetacher;
 };
 
+JNIImageWriterContext::BufferDetacher JNIImageWriterContext::sBufferDetacher;
+
+void JNIImageWriterContext::BufferDetacher::addRef() {
+    Mutex::Autolock l(mLock);
+    mRefCount++;
+    if (mRefCount == 1) {
+        mThread = new DetachThread();
+        mThread->run("BufDtchThrd");
+    }
+}
+
+void JNIImageWriterContext::BufferDetacher::removeRef() {
+    Mutex::Autolock l(mLock);
+    mRefCount--;
+    if (mRefCount == 0) {
+        mThread->requestExit();
+        mThread->join();
+        mThread.clear();
+    }
+}
+
+void JNIImageWriterContext::BufferDetacher::detach(wp<Surface> bq) {
+    Mutex::Autolock l(mLock);
+    if (mThread == nullptr) {
+        ALOGE("%s: buffer detach thread is gone!", __FUNCTION__);
+        return;
+    }
+    mThread->detach(bq);
+}
+
+void JNIImageWriterContext::BufferDetacher::DetachThread::detach(wp<Surface> bq) {
+    Mutex::Autolock l(mLock);
+    mQueue.push_back(bq);
+    mCondition.signal();
+}
+
+void JNIImageWriterContext::BufferDetacher::DetachThread::requestExit() {
+    Thread::requestExit();
+    {
+        Mutex::Autolock l(mLock);
+        mQueue.clear();
+    }
+    mCondition.signal();
+}
+
+bool JNIImageWriterContext::BufferDetacher::DetachThread::threadLoop() {
+    Mutex::Autolock l(mLock);
+    mCondition.waitRelative(mLock, kWaitDuration);
+
+    while (!mQueue.empty()) {
+        if (exitPending()) {
+            return false;
+        }
+
+        wp<Surface> wbq = mQueue.front();
+        mQueue.pop_front();
+        sp<Surface> bq = wbq.promote();
+        if (bq != nullptr) {
+            sp<Fence> fence;
+            sp<GraphicBuffer> buffer;
+            ALOGV("%s: One buffer is detached", __FUNCTION__);
+            mLock.unlock();
+            bq->detachNextBuffer(&buffer, &fence);
+            mLock.lock();
+        }
+    }
+    return !exitPending();
+}
+
 JNIImageWriterContext::JNIImageWriterContext(JNIEnv* env, jobject weakThiz, jclass clazz) :
-    mWeakThiz(env->NewGlobalRef(weakThiz)),
-    mClazz((jclass)env->NewGlobalRef(clazz)),
-    mFormat(0),
-    mWidth(-1),
-    mHeight(-1) {
+        mWeakThiz(env->NewGlobalRef(weakThiz)),
+        mClazz((jclass)env->NewGlobalRef(clazz)),
+        mFormat(0),
+        mWidth(-1),
+        mHeight(-1) {
+    sBufferDetacher.addRef();
 }
 
 JNIImageWriterContext::~JNIImageWriterContext() {
@@ -115,6 +230,7 @@
     }
 
     mProducer.clear();
+    sBufferDetacher.removeRef();
 }
 
 JNIEnv* JNIImageWriterContext::getJNIEnv(bool* needsDetach) {
@@ -153,10 +269,7 @@
         // need let this callback give a BufferItem, then only detach if it was attached to this
         // Writer. Do the detach unconditionally for opaque format now. see b/19977520
         if (mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
-            sp<Fence> fence;
-            sp<GraphicBuffer> buffer;
-            ALOGV("%s: One buffer is detached", __FUNCTION__);
-            mProducer->detachNextBuffer(&buffer, &fence);
+            sBufferDetacher.detach(mProducer);
         }
 
         env->CallStaticVoidMethod(mClazz, gImageWriterClassInfo.postEventFromNative, mWeakThiz);
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 0894ee5..2a43238 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -17,7 +17,9 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.captiveportallogin" >
+    package="com.android.captiveportallogin"
+    android:versionCode="10"
+    android:versionName="Q-initial">
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/packages/CarSystemUI/res/drawable/car_ic_selection_bg.xml b/packages/CarSystemUI/res/drawable/car_ic_selection_bg.xml
index 781beaf..12993f5 100644
--- a/packages/CarSystemUI/res/drawable/car_ic_selection_bg.xml
+++ b/packages/CarSystemUI/res/drawable/car_ic_selection_bg.xml
@@ -20,7 +20,7 @@
     android:viewportHeight="70.0"
     android:viewportWidth="70.0">
     <path
-        android:fillColor="@color/car_accent"
+        android:fillColor="?android:attr/colorAccent"
         android:fillType="evenOdd"
         android:pathData="M4,0L66,0A4,4 0,0 1,70 4L70,66A4,4 0,0 1,66 70L4,70A4,4 0,0 1,0 66L0,4A4,4 0,0 1,4 0z"
         android:strokeColor="#00000000"
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 369bb9f..bd0e0b8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -92,6 +92,10 @@
 
     @Override
     public void start() {
+        // get the provisioned state before calling the parent class since it's that flow that
+        // builds the nav bar
+        mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+        mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
         super.start();
         mTaskStackListener = new TaskStackListenerImpl();
         mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
@@ -105,8 +109,6 @@
         mHvacController.connectToCarService();
 
         CarSystemUIFactory factory = SystemUIFactory.getInstance();
-        mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
-        mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
         if (!mDeviceIsProvisioned) {
             mDeviceProvisionedController.addCallback(
                     new DeviceProvisionedController.DeviceProvisionedListener() {
diff --git a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
index 6cf72a4..ba361c4 100644
--- a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
+++ b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
@@ -26,6 +26,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 
 /**
  * Observes the settings for {@link Assistant}.
@@ -103,7 +104,7 @@
 
     private void registerDeviceConfigs() {
         DeviceConfig.addOnPropertyChangedListener(
-                DeviceConfig.NotificationAssistant.NAMESPACE,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
                 this::postToHandler,
                 this::onDeviceConfigPropertyChanged);
 
@@ -117,7 +118,7 @@
 
     @VisibleForTesting
     void onDeviceConfigPropertyChanged(String namespace, String name, String value) {
-        if (!DeviceConfig.NotificationAssistant.NAMESPACE.equals(namespace)) {
+        if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(namespace)) {
             Log.e(LOG_TAG, "Received update from DeviceConfig for unrelated namespace: "
                     + namespace + " " + name + "=" + value);
             return;
@@ -128,17 +129,17 @@
 
     private void updateFromDeviceConfigFlags() {
         mGenerateReplies = DeviceConfigHelper.getBoolean(
-                DeviceConfig.NotificationAssistant.GENERATE_REPLIES, DEFAULT_GENERATE_REPLIES);
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES, DEFAULT_GENERATE_REPLIES);
 
         mGenerateActions = DeviceConfigHelper.getBoolean(
-                DeviceConfig.NotificationAssistant.GENERATE_ACTIONS, DEFAULT_GENERATE_ACTIONS);
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS, DEFAULT_GENERATE_ACTIONS);
 
         mMaxMessagesToExtract = DeviceConfigHelper.getInteger(
-                DeviceConfig.NotificationAssistant.MAX_MESSAGES_TO_EXTRACT,
+                SystemUiDeviceConfigFlags.NAS_MAX_MESSAGES_TO_EXTRACT,
                 DEFAULT_MAX_MESSAGES_TO_EXTRACT);
 
         mMaxSuggestions = DeviceConfigHelper.getInteger(
-                DeviceConfig.NotificationAssistant.MAX_SUGGESTIONS, DEFAULT_MAX_SUGGESTIONS);
+                SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS, DEFAULT_MAX_SUGGESTIONS);
 
         mOnUpdateRunnable.run();
     }
@@ -193,8 +194,7 @@
 
         private static String getValue(String key) {
             return DeviceConfig.getProperty(
-                    DeviceConfig.NotificationAssistant.NAMESPACE,
-                    key);
+                    DeviceConfig.NAMESPACE_SYSTEMUI, key);
         }
     }
 
@@ -202,4 +202,4 @@
         AssistantSettings createAndRegister(Handler handler, ContentResolver resolver, int userId,
                 Runnable onUpdateRunnable);
     }
-}
\ No newline at end of file
+}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
index d890c1a..851e2f2 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
@@ -17,7 +17,6 @@
 package android.ext.services.notification;
 
 import static android.ext.services.notification.AssistantSettings.DEFAULT_MAX_SUGGESTIONS;
-import static android.provider.DeviceConfig.NotificationAssistant;
 import static android.provider.DeviceConfig.setProperty;
 
 import static junit.framework.Assert.assertFalse;
@@ -30,12 +29,15 @@
 import android.content.ContentResolver;
 import android.os.Handler;
 import android.os.Looper;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.testing.TestableContext;
 
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -49,7 +51,7 @@
 @RunWith(AndroidJUnit4.class)
 public class AssistantSettingsTest {
     private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
-            "device_config delete " + NotificationAssistant.NAMESPACE;
+            "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI;
 
     private static final int USER_ID = 5;
 
@@ -87,13 +89,13 @@
     @Test
     public void testGenerateRepliesDisabled() {
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_REPLIES,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "false",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_REPLIES,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "false");
 
         assertFalse(mAssistantSettings.mGenerateReplies);
@@ -102,13 +104,13 @@
     @Test
     public void testGenerateRepliesEnabled() {
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_REPLIES,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "true",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_REPLIES,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "true");
 
         assertTrue(mAssistantSettings.mGenerateReplies);
@@ -117,25 +119,25 @@
     @Test
     public void testGenerateRepliesEmptyFlag() {
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_REPLIES,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "false",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_REPLIES,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "false");
 
         assertFalse(mAssistantSettings.mGenerateReplies);
 
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_REPLIES,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_REPLIES,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "");
 
         // Go back to the default value.
@@ -145,13 +147,13 @@
     @Test
     public void testGenerateActionsDisabled() {
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_ACTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "false",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_ACTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "false");
 
         assertFalse(mAssistantSettings.mGenerateActions);
@@ -160,13 +162,13 @@
     @Test
     public void testGenerateActionsEnabled() {
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_ACTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "true",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_ACTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "true");
 
         assertTrue(mAssistantSettings.mGenerateActions);
@@ -175,25 +177,25 @@
     @Test
     public void testGenerateActionsEmptyFlag() {
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_ACTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "false",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_ACTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "false");
 
         assertFalse(mAssistantSettings.mGenerateActions);
 
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_ACTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.GENERATE_ACTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "");
 
         // Go back to the default value.
@@ -203,13 +205,13 @@
     @Test
     public void testMaxMessagesToExtract() {
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.MAX_MESSAGES_TO_EXTRACT,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_MAX_MESSAGES_TO_EXTRACT,
                 "10",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.MAX_MESSAGES_TO_EXTRACT,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_MAX_MESSAGES_TO_EXTRACT,
                 "10");
 
         assertEquals(10, mAssistantSettings.mMaxMessagesToExtract);
@@ -218,13 +220,13 @@
     @Test
     public void testMaxSuggestions() {
         setProperty(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.MAX_SUGGESTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS,
                 "5",
                 false /* makeDefault */);
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.MAX_SUGGESTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS,
                 "5");
 
         assertEquals(5, mAssistantSettings.mMaxSuggestions);
@@ -233,8 +235,8 @@
     @Test
     public void testMaxSuggestionsEmpty() {
         mAssistantSettings.onDeviceConfigPropertyChanged(
-                NotificationAssistant.NAMESPACE,
-                NotificationAssistant.MAX_SUGGESTIONS,
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS,
                 "");
 
         assertEquals(DEFAULT_MAX_SUGGESTIONS, mAssistantSettings.mMaxSuggestions);
@@ -278,13 +280,14 @@
     private static void clearDeviceConfig() throws IOException {
         UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         uiDevice.executeShellCommand(
-                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + NotificationAssistant.GENERATE_ACTIONS);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS);
         uiDevice.executeShellCommand(
-                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + NotificationAssistant.GENERATE_REPLIES);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES);
         uiDevice.executeShellCommand(
-                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + NotificationAssistant.MAX_MESSAGES_TO_EXTRACT);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " "
+                + SystemUiDeviceConfigFlags.NAS_MAX_MESSAGES_TO_EXTRACT);
         uiDevice.executeShellCommand(
-                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + NotificationAssistant.MAX_SUGGESTIONS);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS);
     }
 
 }
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 52c209e..90521de 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -18,7 +18,9 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack"
-          android:sharedUserId="android.uid.networkstack">
+          android:sharedUserId="android.uid.networkstack"
+          android:versionCode="10"
+          android:versionName="Q-initial">
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/packages/NetworkStackPermissionStub/AndroidManifest.xml b/packages/NetworkStackPermissionStub/AndroidManifest.xml
index a8742d7..ba8a178 100644
--- a/packages/NetworkStackPermissionStub/AndroidManifest.xml
+++ b/packages/NetworkStackPermissionStub/AndroidManifest.xml
@@ -18,7 +18,9 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.networkstack.permissionstub"
-    android:sharedUserId="android.uid.networkstack">
+    android:sharedUserId="android.uid.networkstack"
+    android:versionCode="10"
+    android:versionName="Q-initial">
     <!--
     This package only exists to define the below permissions, and enforce that they are only
     granted to apps sharing the same signature.
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..911cfcd
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -0,0 +1,412 @@
+/*
+ * 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 = context.resources.getInteger(
+            com.android.internal.R.integer.config_criticalBatteryWarningLevel)
+
+    var charging = false
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
+    var powerSaveEnabled = false
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
+    private val fillColorStrokePaint = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
+        p.color = frameColor
+        p.isDither = true
+        p.strokeWidth = 5f
+        p.style = Paint.Style.STROKE
+        p.blendMode = BlendMode.SRC
+        p.strokeMiter = 5f
+        p.strokeJoin = Paint.Join.ROUND
+    }
+
+    private val fillColorStrokeProtection = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
+        p.isDither = true
+        p.strokeWidth = 5f
+        p.style = Paint.Style.STROKE
+        p.blendMode = BlendMode.CLEAR
+        p.strokeMiter = 5f
+        p.strokeJoin = Paint.Join.ROUND
+    }
+
+    private val fillPaint = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
+        p.color = frameColor
+        p.alpha = 255
+        p.isDither = true
+        p.strokeWidth = 0f
+        p.style = Paint.Style.FILL_AND_STROKE
+    }
+
+    // Only used if dualTone is set to true
+    private val dualToneBackgroundFill = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
+        p.color = frameColor
+        p.alpha = 255
+        p.isDither = true
+        p.strokeWidth = 0f
+        p.style = Paint.Style.FILL_AND_STROKE
+    }
+
+    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()
+
+        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 -> fillColor
+            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
+
+        // Also update the level color, since fillColor may have changed
+        levelColor = batteryColorForLevel(level)
+
+        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 / WIDTH), (b.bottom / HEIGHT))
+        }
+
+        perimeterPath.transform(scaleMatrix, scaledPerimeter)
+        fillMask.transform(scaleMatrix, scaledFill)
+        scaledFill.computeBounds(fillRect, true)
+        boltPath.transform(scaleMatrix, scaledBolt)
+        plusPath.transform(scaleMatrix, scaledPlus)
+
+        // It is expected that this view only ever scale by the same factor in each dimension, so
+        // just pick one to scale the strokeWidths
+        val scaledStrokeWidth =
+                Math.max(b.right / WIDTH * PROTECTION_STROKE_WIDTH, PROTECTION_MIN_STROKE_WIDTH)
+
+        fillColorStrokePaint.strokeWidth = scaledStrokeWidth
+        fillColorStrokeProtection.strokeWidth = scaledStrokeWidth
+    }
+
+    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
+        // On a 12x20 grid, how wide to make the fill protection stroke.
+        // Scales when our size changes
+        private const val PROTECTION_STROKE_WIDTH = 1.4f
+        // Arbitrarily chosen for visibility at small sizes
+        private const val PROTECTION_MIN_STROKE_WIDTH = 5f
+    }
+}
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/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 26ea6ab..65e0c0f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -40,8 +40,8 @@
     <bool name="def_wifi_display_on">false</bool>
     <bool name="def_install_non_market_apps">false</bool>
     <bool name="def_package_verifier_enable">true</bool>
-    <!-- Comma-separated list of location providers -->
-    <string name="def_location_providers_allowed" translatable="false">gps,network</string>
+    <!-- 0 == off, 3 == on -->
+    <integer name="def_location_mode">3</integer>
     <bool name="assisted_gps_enabled">true</bool>
     <bool name="def_netstats_enabled">true</bool>
     <bool name="def_usb_mass_storage_enabled">true</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 0ee16a9..5e2b7c8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2340,9 +2340,6 @@
             stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
                     + " VALUES(?,?);");
 
-            loadStringSetting(stmt, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
-                    R.string.def_location_providers_allowed);
-
             // Don't do this.  The SystemServer will initialize ADB_ENABLED from a
             // persistent system property instead.
             //loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index ceafbfa..d6c33a3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -969,6 +969,11 @@
                 try {
                     synchronized (mLock) {
                         Setting setting = getSecureSetting(
+                                Settings.Secure.LOCATION_MODE, userId);
+                        updateSecureSetting(Settings.Secure.LOCATION_MODE,
+                                setting != null ? setting.getValue() : null, null,
+                                true, userId, true);
+                        setting = getSecureSetting(
                                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
                         updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                                 setting != null ? setting.getValue() : null, null,
@@ -4229,23 +4234,18 @@
                         final Setting locationProvidersAllowed = secureSettings.getSettingLocked(
                                 Secure.LOCATION_PROVIDERS_ALLOWED);
 
-                        String defLocationMode = Integer.toString(
-                                !TextUtils.isEmpty(locationProvidersAllowed.getValue())
-                                        ? Secure.LOCATION_MODE_ON
-                                        : Secure.LOCATION_MODE_OFF);
+                        final int defLocationMode;
+                        if (locationProvidersAllowed.isNull()) {
+                            defLocationMode = getContext().getResources().getInteger(
+                                    R.integer.def_location_mode);
+                        } else {
+                            defLocationMode =
+                                    !TextUtils.isEmpty(locationProvidersAllowed.getValue())
+                                            ? Secure.LOCATION_MODE_ON
+                                            : Secure.LOCATION_MODE_OFF;
+                        }
                         secureSettings.insertSettingLocked(
-                                Secure.LOCATION_MODE, defLocationMode,
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-
-                        // also reset LOCATION_PROVIDERS_ALLOWED back to the default value - this
-                        // setting is now only for debug/test purposes, and will likely be removed
-                        // in a later release. LocationManagerService is responsible for adjusting
-                        // these settings to the proper state.
-
-                        String defLocationProvidersAllowed = getContext().getResources().getString(
-                                R.string.def_location_providers_allowed);
-                        secureSettings.insertSettingLocked(
-                                Secure.LOCATION_PROVIDERS_ALLOWED, defLocationProvidersAllowed,
+                                Secure.LOCATION_MODE, Integer.toString(defLocationMode),
                                 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
                     }
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 0da3b10..fc6ef2b 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -146,6 +146,7 @@
     <uses-permission android:name="android.permission.SET_TIME_ZONE" />
     <uses-permission android:name="android.permission.DISABLE_HIDDEN_API_CHECKS" />
     <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
+    <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
     <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
     <!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) -->
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
diff --git a/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml b/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
index d3c3a51..a2404b0 100644
--- a/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
+++ b/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
@@ -1,9 +1,9 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="200dp"
-    android:width="200dp"
-    android:viewportHeight="100"
-    android:viewportWidth="100">
+    android:height="350dp"
+    android:width="350dp"
+    android:viewportHeight="254.66145"
+    android:viewportWidth="254.66145">
     <path
         android:fillColor="#000000"
-        android:pathData="M50.082,14.199m-13.985,0a13.985,13.985 0,1 1,27.97 0a13.985,13.985 0,1 1,-27.97 0"/>
+        android:pathData="M127.331,40.481m-10.914,0a10.914,10.914 0,1 1,21.828 0a10.914,10.914 0,1 1,-21.828 0"/>
 </vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml b/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
index a4417fb..be10b5d 100644
--- a/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
+++ b/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
@@ -1,9 +1,11 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="200dp"
-    android:width="200dp"
-    android:viewportHeight="100"
-    android:viewportWidth="100" >
+    android:height="350dp"
+    android:width="350dp"
+    android:viewportHeight="254.66145"
+    android:viewportWidth="254.66145" >
     <path
-        android:fillColor="#000000"
-        android:pathData="M50.082,0.025L50.082,0.025A13.985,15.63 0,0 1,64.067 15.656L64.067,49.029A13.985,15.63 0,0 1,50.082 64.659L50.082,64.659A13.985,15.63 0,0 1,36.097 49.029L36.097,15.656A13.985,15.63 0,0 1,50.082 0.025z"/>
+        android:strokeColor="#000000"
+        android:strokeWidth="5"
+        android:pathData="M125.923,29.692L128.739,29.692A27.108,30.579 0,0 1,155.847 60.271L155.847,125.268A27.108,30.579 0,0 1,128.739 155.847L125.923,155.847A27.108,30.579 0,0 1,98.815 125.268L98.815,60.271A27.108,30.579 0,0 1,125.923 29.692z"/>
 </vector>
+
diff --git a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
index c8dc8e4..0bc1319 100644
--- a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
@@ -42,15 +42,15 @@
   >
     <ImageView
         android:id="@+id/minute_hand"
-        android:layout_width="300dp"
-        android:layout_height="300dp"
+        android:layout_width="350dp"
+        android:layout_height="350dp"
         android:src="@drawable/bubble_minute_hand"
         android:tint="@color/bubbleMinuteHandColor"
     />
     <ImageView
         android:id="@+id/hour_hand"
-        android:layout_width="300dp"
-        android:layout_height="300dp"
+        android:layout_width="350dp"
+        android:layout_height="350dp"
         android:src="@drawable/bubble_hour_hand"
         android:tint="@color/bubbleHourHandColor"
     />
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 91353d7..863c1cc 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -178,6 +178,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_centerVertical="true"
+                android:maxWidth="100dp"
                 style="@style/TextAppearance.NotificationInfo.Button"/>
 
             <LinearLayout
@@ -186,6 +187,7 @@
                 android:layout_height="wrap_content"
                 android:layout_centerVertical="true"
                 android:layout_alignParentEnd="true"
+                android:maxWidth="200dp"
                 android:orientation="horizontal">
                 <TextView
                     android:id="@+id/deliver_silently"
@@ -195,6 +197,7 @@
                     android:layout_centerVertical="true"
                     android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
                     android:paddingRight="24dp"
+                    android:maxWidth="125dp"
                     style="@style/TextAppearance.NotificationInfo.Button"/>
                 <TextView
                     android:id="@+id/block"
@@ -203,6 +206,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_centerVertical="true"
+                    android:maxWidth="75dp"
                     android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
                     style="@style/TextAppearance.NotificationInfo.Button"/>
                 <TextView
@@ -212,6 +216,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_centerVertical="true"
+                    android:maxWidth="75dp"
                     android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
                     style="@style/TextAppearance.NotificationInfo.Button"/>
             </LinearLayout>
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/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4905e57..d53c785 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1579,7 +1579,7 @@
     <string name="inline_blocking_helper">You usually dismiss these notifications.
     \nKeep showing them?</string>
 
-    <!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=25] -->
+    <!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=20] -->
     <string name="inline_done_button">Done</string>
 
     <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
@@ -1588,7 +1588,7 @@
     <!-- Notification inline controls: block notifications button [CHAR_LIMIT=25] -->
     <string name="inline_stop_button">Stop notifications</string>
 
-    <!-- Notification inline controls: button to deliver notifications silently from this channel [CHAR_LIMIT=35] -->
+    <!-- Notification inline controls: button to deliver notifications silently from this channel [CHAR_LIMIT=30] -->
     <string name="inline_deliver_silently_button">Deliver Silently</string>
 
     <!-- Notification inline controls: button to block notifications from this channel [CHAR_LIMIT=20] -->
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/shared/src/com/android/systemui/shared/system/InputConsumerController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
index 0cde9da..e554dcd 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
@@ -27,26 +27,26 @@
 import android.util.Log;
 import android.view.BatchedInputEventReceiver;
 import android.view.Choreographer;
+import android.view.IWindowManager;
 import android.view.InputChannel;
 import android.view.InputEvent;
-import android.view.IWindowManager;
-import android.view.MotionEvent;
 import android.view.WindowManagerGlobal;
 
 import java.io.PrintWriter;
 
 /**
- * Manages the input consumer that allows the SystemUI to directly receive touch input.
+ * Manages the input consumer that allows the SystemUI to directly receive input.
  */
 public class InputConsumerController {
 
     private static final String TAG = InputConsumerController.class.getSimpleName();
 
     /**
-     * Listener interface for callers to subscribe to touch events.
+     * Listener interface for callers to subscribe to input events.
      */
-    public interface TouchListener {
-        boolean onTouchEvent(MotionEvent ev);
+    public interface InputListener {
+        /** Handles any input event. */
+        boolean onInputEvent(InputEvent ev);
     }
 
     /**
@@ -71,9 +71,8 @@
         public void onInputEvent(InputEvent event) {
             boolean handled = true;
             try {
-                if (mListener != null && event instanceof MotionEvent) {
-                    MotionEvent ev = (MotionEvent) event;
-                    handled = mListener.onTouchEvent(ev);
+                if (mListener != null) {
+                    handled = mListener.onInputEvent(event);
                 }
             } finally {
                 finishInputEvent(event, handled);
@@ -86,7 +85,7 @@
     private final String mName;
 
     private InputEventReceiver mInputEventReceiver;
-    private TouchListener mListener;
+    private InputListener mListener;
     private RegistrationListener mRegistrationListener;
 
     /**
@@ -115,9 +114,9 @@
     }
 
     /**
-     * Sets the touch listener.
+     * Sets the input listener.
      */
-    public void setTouchListener(TouchListener listener) {
+    public void setInputListener(InputListener listener) {
         mListener = listener;
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index 3d2f61e..c54a469 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -48,6 +48,21 @@
         onActivityLaunchOnSecondaryDisplayFailed();
     }
 
+    /**
+     * @see #onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo)
+     */
+    public void onActivityLaunchOnSecondaryDisplayRerouted() { }
+
+    /**
+     * Called when an activity was requested to be launched on a secondary display but was rerouted
+     * to default display.
+     *
+     * @param taskInfo info about the Activity's task
+     */
+    public void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo) {
+        onActivityLaunchOnSecondaryDisplayRerouted();
+    }
+
     public void onTaskProfileLocked(int taskId, int userId) { }
     public void onTaskCreated(int taskId, ComponentName componentName) { }
     public void onTaskRemoved(int taskId) { }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index a9ac42f..7e4ab85 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -141,6 +141,13 @@
     }
 
     @Override
+    public void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo,
+            int requestedDisplayId) throws RemoteException {
+        mHandler.obtainMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED,
+                 requestedDisplayId, 0 /* unused */, taskInfo).sendToTarget();
+    }
+
+    @Override
     public void onTaskProfileLocked(int taskId, int userId) throws RemoteException {
         mHandler.obtainMessage(H.ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget();
     }
@@ -189,6 +196,7 @@
         private static final int ON_TASK_REMOVED = 13;
         private static final int ON_TASK_MOVED_TO_FRONT = 14;
         private static final int ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE = 15;
+        private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED = 16;
 
 
         public H(Looper looper) {
@@ -270,6 +278,14 @@
                         }
                         break;
                     }
+                    case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED: {
+                        final RunningTaskInfo info = (RunningTaskInfo) msg.obj;
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i)
+                                .onActivityLaunchOnSecondaryDisplayRerouted(info);
+                        }
+                        break;
+                    }
                     case ON_TASK_PROFILE_LOCKED: {
                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
                             mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2);
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/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 2a1d066..f5451e9 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -63,6 +63,9 @@
 
     public HardwareUiLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
+        // Manually re-initialize mRotation to portrait-mode, since this view must always
+        // be constructed in portrait mode and rotated into the correct initial position.
+        mRotation = ROTATION_NONE;
         updateSettings();
     }
 
@@ -172,6 +175,10 @@
                 mSeparatedView.setBackground(mSeparatedViewBackground);
                 updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
                 mOldHeight = mList.getMeasuredHeight();
+
+                // Must be called to initialize view rotation correctly.
+                // Requires LayoutParams, hence why this isn't called during the constructor.
+                updateRotation();
             } else {
                 return;
             }
@@ -189,7 +196,18 @@
         mSwapOrientation = swapOrientation;
     }
 
-    @Override
+    private void updateRotation() {
+        int rotation = RotationUtils.getRotation(getContext());
+        if (rotation != mRotation) {
+            rotate(mRotation, rotation);
+            mRotation = rotation;
+        }
+    }
+
+    /**
+     *  Requires LayoutParams to be set to work correctly, and therefore must be run after after
+     *  the HardwareUILayout has been added to the view hierarchy.
+     */
     protected void rotate(int from, int to) {
         super.rotate(from, to);
         if (from != ROTATION_NONE && to != ROTATION_NONE) {
@@ -522,4 +540,4 @@
         inoutInfo.contentInsets.set(mList.getLeft(), mList.getTop(),
                 0, getBottom() - mList.getBottom());
     };
-}
+}
\ No newline at end of file
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..77180f8 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;
@@ -190,15 +190,6 @@
         }
     }
 
-    public void reregisterAllSensors() {
-        for (TriggerSensor s : mSensors) {
-            s.setListening(false);
-        }
-        for (TriggerSensor s : mSensors) {
-            s.setListening(true);
-        }
-    }
-
     public void onUserSwitched() {
         for (TriggerSensor s : mSensors) {
             s.updateListener();
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index b6e830c..b2f707f 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;
@@ -238,9 +238,6 @@
             case DOZE:
             case DOZE_AOD:
                 mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
-                if (oldState != DozeMachine.State.INITIALIZED) {
-                    mDozeSensors.reregisterAllSensors();
-                }
                 mDozeSensors.setListening(true);
                 if (newState == DozeMachine.State.DOZE_AOD && !sWakeDisplaySensorState) {
                     onWakeScreen(false, newState);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index cef1b6b..3140e6d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -37,6 +37,7 @@
 import android.util.Log;
 import android.util.Size;
 import android.view.IPinnedStackController;
+import android.view.InputEvent;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
@@ -206,7 +207,7 @@
         mEnableDimissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
 
         // Register the listener for input consumer touch events
-        inputConsumerController.setTouchListener(this::handleTouchEvent);
+        inputConsumerController.setInputListener(this::handleTouchEvent);
         inputConsumerController.setRegistrationListener(this::onRegistrationChanged);
         onRegistrationChanged(inputConsumerController.isRegistered());
     }
@@ -370,11 +371,16 @@
                 mMovementBounds, true /* allowMenuTimeout */, willResizeMenu());
     }
 
-    private boolean handleTouchEvent(MotionEvent ev) {
+    private boolean handleTouchEvent(InputEvent inputEvent) {
+        // Skip any non motion events
+        if (!(inputEvent instanceof MotionEvent)) {
+            return true;
+        }
         // Skip touch handling until we are bound to the controller
         if (mPinnedStackController == null) {
             return true;
         }
+        MotionEvent ev = (MotionEvent) inputEvent;
 
         // Update the touch state
         mTouchState.onTouchEvent(ev);
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/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index b65c4a5..b4dd114 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -34,12 +34,17 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.widget.ImageMessageConsumer;
+import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.InflationTask;
+import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.notification.InflationException;
 import com.android.systemui.statusbar.notification.MediaNotificationProcessor;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.InflatedSmartReplies;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
 import com.android.systemui.util.Assert;
 
 import java.lang.annotation.Retention;
@@ -278,6 +283,8 @@
         InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority,
                 mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight,
                 mRedactAmbient, packageContext);
+        result = inflateSmartReplyViews(result, reInflateFlags, mRow.getEntry(),
+                mRow.getContext(), mRow.getHeadsUpManager());
         apply(
                 inflateSynchronously,
                 result,
@@ -306,6 +313,7 @@
                 if (mRow.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) {
                     mRow.getPrivateLayout().setHeadsUpChild(null);
                     mCachedContentViews.remove(FLAG_CONTENT_VIEW_HEADS_UP);
+                    mRow.getPrivateLayout().setHeadsUpInflatedSmartReplies(null);
                 }
                 break;
             case FLAG_CONTENT_VIEW_AMBIENT:
@@ -336,12 +344,33 @@
         }
     }
 
+    private static InflationProgress inflateSmartReplyViews(InflationProgress result,
+            @InflationFlag int reInflateFlags, NotificationEntry entry, Context context,
+            HeadsUpManager headsUpManager) {
+        SmartReplyConstants smartReplyConstants = Dependency.get(SmartReplyConstants.class);
+        SmartReplyController smartReplyController = Dependency.get(SmartReplyController.class);
+        if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0 && result.newExpandedView != null) {
+            result.expandedInflatedSmartReplies =
+                    InflatedSmartReplies.inflate(
+                            context, entry, smartReplyConstants, smartReplyController,
+                            headsUpManager);
+        }
+        if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0 && result.newHeadsUpView != null) {
+            result.headsUpInflatedSmartReplies =
+                    InflatedSmartReplies.inflate(
+                            context, entry, smartReplyConstants, smartReplyController,
+                            headsUpManager);
+        }
+        return result;
+    }
+
     private static InflationProgress createRemoteViews(@InflationFlag int reInflateFlags,
             Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup,
             boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
             Context packageContext) {
         InflationProgress result = new InflationProgress();
         isLowPriority = isLowPriority && !isChildInGroup;
+
         if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
             result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);
         }
@@ -661,6 +690,12 @@
                 } else if (result.newExpandedView == null) {
                     privateLayout.setExpandedChild(null);
                 }
+                if (result.newExpandedView != null) {
+                    privateLayout.setExpandedInflatedSmartReplies(
+                            result.expandedInflatedSmartReplies);
+                } else {
+                    privateLayout.setExpandedInflatedSmartReplies(null);
+                }
                 cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView);
                 row.setExpandable(result.newExpandedView != null);
             }
@@ -671,6 +706,12 @@
                 } else if (result.newHeadsUpView == null) {
                     privateLayout.setHeadsUpChild(null);
                 }
+                if (result.newHeadsUpView != null) {
+                    privateLayout.setHeadsUpInflatedSmartReplies(
+                            result.headsUpInflatedSmartReplies);
+                } else {
+                    privateLayout.setHeadsUpInflatedSmartReplies(null);
+                }
                 cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView);
             }
 
@@ -846,9 +887,12 @@
                             packageContext);
                     processor.processNotification(notification, recoveredBuilder);
                 }
-                return createRemoteViews(mReInflateFlags, recoveredBuilder, mIsLowPriority,
+                InflationProgress inflationProgress = createRemoteViews(mReInflateFlags,
+                        recoveredBuilder, mIsLowPriority,
                         mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight,
                         mRedactAmbient, packageContext);
+                return inflateSmartReplyViews(inflationProgress, mReInflateFlags, mRow.getEntry(),
+                        mRow.getContext(), mRow.getHeadsUpManager());
             } catch (Exception e) {
                 mError = e;
                 return null;
@@ -927,6 +971,9 @@
         private View inflatedPublicView;
         private CharSequence headsUpStatusBarText;
         private CharSequence headsUpStatusBarTextPublic;
+
+        private InflatedSmartReplies expandedInflatedSmartReplies;
+        private InflatedSmartReplies headsUpInflatedSmartReplies;
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 1dc48d4..646617c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.PendingIntent;
-import android.app.RemoteInput;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Build;
@@ -28,7 +27,6 @@
 import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.NotificationHeaderView;
 import android.view.View;
@@ -39,7 +37,6 @@
 import android.widget.LinearLayout;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
@@ -52,13 +49,14 @@
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.policy.InflatedSmartReplies;
+import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
 import com.android.systemui.statusbar.policy.RemoteInputView;
 import com.android.systemui.statusbar.policy.SmartReplyConstants;
 import com.android.systemui.statusbar.policy.SmartReplyView;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.List;
 
 /**
  * A frame layout containing the actual payload of the notification, including the contracted,
@@ -95,6 +93,8 @@
     private SmartReplyView mExpandedSmartReplyView;
     private SmartReplyView mHeadsUpSmartReplyView;
     private SmartReplyController mSmartReplyController;
+    private InflatedSmartReplies mExpandedInflatedSmartReplies;
+    private InflatedSmartReplies mHeadsUpInflatedSmartReplies;
 
     private NotificationViewWrapper mContractedWrapper;
     private NotificationViewWrapper mExpandedWrapper;
@@ -1318,8 +1318,22 @@
             return;
         }
 
-        SmartRepliesAndActions smartRepliesAndActions =
-                chooseSmartRepliesAndActions(mSmartReplyConstants, entry);
+        applyRemoteInput(entry, InflatedSmartReplies.hasFreeformRemoteInput(entry));
+
+        if (mExpandedInflatedSmartReplies == null && mHeadsUpInflatedSmartReplies == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Both expanded, and heads-up InflatedSmartReplies are null, "
+                        + "don't add smart replies.");
+            }
+            return;
+        }
+        // The inflated smart-reply objects for the expanded view and the heads-up view both contain
+        // the same SmartRepliesAndActions to avoid discrepancies between the two views. We here
+        // reuse that object for our local SmartRepliesAndActions to avoid discrepancies between
+        // this class and the InflatedSmartReplies classes.
+        SmartRepliesAndActions smartRepliesAndActions = mExpandedInflatedSmartReplies != null
+                ? mExpandedInflatedSmartReplies.getSmartRepliesAndActions()
+                : mHeadsUpInflatedSmartReplies.getSmartRepliesAndActions();
         if (DEBUG) {
             Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.",
                     entry.notification.getKey(),
@@ -1328,86 +1342,9 @@
                     smartRepliesAndActions.smartReplies == null ? 0 :
                             smartRepliesAndActions.smartReplies.choices.length));
         }
-
-        applyRemoteInput(entry, smartRepliesAndActions.hasFreeformRemoteInput);
         applySmartReplyView(smartRepliesAndActions, entry);
     }
 
-    /**
-     * Chose what smart replies and smart actions to display. App generated suggestions take
-     * precedence. So if the app provides any smart replies, we don't show any
-     * replies or actions generated by the NotificationAssistantService (NAS), and if the app
-     * provides any smart actions we also don't show any NAS-generated replies or actions.
-     */
-    @VisibleForTesting
-    static SmartRepliesAndActions chooseSmartRepliesAndActions(
-            SmartReplyConstants smartReplyConstants,
-            final NotificationEntry entry) {
-        Notification notification = entry.notification.getNotification();
-        Pair<RemoteInput, Notification.Action> remoteInputActionPair =
-                notification.findRemoteInputActionPair(false /* freeform */);
-        Pair<RemoteInput, Notification.Action> freeformRemoteInputActionPair =
-                notification.findRemoteInputActionPair(true /* freeform */);
-
-        if (!smartReplyConstants.isEnabled()) {
-            if (DEBUG) {
-                Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for "
-                        + entry.notification.getKey());
-            }
-            return new SmartRepliesAndActions(null, null, freeformRemoteInputActionPair != null);
-        }
-        // Only use smart replies from the app if they target P or above. We have this check because
-        // the smart reply API has been used for other things (Wearables) in the past. The API to
-        // add smart actions is new in Q so it doesn't require a target-sdk check.
-        boolean enableAppGeneratedSmartReplies = (!smartReplyConstants.requiresTargetingP()
-                || entry.targetSdk >= Build.VERSION_CODES.P);
-
-        boolean appGeneratedSmartRepliesExist =
-                enableAppGeneratedSmartReplies
-                        && remoteInputActionPair != null
-                        && !ArrayUtils.isEmpty(remoteInputActionPair.first.getChoices())
-                        && remoteInputActionPair.second.actionIntent != null;
-
-        List<Notification.Action> appGeneratedSmartActions = notification.getContextualActions();
-        boolean appGeneratedSmartActionsExist = !appGeneratedSmartActions.isEmpty();
-
-        SmartReplyView.SmartReplies smartReplies = null;
-        SmartReplyView.SmartActions smartActions = null;
-        if (appGeneratedSmartRepliesExist) {
-            smartReplies = new SmartReplyView.SmartReplies(
-                    remoteInputActionPair.first.getChoices(),
-                    remoteInputActionPair.first,
-                    remoteInputActionPair.second.actionIntent,
-                    false /* fromAssistant */);
-        }
-        if (appGeneratedSmartActionsExist) {
-            smartActions = new SmartReplyView.SmartActions(appGeneratedSmartActions,
-                    false /* fromAssistant */);
-        }
-        // Apps didn't provide any smart replies / actions, use those from NAS (if any).
-        if (!appGeneratedSmartRepliesExist && !appGeneratedSmartActionsExist) {
-            boolean useGeneratedReplies = !ArrayUtils.isEmpty(entry.systemGeneratedSmartReplies)
-                    && freeformRemoteInputActionPair != null
-                    && freeformRemoteInputActionPair.second.getAllowGeneratedReplies()
-                    && freeformRemoteInputActionPair.second.actionIntent != null;
-            if (useGeneratedReplies) {
-                smartReplies = new SmartReplyView.SmartReplies(
-                        entry.systemGeneratedSmartReplies,
-                        freeformRemoteInputActionPair.first,
-                        freeformRemoteInputActionPair.second.actionIntent,
-                        true /* fromAssistant */);
-            }
-            boolean useSmartActions = !ArrayUtils.isEmpty(entry.systemGeneratedSmartActions)
-                    && notification.getAllowSystemGeneratedContextualActions();
-            if (useSmartActions) {
-                smartActions = new SmartReplyView.SmartActions(
-                        entry.systemGeneratedSmartActions, true /* fromAssistant */);
-            }
-        }
-        return new SmartRepliesAndActions(
-                smartReplies, smartActions, freeformRemoteInputActionPair != null);
-    }
-
     private void applyRemoteInput(NotificationEntry entry, boolean hasFreeformRemoteInput) {
         View bigContentView = mExpandedChild;
         if (bigContentView != null) {
@@ -1507,11 +1444,12 @@
         return null;
     }
 
-    private void applySmartReplyView(SmartRepliesAndActions smartRepliesAndActions,
+    private void applySmartReplyView(
+            SmartRepliesAndActions smartRepliesAndActions,
             NotificationEntry entry) {
         if (mExpandedChild != null) {
-            mExpandedSmartReplyView =
-                    applySmartReplyView(mExpandedChild, smartRepliesAndActions, entry);
+            mExpandedSmartReplyView = applySmartReplyView(mExpandedChild, smartRepliesAndActions,
+                    entry, mExpandedInflatedSmartReplies);
             if (mExpandedSmartReplyView != null) {
                 if (smartRepliesAndActions.smartReplies != null
                         || smartRepliesAndActions.smartActions != null) {
@@ -1533,65 +1471,79 @@
             }
         }
         if (mHeadsUpChild != null && mSmartReplyConstants.getShowInHeadsUp()) {
-            mHeadsUpSmartReplyView =
-                    applySmartReplyView(mHeadsUpChild, smartRepliesAndActions, entry);
+            mHeadsUpSmartReplyView = applySmartReplyView(mHeadsUpChild, smartRepliesAndActions,
+                    entry, mHeadsUpInflatedSmartReplies);
         }
     }
 
+    @Nullable
     private SmartReplyView applySmartReplyView(View view,
-            SmartRepliesAndActions smartRepliesAndActions, NotificationEntry entry) {
+            SmartRepliesAndActions smartRepliesAndActions,
+            NotificationEntry entry, InflatedSmartReplies inflatedSmartReplyView) {
         View smartReplyContainerCandidate = view.findViewById(
                 com.android.internal.R.id.smart_reply_container);
         if (!(smartReplyContainerCandidate instanceof LinearLayout)) {
             return null;
         }
+
         LinearLayout smartReplyContainer = (LinearLayout) smartReplyContainerCandidate;
-        // If there are no smart replies and no smart actions - early out.
-        if (smartRepliesAndActions.smartReplies == null
-                && smartRepliesAndActions.smartActions == null) {
+        if (!InflatedSmartReplies.shouldShowSmartReplyView(entry, smartRepliesAndActions)) {
             smartReplyContainer.setVisibility(View.GONE);
             return null;
         }
-        // If we are showing the spinner we don't want to add the buttons.
-        boolean showingSpinner = entry.notification.getNotification()
-                .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
-        if (showingSpinner) {
-            smartReplyContainer.setVisibility(View.GONE);
-            return null;
-        }
-        // If we are keeping the notification around while sending we don't want to add the buttons.
-        boolean hideSmartReplies = entry.notification.getNotification()
-                .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
-        if (hideSmartReplies) {
-            smartReplyContainer.setVisibility(View.GONE);
-            return null;
-        }
+
         SmartReplyView smartReplyView = null;
-        if (smartReplyContainer.getChildCount() == 0) {
-            smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer);
+        if (smartReplyContainer.getChildCount() == 1
+                && smartReplyContainer.getChildAt(0) instanceof SmartReplyView) {
+            // If we already have a SmartReplyView - replace it with the newly inflated one. The
+            // newly inflated one is connected to the new inflated smart reply/action buttons.
+            smartReplyContainer.removeAllViews();
+        }
+        if (smartReplyContainer.getChildCount() == 0
+                && inflatedSmartReplyView != null
+                && inflatedSmartReplyView.getSmartReplyView() != null) {
+            smartReplyView = inflatedSmartReplyView.getSmartReplyView();
             smartReplyContainer.addView(smartReplyView);
-        } else if (smartReplyContainer.getChildCount() == 1) {
-            View child = smartReplyContainer.getChildAt(0);
-            if (child instanceof SmartReplyView) {
-                smartReplyView = (SmartReplyView) child;
-            }
         }
         if (smartReplyView != null) {
             smartReplyView.resetSmartSuggestions(smartReplyContainer);
-            if (smartRepliesAndActions.smartReplies != null) {
-                smartReplyView.addRepliesFromRemoteInput(
-                        smartRepliesAndActions.smartReplies, mSmartReplyController, entry);
-            }
-            if (smartRepliesAndActions.smartActions != null) {
-                smartReplyView.addSmartActions(
-                        smartRepliesAndActions.smartActions, mSmartReplyController, entry,
-                        mContainingNotification.getHeadsUpManager());
-            }
+            smartReplyView.addPreInflatedButtons(
+                    inflatedSmartReplyView.getSmartSuggestionButtons());
             smartReplyContainer.setVisibility(View.VISIBLE);
         }
         return smartReplyView;
     }
 
+    /**
+     * Set pre-inflated views necessary to display smart replies and actions in the expanded
+     * notification state.
+     *
+     * @param inflatedSmartReplies the pre-inflated state to add to this view. If null the existing
+     * {@link SmartReplyView} related to the expanded notification state is cleared.
+     */
+    public void setExpandedInflatedSmartReplies(
+            @Nullable InflatedSmartReplies inflatedSmartReplies) {
+        mExpandedInflatedSmartReplies = inflatedSmartReplies;
+        if (inflatedSmartReplies == null) {
+            mExpandedSmartReplyView = null;
+        }
+    }
+
+    /**
+     * Set pre-inflated views necessary to display smart replies and actions in the heads-up
+     * notification state.
+     *
+     * @param inflatedSmartReplies the pre-inflated state to add to this view. If null the existing
+     * {@link SmartReplyView} related to the heads-up notification state is cleared.
+     */
+    public void setHeadsUpInflatedSmartReplies(
+            @Nullable InflatedSmartReplies inflatedSmartReplies) {
+        mHeadsUpInflatedSmartReplies = inflatedSmartReplies;
+        if (inflatedSmartReplies == null) {
+            mHeadsUpSmartReplyView = null;
+        }
+    }
+
     public void closeRemoteInput() {
         if (mHeadsUpRemoteInput != null) {
             mHeadsUpRemoteInput.close();
@@ -2005,22 +1957,4 @@
         }
         pw.println();
     }
-
-    @VisibleForTesting
-    static class SmartRepliesAndActions {
-        @Nullable
-        public final SmartReplyView.SmartReplies smartReplies;
-        @Nullable
-        public final SmartReplyView.SmartActions smartActions;
-        public final boolean hasFreeformRemoteInput;
-
-        SmartRepliesAndActions(
-                @Nullable SmartReplyView.SmartReplies smartReplies,
-                @Nullable SmartReplyView.SmartActions smartActions,
-                boolean hasFreeformRemoteInput) {
-            this.smartReplies = smartReplies;
-            this.smartActions = smartActions;
-            this.hasFreeformRemoteInput = hasFreeformRemoteInput;
-        }
-    }
 }
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/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index e1a77b0..ce69a48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -246,7 +246,7 @@
     private boolean isExpanded(State state) {
         return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
                 || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
-                || state.headsUpShowing || state.bubblesShowing
+                || state.headsUpShowing || state.bubblesShowing || state.assistShowing
                 || state.scrimsVisibility != ScrimController.VISIBILITY_FULLY_TRANSPARENT);
     }
 
@@ -490,6 +490,21 @@
     }
 
     /**
+     * Sets whether assist UI is showing on the screen.
+     */
+    public void setAssistShowing(boolean assistShowing) {
+        mCurrentState.assistShowing = assistShowing;
+        apply(mCurrentState);
+    }
+
+    /**
+     * The assist UI showing state for the status bar.
+     */
+    public boolean getAssistShowing() {
+        return mCurrentState.assistShowing;
+    }
+
+    /**
      * Sets if there is a bubble being expanded on the screen.
      */
     public void setBubbleExpanded(boolean bubbleExpanded) {
@@ -558,6 +573,7 @@
         boolean notTouchable;
         boolean bubblesShowing;
         boolean bubbleExpanded;
+        boolean assistShowing;
 
         /**
          * The {@link StatusBar} state from the status bar.
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/InflatedSmartReplies.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
new file mode 100644
index 0000000..d8ea1f6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
@@ -0,0 +1,225 @@
+/*
+ * 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.systemui.statusbar.policy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+import android.util.Pair;
+import android.widget.Button;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Holder for inflated smart replies and actions. These objects should be inflated on a background
+ * thread, to later be accessed and modified on the (performance critical) UI thread.
+ */
+public class InflatedSmartReplies {
+    private static final String TAG = "InflatedSmartReplies";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    @Nullable private final SmartReplyView mSmartReplyView;
+    @Nullable private final List<Button> mSmartSuggestionButtons;
+    @NonNull private final SmartRepliesAndActions mSmartRepliesAndActions;
+
+    private InflatedSmartReplies(
+            @Nullable SmartReplyView smartReplyView,
+            @Nullable List<Button> smartSuggestionButtons,
+            @NonNull SmartRepliesAndActions smartRepliesAndActions) {
+        mSmartReplyView = smartReplyView;
+        mSmartSuggestionButtons = smartSuggestionButtons;
+        mSmartRepliesAndActions = smartRepliesAndActions;
+    }
+
+    @Nullable public SmartReplyView getSmartReplyView() {
+        return mSmartReplyView;
+    }
+
+    @Nullable public List<Button> getSmartSuggestionButtons() {
+        return mSmartSuggestionButtons;
+    }
+
+    @NonNull public SmartRepliesAndActions getSmartRepliesAndActions() {
+        return mSmartRepliesAndActions;
+    }
+
+    /**
+     * Inflate a SmartReplyView and its smart suggestions.
+     */
+    public static InflatedSmartReplies inflate(
+            Context context,
+            NotificationEntry entry,
+            SmartReplyConstants smartReplyConstants,
+            SmartReplyController smartReplyController,
+            HeadsUpManager headsUpManager) {
+        SmartRepliesAndActions smartRepliesAndActions =
+                chooseSmartRepliesAndActions(smartReplyConstants, entry);
+        if (!shouldShowSmartReplyView(entry, smartRepliesAndActions)) {
+            return new InflatedSmartReplies(null /* smartReplyView */,
+                    null /* smartSuggestionButtons */, smartRepliesAndActions);
+        }
+
+        SmartReplyView smartReplyView = SmartReplyView.inflate(context);
+
+        List<Button> suggestionButtons = new ArrayList<>();
+        if (smartRepliesAndActions.smartReplies != null) {
+            suggestionButtons.addAll(smartReplyView.inflateRepliesFromRemoteInput(
+                    smartRepliesAndActions.smartReplies, smartReplyController, entry));
+        }
+        if (smartRepliesAndActions.smartActions != null) {
+            suggestionButtons.addAll(
+                    smartReplyView.inflateSmartActions(smartRepliesAndActions.smartActions,
+                            smartReplyController, entry, headsUpManager));
+        }
+
+        return new InflatedSmartReplies(smartReplyView, suggestionButtons,
+                smartRepliesAndActions);
+    }
+
+    /**
+     * Returns whether we should show the smart reply view and its smart suggestions.
+     */
+    public static boolean shouldShowSmartReplyView(
+            NotificationEntry entry,
+            SmartRepliesAndActions smartRepliesAndActions) {
+        if (smartRepliesAndActions.smartReplies == null
+                && smartRepliesAndActions.smartActions == null) {
+            // There are no smart replies and no smart actions.
+            return false;
+        }
+        // If we are showing the spinner we don't want to add the buttons.
+        boolean showingSpinner = entry.notification.getNotification()
+                .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
+        if (showingSpinner) {
+            return false;
+        }
+        // If we are keeping the notification around while sending we don't want to add the buttons.
+        boolean hideSmartReplies = entry.notification.getNotification()
+                .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
+        if (hideSmartReplies) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Chose what smart replies and smart actions to display. App generated suggestions take
+     * precedence. So if the app provides any smart replies, we don't show any
+     * replies or actions generated by the NotificationAssistantService (NAS), and if the app
+     * provides any smart actions we also don't show any NAS-generated replies or actions.
+     */
+    @NonNull
+    public static SmartRepliesAndActions chooseSmartRepliesAndActions(
+            SmartReplyConstants smartReplyConstants,
+            final NotificationEntry entry) {
+        Notification notification = entry.notification.getNotification();
+        Pair<RemoteInput, Notification.Action> remoteInputActionPair =
+                notification.findRemoteInputActionPair(false /* freeform */);
+        Pair<RemoteInput, Notification.Action> freeformRemoteInputActionPair =
+                notification.findRemoteInputActionPair(true /* freeform */);
+
+        if (!smartReplyConstants.isEnabled()) {
+            if (DEBUG) {
+                Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for "
+                        + entry.notification.getKey());
+            }
+            return new SmartRepliesAndActions(null, null);
+        }
+        // Only use smart replies from the app if they target P or above. We have this check because
+        // the smart reply API has been used for other things (Wearables) in the past. The API to
+        // add smart actions is new in Q so it doesn't require a target-sdk check.
+        boolean enableAppGeneratedSmartReplies = (!smartReplyConstants.requiresTargetingP()
+                || entry.targetSdk >= Build.VERSION_CODES.P);
+
+        boolean appGeneratedSmartRepliesExist =
+                enableAppGeneratedSmartReplies
+                        && remoteInputActionPair != null
+                        && !ArrayUtils.isEmpty(remoteInputActionPair.first.getChoices())
+                        && remoteInputActionPair.second.actionIntent != null;
+
+        List<Notification.Action> appGeneratedSmartActions = notification.getContextualActions();
+        boolean appGeneratedSmartActionsExist = !appGeneratedSmartActions.isEmpty();
+
+        SmartReplyView.SmartReplies smartReplies = null;
+        SmartReplyView.SmartActions smartActions = null;
+        if (appGeneratedSmartRepliesExist) {
+            smartReplies = new SmartReplyView.SmartReplies(
+                    remoteInputActionPair.first.getChoices(),
+                    remoteInputActionPair.first,
+                    remoteInputActionPair.second.actionIntent,
+                    false /* fromAssistant */);
+        }
+        if (appGeneratedSmartActionsExist) {
+            smartActions = new SmartReplyView.SmartActions(appGeneratedSmartActions,
+                    false /* fromAssistant */);
+        }
+        // Apps didn't provide any smart replies / actions, use those from NAS (if any).
+        if (!appGeneratedSmartRepliesExist && !appGeneratedSmartActionsExist) {
+            boolean useGeneratedReplies = !ArrayUtils.isEmpty(entry.systemGeneratedSmartReplies)
+                    && freeformRemoteInputActionPair != null
+                    && freeformRemoteInputActionPair.second.getAllowGeneratedReplies()
+                    && freeformRemoteInputActionPair.second.actionIntent != null;
+            if (useGeneratedReplies) {
+                smartReplies = new SmartReplyView.SmartReplies(
+                        entry.systemGeneratedSmartReplies,
+                        freeformRemoteInputActionPair.first,
+                        freeformRemoteInputActionPair.second.actionIntent,
+                        true /* fromAssistant */);
+            }
+            boolean useSmartActions = !ArrayUtils.isEmpty(entry.systemGeneratedSmartActions)
+                    && notification.getAllowSystemGeneratedContextualActions();
+            if (useSmartActions) {
+                smartActions = new SmartReplyView.SmartActions(
+                        entry.systemGeneratedSmartActions, true /* fromAssistant */);
+            }
+        }
+        return new SmartRepliesAndActions(smartReplies, smartActions);
+    }
+
+    /**
+     * Returns whether the {@link Notification} represented by entry has a free-form remote input.
+     * Such an input can be used e.g. to implement smart reply buttons - by passing the replies
+     * through the remote input.
+     */
+    public static boolean hasFreeformRemoteInput(NotificationEntry entry) {
+        Notification notification = entry.notification.getNotification();
+        return null != notification.findRemoteInputActionPair(true /* freeform */);
+    }
+
+    /**
+     * A storage for smart replies and smart action.
+     */
+    public static class SmartRepliesAndActions {
+        @Nullable public final SmartReplyView.SmartReplies smartReplies;
+        @Nullable public final SmartReplyView.SmartActions smartActions;
+
+        SmartRepliesAndActions(
+                @Nullable SmartReplyView.SmartReplies smartReplies,
+                @Nullable SmartReplyView.SmartActions smartActions) {
+            this.smartReplies = smartReplies;
+            this.smartActions = smartActions;
+        }
+    }
+}
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..72f4fc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -21,13 +21,14 @@
 import android.app.RemoteInput;
 import android.content.Context;
 import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.net.Uri;
 import android.os.Handler;
-import android.provider.Settings;
+import android.provider.DeviceConfig;
+import android.text.TextUtils;
 import android.util.KeyValueListParser;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.systemui.R;
 
 import javax.inject.Inject;
@@ -35,20 +36,10 @@
 import javax.inject.Singleton;
 
 @Singleton
-public final class SmartReplyConstants extends ContentObserver {
+public final class SmartReplyConstants {
 
     private static final String TAG = "SmartReplyConstants";
 
-    private static final String KEY_ENABLED = "enabled";
-    private static final String KEY_REQUIRES_TARGETING_P = "requires_targeting_p";
-    private static final String KEY_MAX_SQUEEZE_REMEASURE_ATTEMPTS =
-            "max_squeeze_remeasure_attempts";
-    private static final String KEY_EDIT_CHOICES_BEFORE_SENDING =
-            "edit_choices_before_sending";
-    private static final String KEY_SHOW_IN_HEADS_UP = "show_in_heads_up";
-    private static final String KEY_MIN_NUM_REPLIES = "min_num_system_generated_replies";
-    private static final String KEY_MAX_NUM_ACTIONS = "max_num_actions";
-
     private final boolean mDefaultEnabled;
     private final boolean mDefaultRequiresP;
     private final int mDefaultMaxSqueezeRemeasureAttempts;
@@ -57,21 +48,25 @@
     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 Handler mHandler;
     private final Context mContext;
     private final KeyValueListParser mParser = new KeyValueListParser(',');
 
     @Inject
     public SmartReplyConstants(@Named(MAIN_HANDLER_NAME) Handler handler, Context context) {
-        super(handler);
-
+        mHandler = handler;
         mContext = context;
         final Resources resources = mContext.getResources();
         mDefaultEnabled = resources.getBoolean(
@@ -89,35 +84,86 @@
         mDefaultMaxNumActions = resources.getInteger(
                 R.integer.config_smart_replies_in_notifications_max_num_actions);
 
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS),
-                false, this);
+        registerDeviceConfigListener();
         updateConstants();
     }
 
-    @Override
-    public void onChange(boolean selfChange, Uri uri) {
+    private void registerDeviceConfigListener() {
+        DeviceConfig.addOnPropertyChangedListener(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                this::postToHandler,
+                this::onDeviceConfigPropertyChanged);
+    }
+
+    private void postToHandler(Runnable r) {
+        this.mHandler.post(r);
+    }
+
+    @VisibleForTesting
+    void onDeviceConfigPropertyChanged(String namespace, String name, String value) {
+        if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(namespace)) {
+            Log.e(TAG, "Received update from DeviceConfig for unrelated namespace: "
+                    + namespace + " " + name + "=" + value);
+            return;
+        }
+
         updateConstants();
     }
 
     private void updateConstants() {
         synchronized (SmartReplyConstants.this) {
-            try {
-                mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
-                        Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS));
-            } catch (IllegalArgumentException e) {
-                Log.e(TAG, "Bad smart reply constants", e);
-            }
-            mEnabled = mParser.getBoolean(KEY_ENABLED, mDefaultEnabled);
-            mRequiresTargetingP = mParser.getBoolean(KEY_REQUIRES_TARGETING_P, mDefaultRequiresP);
-            mMaxSqueezeRemeasureAttempts = mParser.getInt(
-                    KEY_MAX_SQUEEZE_REMEASURE_ATTEMPTS, mDefaultMaxSqueezeRemeasureAttempts);
-            mEditChoicesBeforeSending = mParser.getBoolean(
-                    KEY_EDIT_CHOICES_BEFORE_SENDING, mDefaultEditChoicesBeforeSending);
-            mShowInHeadsUp = mParser.getBoolean(KEY_SHOW_IN_HEADS_UP, mDefaultShowInHeadsUp);
-            mMinNumSystemGeneratedReplies =
-                    mParser.getInt(KEY_MIN_NUM_REPLIES, mDefaultMinNumSystemGeneratedReplies);
-            mMaxNumActions = mParser.getInt(KEY_MAX_NUM_ACTIONS, mDefaultMaxNumActions);
+            mEnabled = readDeviceConfigBooleanOrDefaultIfEmpty(
+                    SystemUiDeviceConfigFlags.SSIN_ENABLED,
+                    mDefaultEnabled);
+            mRequiresTargetingP = readDeviceConfigBooleanOrDefaultIfEmpty(
+                    SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P,
+                    mDefaultRequiresP);
+            mMaxSqueezeRemeasureAttempts = readDeviceConfigIntegerOrDefaultIfEmpty(
+                    SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS,
+                    mDefaultMaxSqueezeRemeasureAttempts);
+            mEditChoicesBeforeSending = readDeviceConfigBooleanOrDefaultIfEmpty(
+                    SystemUiDeviceConfigFlags.SSIN_EDIT_CHOICES_BEFORE_SENDING,
+                    mDefaultEditChoicesBeforeSending);
+            mShowInHeadsUp = readDeviceConfigBooleanOrDefaultIfEmpty(
+                    SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP,
+                    mDefaultShowInHeadsUp);
+            mMinNumSystemGeneratedReplies = readDeviceConfigIntegerOrDefaultIfEmpty(
+                    SystemUiDeviceConfigFlags.SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES,
+                    mDefaultMinNumSystemGeneratedReplies);
+            mMaxNumActions = readDeviceConfigIntegerOrDefaultIfEmpty(
+                    SystemUiDeviceConfigFlags.SSIN_MAX_NUM_ACTIONS,
+                    mDefaultMaxNumActions);
+        }
+    }
+
+    private static boolean readDeviceConfigBooleanOrDefaultIfEmpty(String propertyName,
+            boolean defaultValue) {
+        String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI, propertyName);
+        if (TextUtils.isEmpty(value)) {
+            return defaultValue;
+        }
+        if ("true".equals(value)) {
+            return true;
+        }
+        if ("false".equals(value)) {
+            return false;
+        }
+        // For invalid configs we return the default value.
+        return defaultValue;
+    }
+
+    private static int readDeviceConfigIntegerOrDefaultIfEmpty(String propertyName,
+            int defaultValue) {
+        String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI, propertyName);
+        if (TextUtils.isEmpty(value)) {
+            return defaultValue;
+        }
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "Tried to read an integer flag, property name="
+                    + propertyName + ", value=" + value);
+            return defaultValue;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 45d215e..ed5487f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -196,66 +196,81 @@
     }
 
     /**
+     * Add buttons to the {@link SmartReplyView} - these buttons must have been preinflated using
+     * one of the methods in this class.
+     */
+    public void addPreInflatedButtons(List<Button> smartSuggestionButtons) {
+        for (Button button : smartSuggestionButtons) {
+            addView(button);
+        }
+        reallocateCandidateButtonQueueForSqueezing();
+    }
+
+    /**
      * Add smart replies to this view, using the provided {@link RemoteInput} and
      * {@link PendingIntent} to respond when the user taps a smart reply. Only the replies that fit
      * into the notification are shown.
      */
-    public void addRepliesFromRemoteInput(
-            SmartReplies smartReplies,
+    public List<Button> inflateRepliesFromRemoteInput(
+            @NonNull SmartReplies smartReplies,
             SmartReplyController smartReplyController, NotificationEntry entry) {
+        List<Button> buttons = new ArrayList<>();
+
         if (smartReplies.remoteInput != null && smartReplies.pendingIntent != null) {
             if (smartReplies.choices != null) {
                 for (int i = 0; i < smartReplies.choices.length; ++i) {
-                    Button replyButton = inflateReplyButton(
-                            getContext(), this, i, smartReplies, smartReplyController, entry);
-                    addView(replyButton);
+                    buttons.add(inflateReplyButton(
+                            this, getContext(), i, smartReplies, smartReplyController, entry));
                 }
                 this.mSmartRepliesGeneratedByAssistant = smartReplies.fromAssistant;
             }
         }
-        reallocateCandidateButtonQueueForSqueezing();
+        return buttons;
     }
 
     /**
      * Add smart actions to be shown next to smart replies. Only the actions that fit into the
      * notification are shown.
      */
-    public void addSmartActions(SmartActions smartActions,
+    public List<Button> inflateSmartActions(@NonNull SmartActions smartActions,
             SmartReplyController smartReplyController, NotificationEntry entry,
             HeadsUpManager headsUpManager) {
+        List<Button> buttons = new ArrayList<>();
         int numSmartActions = smartActions.actions.size();
         for (int n = 0; n < numSmartActions; n++) {
             Notification.Action action = smartActions.actions.get(n);
             if (action.actionIntent != null) {
-                Button actionButton = inflateActionButton(
-                        getContext(), this, n, smartActions, smartReplyController, entry,
-                        headsUpManager);
-                addView(actionButton);
+                buttons.add(inflateActionButton(
+                        this, getContext(), n, smartActions, smartReplyController, entry,
+                        headsUpManager));
             }
         }
-        reallocateCandidateButtonQueueForSqueezing();
+        return buttons;
     }
 
-    public static SmartReplyView inflate(Context context, ViewGroup root) {
-        return (SmartReplyView)
-                LayoutInflater.from(context).inflate(R.layout.smart_reply_view, root, false);
+    /**
+     * Inflate an instance of this class.
+     */
+    public static SmartReplyView inflate(Context context) {
+        return (SmartReplyView) LayoutInflater.from(context).inflate(
+                R.layout.smart_reply_view, null /* root */);
     }
 
     @VisibleForTesting
-    Button inflateReplyButton(Context context, ViewGroup root, int replyIndex,
-            SmartReplies smartReplies, SmartReplyController smartReplyController,
+    static Button inflateReplyButton(SmartReplyView smartReplyView, Context context,
+            int replyIndex, SmartReplies smartReplies, SmartReplyController smartReplyController,
             NotificationEntry entry) {
         Button b = (Button) LayoutInflater.from(context).inflate(
-                R.layout.smart_reply_button, root, false);
+                R.layout.smart_reply_button, smartReplyView, false);
         CharSequence choice = smartReplies.choices[replyIndex];
         b.setText(choice);
 
         OnDismissAction action = () -> {
-            if (mConstants.getEffectiveEditChoicesBeforeSending(
+            if (smartReplyView.mConstants.getEffectiveEditChoicesBeforeSending(
                     smartReplies.remoteInput.getEditChoicesBeforeSending())) {
                 EditedSuggestionInfo editedSuggestionInfo =
                         new EditedSuggestionInfo(choice, replyIndex);
-                mRemoteInputManager.activateRemoteInput(b,
+                smartReplyView.mRemoteInputManager.activateRemoteInput(b,
                         new RemoteInput[] { smartReplies.remoteInput }, smartReplies.remoteInput,
                         smartReplies.pendingIntent, editedSuggestionInfo);
                 return false;
@@ -276,33 +291,41 @@
             } catch (PendingIntent.CanceledException e) {
                 Log.w(TAG, "Unable to send smart reply", e);
             }
-            mSmartReplyContainer.setVisibility(View.GONE);
+            // Note that as inflateReplyButton is called mSmartReplyContainer is null, but when the
+            // reply Button is added to the SmartReplyView mSmartReplyContainer will be set. So, it
+            // will not be possible for a user to trigger this on-click-listener without
+            // mSmartReplyContainer being set.
+            smartReplyView.mSmartReplyContainer.setVisibility(View.GONE);
             return false; // do not defer
         };
 
         b.setOnClickListener(view -> {
-            mKeyguardDismissUtil.executeWhenUnlocked(action);
+            smartReplyView.mKeyguardDismissUtil.executeWhenUnlocked(action);
         });
 
         b.setAccessibilityDelegate(new AccessibilityDelegate() {
             public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
                 super.onInitializeAccessibilityNodeInfo(host, info);
-                String label = getResources().getString(R.string.accessibility_send_smart_reply);
+                String label = smartReplyView.getResources().getString(
+                        R.string.accessibility_send_smart_reply);
                 info.addAction(new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, label));
             }
         });
 
-        setColors(b, mCurrentBackgroundColor, mDefaultStrokeColor, mDefaultTextColor, mRippleColor);
+        SmartReplyView.setButtonColors(b, smartReplyView.mCurrentBackgroundColor,
+                smartReplyView.mDefaultStrokeColor, smartReplyView.mDefaultTextColor,
+                smartReplyView.mRippleColor, smartReplyView.mStrokeWidth);
         return b;
     }
 
     @VisibleForTesting
-    Button inflateActionButton(Context context, ViewGroup root, int actionIndex,
-            SmartActions smartActions, SmartReplyController smartReplyController,
-            NotificationEntry entry, HeadsUpManager headsUpManager) {
+    static Button inflateActionButton(SmartReplyView smartReplyView, Context context,
+            int actionIndex, SmartActions smartActions,
+            SmartReplyController smartReplyController, NotificationEntry entry,
+            HeadsUpManager headsUpManager) {
         Notification.Action action = smartActions.actions.get(actionIndex);
         Button button = (Button) LayoutInflater.from(context).inflate(
-                R.layout.smart_action_button, root, false);
+                R.layout.smart_action_button, smartReplyView, false);
         button.setText(action.title);
 
         Drawable iconDrawable = action.getIcon().loadDrawable(context);
@@ -313,7 +336,7 @@
         button.setCompoundDrawables(iconDrawable, null, null, null);
 
         button.setOnClickListener(view ->
-                getActivityStarter().startPendingIntentDismissingKeyguard(
+                smartReplyView.getActivityStarter().startPendingIntentDismissingKeyguard(
                         action.actionIntent,
                         () -> {
                             smartReplyController.smartActionClicked(
@@ -803,12 +826,13 @@
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             final Button child = (Button) getChildAt(i);
-            setColors(child, backgroundColor, strokeColor, textColor, rippleColor);
+            setButtonColors(child, backgroundColor, strokeColor, textColor, rippleColor,
+                    mStrokeWidth);
         }
     }
 
-    private void setColors(Button button, int backgroundColor, int strokeColor, int textColor,
-            int rippleColor) {
+    private static void setButtonColors(Button button, int backgroundColor, int strokeColor,
+            int textColor, int rippleColor, int strokeWidth) {
         Drawable drawable = button.getBackground();
         if (drawable instanceof RippleDrawable) {
             // Mutate in case other notifications are using this drawable.
@@ -821,7 +845,7 @@
                 if (background instanceof GradientDrawable) {
                     GradientDrawable gradientDrawable = (GradientDrawable) background;
                     gradientDrawable.setColor(backgroundColor);
-                    gradientDrawable.setStroke(mStrokeWidth, strokeColor);
+                    gradientDrawable.setStroke(strokeWidth, strokeColor);
                 }
             }
             button.setBackground(drawable);
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/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
index c80396d..d756b09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import static com.google.common.truth.Truth.assertThat;
-
 import static org.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -31,62 +29,31 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AppOpsManager;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
-import android.content.Intent;
 import android.graphics.drawable.Icon;
-import android.service.notification.StatusBarNotification;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
-import android.util.Pair;
 import android.view.NotificationHeaderView;
 import android.view.View;
 
-import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.policy.SmartReplyConstants;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class NotificationContentViewTest extends SysuiTestCase {
 
-    private static final String TEST_ACTION = "com.android.SMART_REPLY_VIEW_ACTION";
-
     NotificationContentView mView;
 
-    @Mock
-    SmartReplyConstants mSmartReplyConstants;
-    @Mock
-    StatusBarNotification mStatusBarNotification;
-    @Mock
-    Notification mNotification;
-    NotificationEntry mEntry;
-    @Mock
-    RemoteInput mRemoteInput;
-    @Mock
-    RemoteInput mFreeFormRemoteInput;
-
     private Icon mActionIcon;
 
-
     @Before
     @UiThreadTest
     public void setup() {
-        MockitoAnnotations.initMocks(this);
-
         mView = new NotificationContentView(mContext, null);
         ExpandableNotificationRow row = new ExpandableNotificationRow(mContext, null);
         ExpandableNotificationRow mockRow = spy(row);
@@ -103,13 +70,6 @@
 
         mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
         mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
-
-        // Smart replies and actions
-        when(mNotification.getAllowSystemGeneratedContextualActions()).thenReturn(true);
-        when(mStatusBarNotification.getNotification()).thenReturn(mNotification);
-        mEntry = new NotificationEntry(mStatusBarNotification);
-        when(mSmartReplyConstants.isEnabled()).thenReturn(true);
-        mActionIcon = Icon.createWithResource(mContext, R.drawable.ic_person);
     }
 
     private View createViewWithHeight(int height) {
@@ -158,204 +118,4 @@
         verify(mockAmbient, never()).showAppOpsIcons(ops);
         verify(mockHeadsUp, times(1)).showAppOpsIcons(any());
     }
-
-    private void setupAppGeneratedReplies(CharSequence[] smartReplies) {
-        setupAppGeneratedReplies(smartReplies, true /* allowSystemGeneratedReplies */);
-    }
-
-    private void setupAppGeneratedReplies(
-            CharSequence[] smartReplies, boolean allowSystemGeneratedReplies) {
-        PendingIntent pendingIntent =
-                PendingIntent.getBroadcast(mContext, 0, new Intent(TEST_ACTION), 0);
-        Notification.Action action =
-                new Notification.Action.Builder(null, "Test Action", pendingIntent).build();
-        when(mRemoteInput.getChoices()).thenReturn(smartReplies);
-        Pair<RemoteInput, Notification.Action> remoteInputActionPair =
-                Pair.create(mRemoteInput, action);
-        when(mNotification.findRemoteInputActionPair(false)).thenReturn(remoteInputActionPair);
-
-        Notification.Action freeFormRemoteInputAction =
-                createActionBuilder("Freeform Test Action")
-                .setAllowGeneratedReplies(allowSystemGeneratedReplies)
-                .build();
-        Pair<RemoteInput, Notification.Action> freeFormRemoteInputActionPair =
-                Pair.create(mFreeFormRemoteInput, freeFormRemoteInputAction);
-        when(mNotification.findRemoteInputActionPair(true)).thenReturn(
-                freeFormRemoteInputActionPair);
-
-        when(mSmartReplyConstants.requiresTargetingP()).thenReturn(false);
-    }
-
-    private void setupAppGeneratedSuggestions(
-            CharSequence[] smartReplies, List<Notification.Action> smartActions) {
-        setupAppGeneratedReplies(smartReplies);
-        when(mNotification.getContextualActions()).thenReturn(smartActions);
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_smartRepliesOff_noAppGeneratedSmartSuggestions() {
-        CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"};
-        List<Notification.Action> smartActions =
-                createActions(new String[] {"Test Action 1", "Test Action 2"});
-        setupAppGeneratedSuggestions(smartReplies, smartActions);
-        when(mSmartReplyConstants.isEnabled()).thenReturn(false);
-
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartReplies).isNull();
-        assertThat(repliesAndActions.smartActions).isNull();
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_smartRepliesOff_noSystemGeneratedSmartSuggestions() {
-        mEntry.systemGeneratedSmartReplies =
-                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
-        mEntry.systemGeneratedSmartActions =
-                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
-        when(mSmartReplyConstants.isEnabled()).thenReturn(false);
-
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartReplies).isNull();
-        assertThat(repliesAndActions.smartActions).isNull();
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_appGeneratedSmartReplies() {
-        CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"};
-        setupAppGeneratedReplies(smartReplies);
-
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(smartReplies);
-        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
-        assertThat(repliesAndActions.smartActions).isNull();
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_appGeneratedSmartRepliesAndActions() {
-        CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"};
-        List<Notification.Action> smartActions =
-                createActions(new String[] {"Test Action 1", "Test Action 2"});
-        setupAppGeneratedSuggestions(smartReplies, smartActions);
-
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(smartReplies);
-        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
-        assertThat(repliesAndActions.smartActions.actions).isEqualTo(smartActions);
-        assertThat(repliesAndActions.smartActions.fromAssistant).isFalse();
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_sysGeneratedSmartReplies() {
-        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
-        // replies.
-        setupAppGeneratedReplies(null /* smartReplies */);
-
-        mEntry.systemGeneratedSmartReplies =
-                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(
-                mEntry.systemGeneratedSmartReplies);
-        assertThat(repliesAndActions.smartReplies.fromAssistant).isTrue();
-        assertThat(repliesAndActions.smartActions).isNull();
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_noSysGeneratedSmartRepliesIfNotAllowed() {
-        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
-        // replies.
-        setupAppGeneratedReplies(null /* smartReplies */, false /* allowSystemGeneratedReplies */);
-
-        mEntry.systemGeneratedSmartReplies =
-                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartReplies).isNull();
-        assertThat(repliesAndActions.smartActions).isNull();
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_sysGeneratedSmartActions() {
-        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
-        // actions.
-        setupAppGeneratedReplies(null /* smartReplies */);
-
-        mEntry.systemGeneratedSmartActions =
-                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartReplies).isNull();
-        assertThat(repliesAndActions.smartActions.actions)
-                .isEqualTo(mEntry.systemGeneratedSmartActions);
-        assertThat(repliesAndActions.smartActions.fromAssistant).isTrue();
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_appGenPreferredOverSysGen() {
-        CharSequence[] appGenSmartReplies = new String[] {"Reply1", "Reply2"};
-        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
-        // replies.
-        List<Notification.Action> appGenSmartActions =
-                createActions(new String[] {"Test Action 1", "Test Action 2"});
-        setupAppGeneratedSuggestions(appGenSmartReplies, appGenSmartActions);
-
-        mEntry.systemGeneratedSmartReplies =
-                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
-        mEntry.systemGeneratedSmartActions =
-                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
-
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(appGenSmartReplies);
-        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
-        assertThat(repliesAndActions.smartActions.actions).isEqualTo(appGenSmartActions);
-        assertThat(repliesAndActions.smartActions.fromAssistant).isFalse();
-    }
-
-    @Test
-    public void chooseSmartRepliesAndActions_disallowSysGenSmartActions() {
-        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
-        // actions.
-        setupAppGeneratedReplies(null /* smartReplies */, false /* allowSystemGeneratedReplies */);
-        when(mNotification.getAllowSystemGeneratedContextualActions()).thenReturn(false);
-        mEntry.systemGeneratedSmartReplies =
-                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
-        mEntry.systemGeneratedSmartActions =
-                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
-
-        NotificationContentView.SmartRepliesAndActions repliesAndActions =
-                NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
-
-        assertThat(repliesAndActions.smartActions).isNull();
-        assertThat(repliesAndActions.smartReplies).isNull();
-    }
-
-    private Notification.Action.Builder createActionBuilder(String actionTitle) {
-        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
-                new Intent(TEST_ACTION), 0);
-        return new Notification.Action.Builder(mActionIcon, actionTitle, pendingIntent);
-    }
-
-    private Notification.Action createAction(String actionTitle) {
-        return createActionBuilder(actionTitle).build();
-    }
-
-    private List<Notification.Action> createActions(String[] actionTitles) {
-        List<Notification.Action> actions = new ArrayList<>();
-        for (String title : actionTitles) {
-            actions.add(createAction(title));
-        }
-        return actions;
-    }
 }
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/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
new file mode 100644
index 0000000..3382a90
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
@@ -0,0 +1,279 @@
+/*
+ * 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.systemui.statusbar.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.service.notification.StatusBarNotification;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Pair;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class InflatedSmartRepliesTest extends SysuiTestCase {
+
+    private static final String TEST_ACTION = "com.android.SMART_REPLY_VIEW_ACTION";
+
+    @Mock
+    SmartReplyConstants mSmartReplyConstants;
+    @Mock
+    StatusBarNotification mStatusBarNotification;
+    @Mock
+    Notification mNotification;
+    NotificationEntry mEntry;
+    @Mock
+    RemoteInput mRemoteInput;
+    @Mock
+    RemoteInput mFreeFormRemoteInput;
+
+    private Icon mActionIcon;
+
+    @Before
+    @UiThreadTest
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mNotification.getAllowSystemGeneratedContextualActions()).thenReturn(true);
+        when(mStatusBarNotification.getNotification()).thenReturn(mNotification);
+        mEntry = new NotificationEntry(mStatusBarNotification);
+        when(mSmartReplyConstants.isEnabled()).thenReturn(true);
+        mActionIcon = Icon.createWithResource(mContext, R.drawable.ic_person);
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_smartRepliesOff_noAppGeneratedSmartSuggestions() {
+        CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"};
+        List<Notification.Action> smartActions =
+                createActions(new String[] {"Test Action 1", "Test Action 2"});
+        setupAppGeneratedSuggestions(smartReplies, smartActions);
+        when(mSmartReplyConstants.isEnabled()).thenReturn(false);
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies).isNull();
+        assertThat(repliesAndActions.smartActions).isNull();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_smartRepliesOff_noSystemGeneratedSmartSuggestions() {
+        mEntry.systemGeneratedSmartReplies =
+                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+        mEntry.systemGeneratedSmartActions =
+                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
+        when(mSmartReplyConstants.isEnabled()).thenReturn(false);
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies).isNull();
+        assertThat(repliesAndActions.smartActions).isNull();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_appGeneratedSmartReplies() {
+        CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"};
+        setupAppGeneratedReplies(smartReplies);
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(smartReplies);
+        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
+        assertThat(repliesAndActions.smartActions).isNull();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_appGeneratedSmartRepliesAndActions() {
+        CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"};
+        List<Notification.Action> smartActions =
+                createActions(new String[] {"Test Action 1", "Test Action 2"});
+        setupAppGeneratedSuggestions(smartReplies, smartActions);
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(smartReplies);
+        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
+        assertThat(repliesAndActions.smartActions.actions).isEqualTo(smartActions);
+        assertThat(repliesAndActions.smartActions.fromAssistant).isFalse();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_sysGeneratedSmartReplies() {
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // replies.
+        setupAppGeneratedReplies(null /* smartReplies */);
+
+        mEntry.systemGeneratedSmartReplies =
+                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(
+                mEntry.systemGeneratedSmartReplies);
+        assertThat(repliesAndActions.smartReplies.fromAssistant).isTrue();
+        assertThat(repliesAndActions.smartActions).isNull();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_noSysGeneratedSmartRepliesIfNotAllowed() {
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // replies.
+        setupAppGeneratedReplies(null /* smartReplies */, false /* allowSystemGeneratedReplies */);
+
+        mEntry.systemGeneratedSmartReplies =
+                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies).isNull();
+        assertThat(repliesAndActions.smartActions).isNull();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_sysGeneratedSmartActions() {
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // actions.
+        setupAppGeneratedReplies(null /* smartReplies */);
+
+        mEntry.systemGeneratedSmartActions =
+                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies).isNull();
+        assertThat(repliesAndActions.smartActions.actions)
+                .isEqualTo(mEntry.systemGeneratedSmartActions);
+        assertThat(repliesAndActions.smartActions.fromAssistant).isTrue();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_appGenPreferredOverSysGen() {
+        CharSequence[] appGenSmartReplies = new String[] {"Reply1", "Reply2"};
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // replies.
+        List<Notification.Action> appGenSmartActions =
+                createActions(new String[] {"Test Action 1", "Test Action 2"});
+        setupAppGeneratedSuggestions(appGenSmartReplies, appGenSmartActions);
+
+        mEntry.systemGeneratedSmartReplies =
+                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+        mEntry.systemGeneratedSmartActions =
+                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(appGenSmartReplies);
+        assertThat(repliesAndActions.smartReplies.fromAssistant).isFalse();
+        assertThat(repliesAndActions.smartActions.actions).isEqualTo(appGenSmartActions);
+        assertThat(repliesAndActions.smartActions.fromAssistant).isFalse();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_disallowSysGenSmartActions() {
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // actions.
+        setupAppGeneratedReplies(null /* smartReplies */, false /* allowSystemGeneratedReplies */);
+        when(mNotification.getAllowSystemGeneratedContextualActions()).thenReturn(false);
+        mEntry.systemGeneratedSmartReplies =
+                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+        mEntry.systemGeneratedSmartActions =
+                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartActions).isNull();
+        assertThat(repliesAndActions.smartReplies).isNull();
+    }
+
+    private void setupAppGeneratedReplies(CharSequence[] smartReplies) {
+        setupAppGeneratedReplies(smartReplies, true /* allowSystemGeneratedReplies */);
+    }
+
+    private void setupAppGeneratedReplies(
+            CharSequence[] smartReplies, boolean allowSystemGeneratedReplies) {
+        PendingIntent pendingIntent =
+                PendingIntent.getBroadcast(mContext, 0, new Intent(TEST_ACTION), 0);
+        Notification.Action action =
+                new Notification.Action.Builder(null, "Test Action", pendingIntent).build();
+        when(mRemoteInput.getChoices()).thenReturn(smartReplies);
+        Pair<RemoteInput, Notification.Action> remoteInputActionPair =
+                Pair.create(mRemoteInput, action);
+        when(mNotification.findRemoteInputActionPair(false)).thenReturn(remoteInputActionPair);
+
+        Notification.Action freeFormRemoteInputAction =
+                createActionBuilder("Freeform Test Action")
+                .setAllowGeneratedReplies(allowSystemGeneratedReplies)
+                .build();
+        Pair<RemoteInput, Notification.Action> freeFormRemoteInputActionPair =
+                Pair.create(mFreeFormRemoteInput, freeFormRemoteInputAction);
+        when(mNotification.findRemoteInputActionPair(true)).thenReturn(
+                freeFormRemoteInputActionPair);
+
+        when(mSmartReplyConstants.requiresTargetingP()).thenReturn(false);
+    }
+
+    private void setupAppGeneratedSuggestions(
+            CharSequence[] smartReplies, List<Notification.Action> smartActions) {
+        setupAppGeneratedReplies(smartReplies);
+        when(mNotification.getContextualActions()).thenReturn(smartActions);
+    }
+
+    private Notification.Action.Builder createActionBuilder(String actionTitle) {
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
+                new Intent(TEST_ACTION), 0);
+        return new Notification.Action.Builder(mActionIcon, actionTitle, pendingIntent);
+    }
+
+    private Notification.Action createAction(String actionTitle) {
+        return createActionBuilder(actionTitle).build();
+    }
+
+    private List<Notification.Action> createActions(String[] actionTitles) {
+        List<Notification.Action> actions = new ArrayList<>();
+        for (String title : actionTitles) {
+            actions.add(createAction(title));
+        }
+        return actions;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
index bc0f742..cd9069a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
@@ -23,15 +23,17 @@
 import android.app.RemoteInput;
 import android.os.Handler;
 import android.os.Looper;
-import android.provider.Settings;
+import android.provider.DeviceConfig;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableResources;
 
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,7 +49,7 @@
 
     @Before
     public void setUp() {
-        overrideSetting(null); // No config.
+        resetAllDeviceConfigFlags();
         TestableResources resources = mContext.getOrCreateTestableResources();
         resources.addOverride(R.bool.config_smart_replies_in_notifications_enabled, true);
         resources.addOverride(
@@ -58,9 +60,16 @@
         resources.addOverride(
                 R.integer.config_smart_replies_in_notifications_min_num_system_generated_replies,
                 2);
+        resources.addOverride(
+                R.integer.config_smart_replies_in_notifications_max_num_actions, -1);
         mConstants = new SmartReplyConstants(Handler.createAsync(Looper.myLooper()), mContext);
     }
 
+    @After
+    public void tearDown() {
+        resetAllDeviceConfigFlags();
+    }
+
     @Test
     public void testIsEnabledWithNoConfig() {
         assertTrue(mConstants.isEnabled());
@@ -68,25 +77,25 @@
 
     @Test
     public void testIsEnabledWithInvalidConfig() {
-        overrideSetting("invalid config");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_ENABLED, "invalid config");
         triggerConstantsOnChange();
         assertTrue(mConstants.isEnabled());
     }
 
     @Test
     public void testIsEnabledWithValidConfig() {
-        overrideSetting("enabled=false,max_squeeze_remeasure_attempts=5");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_ENABLED, "false");
         triggerConstantsOnChange();
         assertFalse(mConstants.isEnabled());
     }
 
     @Test
     public void testRequiresTargetingPConfig() {
-        overrideSetting("enabled=true,requires_targeting_p=false");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P, "false");
         triggerConstantsOnChange();
         assertEquals(false, mConstants.requiresTargetingP());
 
-        overrideSetting("enabled=true");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P, "");
         triggerConstantsOnChange();
         assertEquals(true, mConstants.requiresTargetingP());
     }
@@ -99,21 +108,21 @@
 
     @Test
     public void testGetMaxSqueezeRemeasureAttemptsWithInvalidConfig() {
-        overrideSetting("invalid config");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS,
+                "invalid config");
         triggerConstantsOnChange();
         assertEquals(7, mConstants.getMaxSqueezeRemeasureAttempts());
     }
 
     @Test
     public void testGetMaxSqueezeRemeasureAttemptsWithValidConfig() {
-        overrideSetting("enabled=false,max_squeeze_remeasure_attempts=5");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS, "5");
         triggerConstantsOnChange();
         assertEquals(5, mConstants.getMaxSqueezeRemeasureAttempts());
     }
 
     @Test
     public void testGetEffectiveEditChoicesBeforeSendingWithNoConfig() {
-        overrideSetting("enabled=true");
         triggerConstantsOnChange();
         assertFalse(
                 mConstants.getEffectiveEditChoicesBeforeSending(
@@ -128,7 +137,7 @@
 
     @Test
     public void testGetEffectiveEditChoicesBeforeSendingWithEnabledConfig() {
-        overrideSetting("enabled=true,edit_choices_before_sending=true");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_EDIT_CHOICES_BEFORE_SENDING, "true");
         triggerConstantsOnChange();
         assertTrue(
                 mConstants.getEffectiveEditChoicesBeforeSending(
@@ -143,7 +152,7 @@
 
     @Test
     public void testGetEffectiveEditChoicesBeforeSendingWithDisabledConfig() {
-        overrideSetting("enabled=true,edit_choices_before_sending=false");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_EDIT_CHOICES_BEFORE_SENDING, "false");
         triggerConstantsOnChange();
         assertFalse(
                 mConstants.getEffectiveEditChoicesBeforeSending(
@@ -164,37 +173,19 @@
 
     @Test
     public void testShowInHeadsUpEnabled() {
-        overrideSetting("enabled=true,show_in_heads_up=true");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP, "true");
         triggerConstantsOnChange();
         assertTrue(mConstants.getShowInHeadsUp());
     }
 
     @Test
     public void testShowInHeadsUpDisabled() {
-        overrideSetting("enabled=true,show_in_heads_up=false");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP, "false");
         triggerConstantsOnChange();
         assertFalse(mConstants.getShowInHeadsUp());
     }
 
     @Test
-    public void testMaxNumActionsWithNoConfig() {
-        assertTrue(mConstants.isEnabled());
-        assertEquals(-1, mConstants.getMaxNumActions());
-    }
-
-    @Test
-    public void testMaxNumActionsSet() {
-        overrideSetting("enabled=true,max_num_actions=10");
-        triggerConstantsOnChange();
-        assertEquals(10, mConstants.getMaxNumActions());
-    }
-
-    private void overrideSetting(String flags) {
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS, flags);
-    }
-
-    @Test
     public void testGetMinNumSystemGeneratedRepliesWithNoConfig() {
         assertTrue(mConstants.isEnabled());
         assertEquals(2, mConstants.getMinNumSystemGeneratedReplies());
@@ -202,15 +193,51 @@
 
     @Test
     public void testGetMinNumSystemGeneratedRepliesWithValidConfig() {
-        overrideSetting("enabled=true,min_num_system_generated_replies=5");
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES, "5");
         triggerConstantsOnChange();
         assertEquals(5, mConstants.getMinNumSystemGeneratedReplies());
     }
 
+    @Test
+    public void testMaxNumActionsWithNoConfig() {
+        assertTrue(mConstants.isEnabled());
+        assertEquals(-1, mConstants.getMaxNumActions());
+    }
+
+    @Test
+    public void testMaxNumActionsSet() {
+        overrideSetting(SystemUiDeviceConfigFlags.SSIN_MAX_NUM_ACTIONS, "10");
+        triggerConstantsOnChange();
+        assertEquals(10, mConstants.getMaxNumActions());
+    }
+
+    private void overrideSetting(String propertyName, String value) {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                propertyName, value, false /* makeDefault */);
+    }
+
     private void triggerConstantsOnChange() {
-        // Since Settings.Global is mocked in TestableContext, we need to manually trigger the
-        // content observer.
-        mConstants.onChange(false,
-                Settings.Global.getUriFor(Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS));
+        mConstants.onDeviceConfigPropertyChanged(DeviceConfig.NAMESPACE_SYSTEMUI,
+                "" /* name */, "" /* value */);
+    }
+
+    private void resetAllDeviceConfigFlags() {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.SSIN_ENABLED, "", false /* makeDefault */);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P, "", false /* makeDefault */);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS, "",
+                false /* makeDefault */);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.SSIN_EDIT_CHOICES_BEFORE_SENDING, "",
+                false /* makeDefault */);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP, "", false /* makeDefault */);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES, "",
+                false /* makeDefault */);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.SSIN_MAX_NUM_ACTIONS, "", false /* makeDefault */);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 6793eca..60b0d61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -113,7 +113,7 @@
         mDependency.injectTestDependency(SmartReplyConstants.class, mConstants);
 
         mContainer = new View(mContext, null);
-        mView = SmartReplyView.inflate(mContext, null);
+        mView = SmartReplyView.inflate(mContext);
 
         // Any number of replies are fine.
         when(mConstants.getMinNumSystemGeneratedReplies()).thenReturn(0);
@@ -402,17 +402,18 @@
     }
 
     private void setSmartReplies(CharSequence[] choices) {
-        setSmartReplies(choices, false /* fromAssistant */);
+        mView.resetSmartSuggestions(mContainer);
+        List<Button> replyButtons = inflateSmartReplies(choices, false /* fromAssistant */);
+        mView.addPreInflatedButtons(replyButtons);
     }
 
-    private void setSmartReplies(CharSequence[] choices, boolean fromAssistant) {
+    private List<Button> inflateSmartReplies(CharSequence[] choices, boolean fromAssistant) {
         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
                 new Intent(TEST_ACTION), 0);
         RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(choices).build();
         SmartReplyView.SmartReplies smartReplies =
                 new SmartReplyView.SmartReplies(choices, input, pendingIntent, fromAssistant);
-        mView.resetSmartSuggestions(mContainer);
-        mView.addRepliesFromRemoteInput(smartReplies, mLogger, mEntry);
+        return mView.inflateRepliesFromRemoteInput(smartReplies, mLogger, mEntry);
     }
 
     private Notification.Action createAction(String actionTitle) {
@@ -431,11 +432,12 @@
 
     private void setSmartActions(String[] actionTitles) {
         mView.resetSmartSuggestions(mContainer);
-        mView.addSmartActions(
+        List<Button> actions = mView.inflateSmartActions(
                 new SmartReplyView.SmartActions(createActions(actionTitles), false),
                 mLogger,
                 mEntry,
                 mHeadsUpManager);
+        mView.addPreInflatedButtons(actions);
     }
 
     private void setSmartRepliesAndActions(CharSequence[] choices, String[] actionTitles) {
@@ -444,12 +446,14 @@
 
     private void setSmartRepliesAndActions(
             CharSequence[] choices, String[] actionTitles, boolean fromAssistant) {
-        setSmartReplies(choices, fromAssistant);
-        mView.addSmartActions(
+        mView.resetSmartSuggestions(mContainer);
+        List<Button> smartSuggestions = inflateSmartReplies(choices, fromAssistant);
+        smartSuggestions.addAll(mView.inflateSmartActions(
                 new SmartReplyView.SmartActions(createActions(actionTitles), fromAssistant),
                 mLogger,
                 mEntry,
-                mHeadsUpManager);
+                mHeadsUpManager));
+        mView.addPreInflatedButtons(smartSuggestions);
     }
 
     private ViewGroup buildExpectedView(CharSequence[] choices, int lineCount) {
@@ -485,8 +489,8 @@
         SmartReplyView.SmartReplies smartReplies =
                 new SmartReplyView.SmartReplies(choices, null, null, false);
         for (int i = 0; i < choices.length; ++i) {
-            Button current = mView.inflateReplyButton(mContext, mView, i, smartReplies,
-                    null, null);
+            Button current = SmartReplyView.inflateReplyButton(mView, mContext, i, smartReplies,
+                    null /* SmartReplyController */, null /* NotificationEntry */);
             current.setPadding(paddingHorizontal, current.getPaddingTop(), paddingHorizontal,
                     current.getPaddingBottom());
             if (previous != null) {
@@ -752,7 +756,7 @@
     }
 
     private Button inflateActionButton(Notification.Action action) {
-        return mView.inflateActionButton(getContext(), mView, 0,
+        return SmartReplyView.inflateActionButton(mView, getContext(), 0,
                 new SmartReplyView.SmartActions(Collections.singletonList(action), false),
                 mLogger, mEntry, mHeadsUpManager);
     }
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 8929e82..365c6b4 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -5434,7 +5434,7 @@
     FIELD_END_BATTERY_PERCENT = 1308;
 
     // ACTION: Settings > Display > Night Light
-    // SUBTYPE: com.android.server.display.ColorDisplayService.AutoMode value
+    // SUBTYPE: com.android.server.display.color.ColorDisplayService.AutoMode value
     // CATEGORY: SETTINGS
     // OS: P
     ACTION_NIGHT_DISPLAY_AUTO_MODE_CHANGED = 1309;
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 670e794..d68442f 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -524,6 +524,15 @@
 
   // Link Probe metrics
   optional LinkProbeStats link_probe_stats = 139;
+
+  // List of NetworkSelectionExperimentDecisions stats for each experiment
+  repeated NetworkSelectionExperimentDecisions network_selection_experiment_decisions_list = 140;
+
+  // Network Request API surface metrics.
+  optional WifiNetworkRequestApiLog wifi_network_request_api_log = 141;
+
+  // Network Suggestion API surface metrics.
+  optional WifiNetworkSuggestionApiLog wifi_network_suggestion_api_log = 142;
 }
 
 // Information that gets logged for every WiFi connection.
@@ -651,6 +660,39 @@
     HLF_UNWANTED = 4;
   }
 
+  // Entity that recommended connecting to this network.
+  enum ConnectionNominator {
+    // Unknown nominator
+    NOMINATOR_UNKNOWN = 0;
+
+    // User selected network manually
+    NOMINATOR_MANUAL = 1;
+
+    // Saved network
+    NOMINATOR_SAVED = 2;
+
+    // Suggestion API
+    NOMINATOR_SUGGESTION = 3;
+
+    // Passpoint
+    NOMINATOR_PASSPOINT = 4;
+
+    // Carrier suggestion
+    NOMINATOR_CARRIER = 5;
+
+    // External scorer
+    NOMINATOR_EXTERNAL_SCORED = 6;
+
+    // Netrec
+    NOMINATOR_NETREC = 7;
+
+    // User connected choice override
+    NOMINATOR_SAVED_USER_CONNECT_CHOICE = 8;
+
+    // Open Network Available Pop-up
+    NOMINATOR_OPEN_NETWORK_AVAILABLE = 9;
+  }
+
   // Start time of the connection.
   optional int64 start_time_millis = 1;// [(datapol.semantic_type) = ST_TIMESTAMP];
 
@@ -680,6 +722,12 @@
 
   // Connection is using locally generated random MAC address.
   optional bool use_randomized_mac = 10 [default = false];
+
+  // Who chose to connect.
+  optional ConnectionNominator connection_nominator = 11;
+
+  // The currently running network selector when this connection event occurred.
+  optional int32 network_selector_experiment_id = 12;
 }
 
 // Number of occurrences of a specific RSSI poll rssi value
@@ -2276,3 +2324,62 @@
   // Counts the occurrences of error codes for failed link probes.
   repeated LinkProbeFailureReasonCount failure_reason_counts = 8;
 }
+
+// Stores the decisions that were made by a experiment when compared against another experiment
+message NetworkSelectionExperimentDecisions {
+  // the id of one experiment
+  optional int32 experiment1_id = 1;
+
+  // the id of the other experiment
+  optional int32 experiment2_id = 2;
+
+  // Counts occurrences of the number of network choices there were when experiment1 makes the
+  // same network selection as experiment2.
+  // The keys are the number of network choices, and the values are the number of occurrences of
+  // this number of network choices when exp1 and exp2 make the same network selection.
+  repeated MapEntryInt32Int32 same_selection_num_choices_counter = 3;
+
+  // Counts occurrences of the number of network choices there were when experiment1 makes the
+  // same network selection as experiment2.
+  // The keys are the number of network choices, and the values are the number of occurrences of
+  // this number of network choices when exp1 and exp2 make different network selections.
+  // Note that it is possible for the network selection to be different even when there only exists
+  // a single network choice, since choosing not to connect to that network is a valid choice.
+  repeated MapEntryInt32Int32 different_selection_num_choices_counter = 4;
+}
+
+// NetworkRequest API metrics.
+message WifiNetworkRequestApiLog {
+  // Number of requests via this API surface.
+  optional int32 num_request = 1;
+
+  // Histogram of requests via this API surface to number of networks matched in scan results.
+  optional HistogramBucketInt32 network_match_size_histogram = 2;
+
+  // Number of successful network connection from this API.
+  optional int32 num_connect_success = 3;
+
+  // Number of requests via this API surface that bypassed user approval.
+  optional int32 num_user_approval_bypass = 4;
+
+  // Number of requests via this API surface that was rejected by the user.
+  optional int32 num_user_reject = 5;
+
+  // Number of unique apps using this API surface.
+  optional int32 num_apps = 6;
+}
+
+// NetworkSuggestion API metrics.
+message WifiNetworkSuggestionApiLog {
+  // Number of modifications to their suggestions by apps.
+  optional int32 num_modification = 1;
+
+  // Number of successful network connection from app suggestions.
+  optional int32 num_connect_success = 2;
+
+  // Number of network connection failures from app suggestions.
+  optional int32 num_connect_failure = 3;
+
+  // Histogram for size of the network lists provided by various apps on the device.
+  repeated HistogramBucketInt32 network_list_size_histogram = 4;
+}
diff --git a/services/art-profile b/services/art-profile
index 7892fcb..6de96e8 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -1013,7 +1013,7 @@
 HPLcom/android/server/display/AutomaticBrightnessController;->weightIntegral(J)F
 HPLcom/android/server/display/BrightnessTracker$Injector;->currentTimeMillis()J
 HPLcom/android/server/display/BrightnessTracker$Injector;->elapsedRealtimeNanos()J
-HPLcom/android/server/display/ColorDisplayService$ColorMatrixEvaluator;->evaluate(F[F[F)[F
+HPLcom/android/server/display/color/ColorDisplayService$ColorMatrixEvaluator;->evaluate(F[F[F)[F
 HPLcom/android/server/display/ColorFade;->draw(F)Z
 HPLcom/android/server/display/ColorFade;->drawFaded(FF)V
 HPLcom/android/server/display/DisplayManagerService$BinderService;->getDisplayIds()[I
@@ -3413,7 +3413,7 @@
 Lcom/android/server/devicepolicy/DevicePolicyManagerService$Lifecycle;
 Lcom/android/server/display/-$$Lambda$VirtualDisplayAdapter$PFyqe-aYIEBicSVtuy5lL_bT8B0;
 Lcom/android/server/display/AutomaticBrightnessController$Callbacks;
-Lcom/android/server/display/ColorDisplayService;
+Lcom/android/server/display/color/ColorDisplayService;
 Lcom/android/server/display/DisplayAdapter$1;
 Lcom/android/server/display/DisplayAdapter$2;
 Lcom/android/server/display/DisplayAdapter$Listener;
@@ -3433,7 +3433,7 @@
 Lcom/android/server/display/DisplayManagerService;
 Lcom/android/server/display/DisplayManagerShellCommand;
 Lcom/android/server/display/DisplayPowerController;
-Lcom/android/server/display/DisplayTransformManager;
+Lcom/android/server/display/color/DisplayTransformManager;
 Lcom/android/server/display/LocalDisplayAdapter$DisplayModeRecord;
 Lcom/android/server/display/LocalDisplayAdapter$HotplugDisplayEventReceiver;
 Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice$1;
@@ -10616,39 +10616,39 @@
 PLcom/android/server/display/BrightnessTracker;->writeAmbientBrightnessStats()V
 PLcom/android/server/display/BrightnessTracker;->writeEvents()V
 PLcom/android/server/display/BrightnessTracker;->writeEventsLocked(Ljava/io/OutputStream;)V
-PLcom/android/server/display/ColorDisplayService$2;-><init>(Lcom/android/server/display/ColorDisplayService;Lcom/android/server/display/DisplayTransformManager;)V
-PLcom/android/server/display/ColorDisplayService$2;->onAnimationUpdate(Landroid/animation/ValueAnimator;)V
-PLcom/android/server/display/ColorDisplayService$3;-><init>(Lcom/android/server/display/ColorDisplayService;Lcom/android/server/display/DisplayTransformManager;[F)V
-PLcom/android/server/display/ColorDisplayService$3;->onAnimationEnd(Landroid/animation/Animator;)V
-PLcom/android/server/display/ColorDisplayService$AutoMode;-><init>(Lcom/android/server/display/ColorDisplayService;)V
-PLcom/android/server/display/ColorDisplayService$AutoMode;-><init>(Lcom/android/server/display/ColorDisplayService;Lcom/android/server/display/ColorDisplayService$1;)V
-PLcom/android/server/display/ColorDisplayService$ColorMatrixEvaluator;-><init>()V
-PLcom/android/server/display/ColorDisplayService$ColorMatrixEvaluator;-><init>(Lcom/android/server/display/ColorDisplayService$1;)V
-PLcom/android/server/display/ColorDisplayService$ColorMatrixEvaluator;->evaluate(FLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-PLcom/android/server/display/ColorDisplayService$CustomAutoMode$1;-><init>(Lcom/android/server/display/ColorDisplayService$CustomAutoMode;Lcom/android/server/display/ColorDisplayService;)V
-PLcom/android/server/display/ColorDisplayService$CustomAutoMode;-><init>(Lcom/android/server/display/ColorDisplayService;)V
-PLcom/android/server/display/ColorDisplayService$CustomAutoMode;->onActivated(Z)V
-PLcom/android/server/display/ColorDisplayService$CustomAutoMode;->onAlarm()V
-PLcom/android/server/display/ColorDisplayService$CustomAutoMode;->onStart()V
-PLcom/android/server/display/ColorDisplayService$CustomAutoMode;->updateActivated()V
-PLcom/android/server/display/ColorDisplayService$CustomAutoMode;->updateNextAlarm(Ljava/lang/Boolean;Ljava/time/LocalDateTime;)V
-PLcom/android/server/display/ColorDisplayService;-><init>(Landroid/content/Context;)V
-PLcom/android/server/display/ColorDisplayService;->access$1000(Lcom/android/server/display/ColorDisplayService;)Ljava/lang/Boolean;
-PLcom/android/server/display/ColorDisplayService;->access$602(Lcom/android/server/display/ColorDisplayService;Landroid/animation/ValueAnimator;)Landroid/animation/ValueAnimator;
-PLcom/android/server/display/ColorDisplayService;->applyTint(Z)V
-PLcom/android/server/display/ColorDisplayService;->getDateTimeAfter(Ljava/time/LocalTime;Ljava/time/LocalDateTime;)Ljava/time/LocalDateTime;
-PLcom/android/server/display/ColorDisplayService;->getDateTimeBefore(Ljava/time/LocalTime;Ljava/time/LocalDateTime;)Ljava/time/LocalDateTime;
-PLcom/android/server/display/ColorDisplayService;->isUserSetupCompleted(Landroid/content/ContentResolver;I)Z
-PLcom/android/server/display/ColorDisplayService;->onActivated(Z)V
-PLcom/android/server/display/ColorDisplayService;->onAutoModeChanged(I)V
-PLcom/android/server/display/ColorDisplayService;->onBootPhase(I)V
-PLcom/android/server/display/ColorDisplayService;->onDisplayColorModeChanged(I)V
-PLcom/android/server/display/ColorDisplayService;->onStart()V
-PLcom/android/server/display/ColorDisplayService;->onStartUser(I)V
-PLcom/android/server/display/ColorDisplayService;->onUserChanged(I)V
-PLcom/android/server/display/ColorDisplayService;->setCoefficientMatrix(Landroid/content/Context;Z)V
-PLcom/android/server/display/ColorDisplayService;->setMatrix(I[F)V
-PLcom/android/server/display/ColorDisplayService;->setUp()V
+PLcom/android/server/display/color/ColorDisplayService$2;-><init>(Lcom/android/server/display/color/ColorDisplayService;Lcom/android/server/display/color/DisplayTransformManager;)V
+PLcom/android/server/display/color/ColorDisplayService$2;->onAnimationUpdate(Landroid/animation/ValueAnimator;)V
+PLcom/android/server/display/color/ColorDisplayService$3;-><init>(Lcom/android/server/display/color/ColorDisplayService;Lcom/android/server/display/color/DisplayTransformManager;[F)V
+PLcom/android/server/display/color/ColorDisplayService$3;->onAnimationEnd(Landroid/animation/Animator;)V
+PLcom/android/server/display/color/ColorDisplayService$AutoMode;-><init>(Lcom/android/server/display/color/ColorDisplayService;)V
+PLcom/android/server/display/color/ColorDisplayService$AutoMode;-><init>(Lcom/android/server/display/color/ColorDisplayService;Lcom/android/server/display/color/ColorDisplayService$1;)V
+PLcom/android/server/display/color/ColorDisplayService$ColorMatrixEvaluator;-><init>()V
+PLcom/android/server/display/color/ColorDisplayService$ColorMatrixEvaluator;-><init>(Lcom/android/server/display/color/ColorDisplayService$1;)V
+PLcom/android/server/display/color/ColorDisplayService$ColorMatrixEvaluator;->evaluate(FLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+PLcom/android/server/display/color/ColorDisplayService$CustomAutoMode$1;-><init>(Lcom/android/server/display/color/ColorDisplayService$CustomAutoMode;Lcom/android/server/display/color/ColorDisplayService;)V
+PLcom/android/server/display/color/ColorDisplayService$CustomAutoMode;-><init>(Lcom/android/server/display/color/ColorDisplayService;)V
+PLcom/android/server/display/color/ColorDisplayService$CustomAutoMode;->onActivated(Z)V
+PLcom/android/server/display/color/ColorDisplayService$CustomAutoMode;->onAlarm()V
+PLcom/android/server/display/color/ColorDisplayService$CustomAutoMode;->onStart()V
+PLcom/android/server/display/color/ColorDisplayService$CustomAutoMode;->updateActivated()V
+PLcom/android/server/display/color/ColorDisplayService$CustomAutoMode;->updateNextAlarm(Ljava/lang/Boolean;Ljava/time/LocalDateTime;)V
+PLcom/android/server/display/color/ColorDisplayService;-><init>(Landroid/content/Context;)V
+PLcom/android/server/display/color/ColorDisplayService;->access$1000(Lcom/android/server/display/color/ColorDisplayService;)Ljava/lang/Boolean;
+PLcom/android/server/display/color/ColorDisplayService;->access$602(Lcom/android/server/display/color/ColorDisplayService;Landroid/animation/ValueAnimator;)Landroid/animation/ValueAnimator;
+PLcom/android/server/display/color/ColorDisplayService;->applyTint(Z)V
+PLcom/android/server/display/color/ColorDisplayService;->getDateTimeAfter(Ljava/time/LocalTime;Ljava/time/LocalDateTime;)Ljava/time/LocalDateTime;
+PLcom/android/server/display/color/ColorDisplayService;->getDateTimeBefore(Ljava/time/LocalTime;Ljava/time/LocalDateTime;)Ljava/time/LocalDateTime;
+PLcom/android/server/display/color/ColorDisplayService;->isUserSetupCompleted(Landroid/content/ContentResolver;I)Z
+PLcom/android/server/display/color/ColorDisplayService;->onActivated(Z)V
+PLcom/android/server/display/color/ColorDisplayService;->onAutoModeChanged(I)V
+PLcom/android/server/display/color/ColorDisplayService;->onBootPhase(I)V
+PLcom/android/server/display/color/ColorDisplayService;->onDisplayColorModeChanged(I)V
+PLcom/android/server/display/color/ColorDisplayService;->onStart()V
+PLcom/android/server/display/color/ColorDisplayService;->onStartUser(I)V
+PLcom/android/server/display/color/ColorDisplayService;->onUserChanged(I)V
+PLcom/android/server/display/color/ColorDisplayService;->setCoefficientMatrix(Landroid/content/Context;Z)V
+PLcom/android/server/display/color/ColorDisplayService;->setMatrix(I[F)V
+PLcom/android/server/display/color/ColorDisplayService;->setUp()V
 PLcom/android/server/display/ColorFade$NaturalSurfaceLayout;-><init>(Landroid/hardware/display/DisplayManagerInternal;ILandroid/view/SurfaceControl;)V
 PLcom/android/server/display/ColorFade$NaturalSurfaceLayout;->dispose()V
 PLcom/android/server/display/ColorFade$NaturalSurfaceLayout;->onDisplayTransaction()V
@@ -10878,17 +10878,17 @@
 PLcom/android/server/display/DisplayPowerState;->setScreenBrightness(I)V
 PLcom/android/server/display/DisplayPowerState;->setScreenState(I)V
 PLcom/android/server/display/DisplayPowerState;->waitUntilClean(Ljava/lang/Runnable;)Z
-PLcom/android/server/display/DisplayTransformManager;->applyColorMatrix([F)V
-PLcom/android/server/display/DisplayTransformManager;->applySaturation(F)V
-PLcom/android/server/display/DisplayTransformManager;->computeColorMatrixLocked()[F
-PLcom/android/server/display/DisplayTransformManager;->getColorMatrix(I)[F
-PLcom/android/server/display/DisplayTransformManager;->needsLinearColorMatrix()Z
-PLcom/android/server/display/DisplayTransformManager;->needsLinearColorMatrix(I)Z
-PLcom/android/server/display/DisplayTransformManager;->setColorMatrix(I[F)V
-PLcom/android/server/display/DisplayTransformManager;->setColorMode(I[F)Z
-PLcom/android/server/display/DisplayTransformManager;->setDaltonizerMode(I)V
-PLcom/android/server/display/DisplayTransformManager;->setDisplayColor(I)V
-PLcom/android/server/display/DisplayTransformManager;->updateConfiguration()V
+PLcom/android/server/display/color/DisplayTransformManager;->applyColorMatrix([F)V
+PLcom/android/server/display/color/DisplayTransformManager;->applySaturation(F)V
+PLcom/android/server/display/color/DisplayTransformManager;->computeColorMatrixLocked()[F
+PLcom/android/server/display/color/DisplayTransformManager;->getColorMatrix(I)[F
+PLcom/android/server/display/color/DisplayTransformManager;->needsLinearColorMatrix()Z
+PLcom/android/server/display/color/DisplayTransformManager;->needsLinearColorMatrix(I)Z
+PLcom/android/server/display/color/DisplayTransformManager;->setColorMatrix(I[F)V
+PLcom/android/server/display/color/DisplayTransformManager;->setColorMode(I[F)Z
+PLcom/android/server/display/color/DisplayTransformManager;->setDaltonizerMode(I)V
+PLcom/android/server/display/color/DisplayTransformManager;->setDisplayColor(I)V
+PLcom/android/server/display/color/DisplayTransformManager;->updateConfiguration()V
 PLcom/android/server/display/HysteresisLevels;-><init>([I[I[I)V
 PLcom/android/server/display/HysteresisLevels;->getBrighteningThreshold(F)F
 PLcom/android/server/display/HysteresisLevels;->getDarkeningThreshold(F)F
@@ -19436,7 +19436,7 @@
 SPLcom/android/server/display/DisplayManagerService;->sendDisplayEventLocked(II)V
 SPLcom/android/server/display/DisplayManagerService;->updateDisplayStateLocked(Lcom/android/server/display/DisplayDevice;)Ljava/lang/Runnable;
 SPLcom/android/server/display/DisplayManagerService;->updateLogicalDisplaysLocked()Z
-SPLcom/android/server/display/DisplayTransformManager;-><init>()V
+SPLcom/android/server/display/color/DisplayTransformManager;-><init>()V
 SPLcom/android/server/display/LocalDisplayAdapter$DisplayModeRecord;-><init>(Landroid/view/SurfaceControl$PhysicalDisplayInfo;)V
 SPLcom/android/server/display/LocalDisplayAdapter$DisplayModeRecord;->hasMatchingMode(Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z
 SPLcom/android/server/display/LocalDisplayAdapter$HotplugDisplayEventReceiver;-><init>(Lcom/android/server/display/LocalDisplayAdapter;Landroid/os/Looper;)V
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
index 385bc6c..a18686d 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
@@ -80,12 +80,7 @@
     @Override // from PerUserSystemService
     protected boolean updateLocked(boolean disabled) {
         final boolean enabledChanged = super.updateLocked(disabled);
-        if (enabledChanged) {
-            if (!isEnabledLocked()) {
-                // Clear the remote service for the next call
-                mRemoteService = null;
-            }
-        }
+        updateRemoteServiceLocked();
         return enabledChanged;
     }
 
@@ -133,6 +128,15 @@
     }
 
     @GuardedBy("mLock")
+    private void updateRemoteServiceLocked() {
+        if (mRemoteService != null) {
+            mRemoteService.destroy();
+            mRemoteService = null;
+        }
+    }
+
+
+    @GuardedBy("mLock")
     @Nullable
     private RemoteContentSuggestionsService getRemoteServiceLocked() {
         if (mRemoteService == null) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index c37a805..0d4fbb8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -71,6 +71,8 @@
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.InetAddresses;
+import android.net.IpPrefix;
 import android.net.LinkProperties;
 import android.net.LinkProperties.CompareResult;
 import android.net.MatchAllNetworkSpecifier;
@@ -1742,6 +1744,12 @@
                 }
             }
         }
+
+        @Override
+        public void onNat64PrefixEvent(int netId, boolean added,
+                                       String prefixString, int prefixLength) {
+            mHandler.post(() -> handleNat64PrefixEvent(netId, added, prefixString, prefixLength));
+        }
     };
 
     @VisibleForTesting
@@ -2783,6 +2791,29 @@
         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
     }
 
+    private void handleNat64PrefixEvent(int netId, boolean added, String prefixString,
+            int prefixLength) {
+        NetworkAgentInfo nai = mNetworkForNetId.get(netId);
+        if (nai == null) return;
+
+        log(String.format("NAT64 prefix %s on netId %d: %s/%d",
+                          (added ? "added" : "removed"), netId, prefixString, prefixLength));
+
+        IpPrefix prefix = null;
+        if (added) {
+            try {
+                prefix = new IpPrefix(InetAddresses.parseNumericAddress(prefixString),
+                        prefixLength);
+            } catch (IllegalArgumentException e) {
+                loge("Invalid NAT64 prefix " + prefixString + "/" + prefixLength);
+                return;
+            }
+        }
+
+        nai.clatd.setNat64Prefix(prefix);
+        handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
+    }
+
     private void updateLingerState(NetworkAgentInfo nai, long now) {
         // 1. Update the linger timer. If it's changed, reschedule or cancel the alarm.
         // 2. If the network was lingering and there are now requests, unlinger it.
@@ -2910,7 +2941,7 @@
             e.rethrowFromSystemServer();
         }
         mNetworkAgentInfos.remove(nai.messenger);
-        nai.maybeStopClat();
+        nai.clatd.update();
         synchronized (mNetworkForNetId) {
             // Remove the NetworkAgent, but don't mark the netId as
             // available until we've told netd to delete it below.
@@ -5256,11 +5287,10 @@
             LinkProperties oldLp) {
         int netId = networkAgent.network.netId;
 
-        // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before
-        // we do anything else, make sure its LinkProperties are accurate.
-        if (networkAgent.clatd != null) {
-            networkAgent.clatd.fixupLinkProperties(oldLp, newLp);
-        }
+        // The NetworkAgentInfo does not know whether clatd is running on its network or not, or
+        // whether there is a NAT64 prefix. Before we do anything else, make sure its LinkProperties
+        // are accurate.
+        networkAgent.clatd.fixupLinkProperties(oldLp, newLp);
 
         updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities);
         updateMtu(newLp, oldLp);
@@ -5290,8 +5320,8 @@
             synchronized (networkAgent) {
                 networkAgent.linkProperties = newLp;
             }
-            // Start or stop clat accordingly to network state.
-            networkAgent.updateClat(mNMS);
+            // Start or stop DNS64 detection and 464xlat according to network state.
+            networkAgent.clatd.update();
             notifyIfacesChangedForNetworkStats();
             if (networkAgent.everConnected) {
                 try {
diff --git a/services/core/java/com/android/server/ExtconUEventObserver.java b/services/core/java/com/android/server/ExtconUEventObserver.java
index 775e4c8..6b42b3d 100644
--- a/services/core/java/com/android/server/ExtconUEventObserver.java
+++ b/services/core/java/com/android/server/ExtconUEventObserver.java
@@ -162,15 +162,6 @@
     /** Does the {@link /sys/class/extcon} directory exist */
     public static boolean extconExists() {
         File extconDir = new File("/sys/class/extcon");
-        boolean retVal = extconDir.exists() && extconDir.isDirectory();
-        // TODO(b/124364409): return the correct value after selinux policy is updated.
-        if (retVal) {
-            Slog.w(TAG, extconDir + " exists " + extconDir.exists() + " isDir "
-                    + extconDir.isDirectory()
-                    + " but reporting it does not exist until selinux policies are updated."
-                    + " see b/124364409"
-            );
-        }
-        return false;
+        return extconDir.exists() && extconDir.isDirectory();
     }
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index d8b96e4..d7cc19b 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -337,7 +337,7 @@
                     @Override
                     public void onChange(boolean selfChange) {
                         synchronized (mLock) {
-                            onProviderAllowedChangedLocked(true);
+                            onProviderAllowedChangedLocked();
                         }
                     }
                 }, UserHandle.USER_ALL);
@@ -436,6 +436,10 @@
 
     @GuardedBy("mLock")
     private void onLocationModeChangedLocked(boolean broadcast) {
+        if (D) {
+            Log.d(TAG, "location enabled is now " + isLocationEnabled());
+        }
+
         for (LocationProvider p : mProviders) {
             p.onLocationModeChangedLocked();
         }
@@ -448,16 +452,10 @@
     }
 
     @GuardedBy("mLock")
-    private void onProviderAllowedChangedLocked(boolean broadcast) {
+    private void onProviderAllowedChangedLocked() {
         for (LocationProvider p : mProviders) {
             p.onAllowedChangedLocked();
         }
-
-        if (broadcast) {
-            mContext.sendBroadcastAsUser(
-                    new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
-                    UserHandle.ALL);
-        }
     }
 
     @GuardedBy("mLock")
@@ -827,6 +825,10 @@
             return;
         }
 
+        if (D) {
+            Log.d(TAG, "foreground user is changing to " + userId);
+        }
+
         // let providers know the current user is on the way out before changing the user
         for (LocationProvider p : mProviders) {
             p.onUserChangingLocked();
@@ -839,7 +841,12 @@
 
         // if the user changes, per-user settings may also have changed
         onLocationModeChangedLocked(false);
-        onProviderAllowedChangedLocked(false);
+        onProviderAllowedChangedLocked();
+
+        // always force useability to be rechecked, even if no per-user settings have changed
+        for (LocationProvider p : mProviders) {
+            p.onUseableChangedLocked(false);
+        }
     }
 
     private class LocationProvider implements AbstractLocationProvider.LocationProviderManager {
@@ -891,9 +898,13 @@
         public void attachLocked(AbstractLocationProvider provider) {
             checkNotNull(provider);
             checkState(mProvider == null);
-            mProvider = provider;
 
-            onUseableChangedLocked();
+            if (D) {
+                Log.d(TAG, mName + " provider attached");
+            }
+
+            mProvider = provider;
+            onUseableChangedLocked(false);
         }
 
         public String getName() {
@@ -1054,26 +1065,12 @@
                         return;
                     }
 
-                    mEnabled = enabled;
-
-                    // update provider allowed settings to reflect enabled status
-                    if (mIsManagedBySettings) {
-                        if (mEnabled && !mAllowed) {
-                            Settings.Secure.putStringForUser(
-                                    mContext.getContentResolver(),
-                                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
-                                    "+" + mName,
-                                    mCurrentUserId);
-                        } else if (!mEnabled && mAllowed) {
-                            Settings.Secure.putStringForUser(
-                                    mContext.getContentResolver(),
-                                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
-                                    "-" + mName,
-                                    mCurrentUserId);
-                        }
+                    if (D) {
+                        Log.d(TAG, mName + " provider enabled is now " + mEnabled);
                     }
 
-                    onUseableChangedLocked();
+                    mEnabled = enabled;
+                    onUseableChangedLocked(false);
                 }
             });
         }
@@ -1091,41 +1088,28 @@
 
         @GuardedBy("mLock")
         public void onLocationModeChangedLocked() {
-            onUseableChangedLocked();
-        }
-
-        private boolean isAllowed() {
-            return isAllowedForUser(mCurrentUserId);
-        }
-
-        private boolean isAllowedForUser(int userId) {
-            String allowedProviders = Settings.Secure.getStringForUser(
-                    mContext.getContentResolver(),
-                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
-                    userId);
-            return TextUtils.delimitedStringContains(allowedProviders, ',', mName);
+            onUseableChangedLocked(false);
         }
 
         @GuardedBy("mLock")
         public void onAllowedChangedLocked() {
             if (mIsManagedBySettings) {
-                boolean allowed = isAllowed();
+                String allowedProviders = Settings.Secure.getStringForUser(
+                        mContext.getContentResolver(),
+                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                        mCurrentUserId);
+                boolean allowed = TextUtils.delimitedStringContains(allowedProviders, ',', mName);
+
                 if (allowed == mAllowed) {
                     return;
                 }
-                mAllowed = allowed;
 
-                // make a best effort to keep the setting matching the real enabled state of the
-                // provider so that legacy applications aren't broken.
-                if (mAllowed && !mEnabled) {
-                    Settings.Secure.putStringForUser(
-                            mContext.getContentResolver(),
-                            Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
-                            "-" + mName,
-                            mCurrentUserId);
+                if (D) {
+                    Log.d(TAG, mName + " provider allowed is now " + mAllowed);
                 }
 
-                onUseableChangedLocked();
+                mAllowed = allowed;
+                onUseableChangedLocked(true);
             }
         }
 
@@ -1140,17 +1124,49 @@
         }
 
         @GuardedBy("mLock")
-        public void onUseableChangedLocked() {
+        private boolean isUseableIgnoringAllowedLocked() {
+            return mProvider != null && mProviders.contains(this) && isLocationEnabled()
+                    && mEnabled;
+        }
+
+        @GuardedBy("mLock")
+        public void onUseableChangedLocked(boolean isAllowedChanged) {
             // if any property that contributes to "useability" here changes state, it MUST result
             // in a direct or indrect call to onUseableChangedLocked. this allows the provider to
             // guarantee that it will always eventually reach the correct state.
-            boolean useable = mProvider != null
-                    && mProviders.contains(this) && isLocationEnabled() && mAllowed && mEnabled;
+            boolean useableIgnoringAllowed = isUseableIgnoringAllowedLocked();
+            boolean useable = useableIgnoringAllowed && mAllowed;
+
+            // update deprecated provider allowed settings for backwards compatibility, and do this
+            // even if there is no change in overall useability state. this may result in trying to
+            // overwrite the same value, but Settings handles deduping this.
+            if (mIsManagedBySettings) {
+                // a "-" change derived from the allowed setting should not be overwritten, but a
+                // "+" change should be corrected if necessary
+                if (useableIgnoringAllowed && !isAllowedChanged) {
+                    Settings.Secure.putStringForUser(
+                            mContext.getContentResolver(),
+                            Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                            "+" + mName,
+                            mCurrentUserId);
+                } else if (!useableIgnoringAllowed) {
+                    Settings.Secure.putStringForUser(
+                            mContext.getContentResolver(),
+                            Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                            "-" + mName,
+                            mCurrentUserId);
+                }
+            }
+
             if (useable == mUseable) {
                 return;
             }
             mUseable = useable;
 
+            if (D) {
+                Log.d(TAG, mName + " provider useable is now " + mUseable);
+            }
+
             if (!mUseable) {
                 // If any provider has been disabled, clear all last locations for all
                 // providers. This is to be on the safe side in case a provider has location
@@ -1160,6 +1176,10 @@
             }
 
             updateProviderUseableLocked(this);
+
+            mContext.sendBroadcastAsUser(
+                    new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
+                    UserHandle.ALL);
         }
 
         @GuardedBy("mLock")
@@ -1720,7 +1740,7 @@
         mProviders.add(provider);
 
         provider.onAllowedChangedLocked();  // allowed state may change while provider was inactive
-        provider.onUseableChangedLocked();
+        provider.onUseableChangedLocked(false);
     }
 
     @GuardedBy("mLock")
@@ -1728,7 +1748,7 @@
         if (mProviders.remove(provider)) {
             long identity = Binder.clearCallingIdentity();
             try {
-                provider.onUseableChangedLocked();
+                provider.onUseableChangedLocked(false);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -2113,7 +2133,6 @@
             }
         }
 
-        if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
         provider.setRequestLocked(providerRequest, worksource);
     }
 
@@ -2507,7 +2526,6 @@
 
     @Override
     public Location getLastLocation(LocationRequest r, String packageName) {
-        if (D) Log.d(TAG, "getLastLocation: " + r);
         synchronized (mLock) {
             LocationRequest request = r != null ? r : DEFAULT_LOCATION_REQUEST;
             int allowedResolutionLevel = getCallerAllowedResolutionLevel();
@@ -2643,33 +2661,33 @@
         synchronized (mLock) {
             checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
                     request.getProvider());
-            // Require that caller can manage given document
-            boolean callerHasLocationHardwarePermission =
-                    mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
-                            == PERMISSION_GRANTED;
-            LocationRequest sanitizedRequest = createSanitizedRequest(request,
+        }
+        // Require that caller can manage given document
+        boolean callerHasLocationHardwarePermission =
+                mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
+                        == PERMISSION_GRANTED;
+        LocationRequest sanitizedRequest = createSanitizedRequest(request,
+                allowedResolutionLevel,
+                callerHasLocationHardwarePermission);
+
+        if (D) {
+            Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
+        }
+
+        // geo-fence manager uses the public location API, need to clear identity
+        int uid = Binder.getCallingUid();
+        if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
+            // temporary measure until geofences work for secondary users
+            Log.w(TAG, "proximity alerts are currently available only to the primary user");
+            return;
+        }
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mGeofenceManager.addFence(sanitizedRequest, geofence, intent,
                     allowedResolutionLevel,
-                    callerHasLocationHardwarePermission);
-
-            if (D) {
-                Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
-            }
-
-            // geo-fence manager uses the public location API, need to clear identity
-            int uid = Binder.getCallingUid();
-            if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
-                // temporary measure until geofences work for secondary users
-                Log.w(TAG, "proximity alerts are currently available only to the primary user");
-                return;
-            }
-            long identity = Binder.clearCallingIdentity();
-            try {
-                mGeofenceManager.addFence(sanitizedRequest, geofence, intent,
-                        allowedResolutionLevel,
-                        uid, packageName);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
+                    uid, packageName);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index ada3947..98f260c 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -205,6 +205,9 @@
 
     private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
 
+    private static final boolean ENABLE_LEGACY_GREYLIST = SystemProperties
+            .getBoolean(StorageManager.PROP_LEGACY_GREYLIST, true);
+
     public static class Lifecycle extends SystemService {
         private StorageManagerService mStorageManagerService;
 
@@ -2289,7 +2292,26 @@
                 refreshIsolatedStorageSettings();
 
                 // Perform hard reboot to kick policy into place
-                mContext.getSystemService(PowerManager.class).reboot(null);
+                mHandler.post(() -> {
+                    mContext.getSystemService(PowerManager.class).reboot(null);
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        if ((mask & StorageManager.DEBUG_LEGACY_GREYLIST) != 0) {
+            final boolean enabled = (flags & StorageManager.DEBUG_LEGACY_GREYLIST) != 0;
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                SystemProperties.set(StorageManager.PROP_LEGACY_GREYLIST,
+                        Boolean.toString(enabled));
+
+                // Perform hard reboot to kick policy into place
+                mHandler.post(() -> {
+                    mContext.getSystemService(PowerManager.class).reboot(null);
+                });
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -2639,8 +2661,8 @@
         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
             "no permission to access the crypt keeper");
 
-        if (StorageManager.isFileEncryptedNativeOnly()) {
-            // Not supported on FBE devices
+        if (!StorageManager.isBlockEncrypted()) {
+            // Only supported on FDE devices
             return;
         }
 
@@ -2663,8 +2685,8 @@
         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
             "no permission to access the crypt keeper");
 
-        if (StorageManager.isFileEncryptedNativeOnly()) {
-            // Not supported on FBE devices
+        if (!StorageManager.isBlockEncrypted()) {
+            // Only supported on FDE devices
             return null;
         }
 
@@ -3675,16 +3697,17 @@
             } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
                 return Zygote.MOUNT_EXTERNAL_NONE;
             } else {
-                // STOPSHIP: remove this temporary workaround once developers
-                // fix bugs where they're opening _data paths in native code
-                switch (packageName) {
-                    case "com.facebook.katana": // b/123996076
-                    case "jp.naver.line.android": // b/124767356
-                    case "com.mxtech.videoplayer.ad": // b/124531483
-                        return Zygote.MOUNT_EXTERNAL_LEGACY;
-                    default:
-                        return Zygote.MOUNT_EXTERNAL_WRITE;
+                if (ENABLE_LEGACY_GREYLIST) {
+                    // STOPSHIP: remove this temporary workaround once developers
+                    // fix bugs where they're opening _data paths in native code
+                    switch (packageName) {
+                        case "com.facebook.katana": // b/123996076
+                        case "jp.naver.line.android": // b/124767356
+                        case "com.mxtech.videoplayer.ad": // b/124531483
+                            return Zygote.MOUNT_EXTERNAL_LEGACY;
+                    }
                 }
+                return Zygote.MOUNT_EXTERNAL_WRITE;
             }
         } catch (RemoteException e) {
             // Should not happen
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index fb541e0..346492f 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -933,6 +933,27 @@
         }
     }
 
+    /**
+     * Return the current foregroundServiceType of the ServiceRecord.
+     * @param className ComponentName of the Service class.
+     * @param token IBinder token.
+     * @return current foreground service type.
+     */
+    public int getForegroundServiceTypeLocked(ComponentName className, IBinder token) {
+        final int userId = UserHandle.getCallingUserId();
+        final long origId = Binder.clearCallingIdentity();
+        int ret = ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
+        try {
+            ServiceRecord r = findServiceLocked(className, token, userId);
+            if (r != null) {
+                ret = r.foregroundServiceType;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+        return ret;
+    }
+
     boolean foregroundAppShownEnoughLocked(ActiveForegroundApp aa, long nowElapsed) {
         if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Shown enough: pkg=" + aa.mPackageName + ", uid="
                 + aa.mUid);
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/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f2902b1..fe85d23 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13586,6 +13586,13 @@
     }
 
     @Override
+    public int getForegroundServiceType(ComponentName className, IBinder token) {
+        synchronized (this) {
+            return mServices.getForegroundServiceTypeLocked(className, token);
+        }
+    }
+
+    @Override
     public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
             boolean requireFull, String name, String callerPackage) {
         return mUserController.handleIncomingUser(callingPid, callingUid, userId, allowAll,
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 afdfbe3..6bd412b 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -88,6 +88,9 @@
 import android.media.audiopolicy.AudioMix;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicyConfig;
+import android.media.audiopolicy.AudioProductStrategies;
+import android.media.audiopolicy.AudioVolumeGroup;
+import android.media.audiopolicy.AudioVolumeGroups;
 import android.media.audiopolicy.IAudioPolicyCallback;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionManager;
@@ -127,6 +130,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
@@ -274,6 +278,11 @@
 
     private SettingsObserver mSettingsObserver;
 
+    /** @see AudioProductStrategies */
+    private static AudioProductStrategies sAudioProductStrategies;
+    /** @see AudioVolumeGroups */
+    private static AudioVolumeGroups sAudioVolumeGroups;
+
     private int mMode = AudioSystem.MODE_NORMAL;
     // protects mRingerMode
     private final Object mSettingsLock = new Object();
@@ -624,6 +633,9 @@
         mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
 
+        sAudioProductStrategies = new AudioProductStrategies();
+        sAudioVolumeGroups = new AudioVolumeGroups();
+
         // Initialize volume
         int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
         if (maxCallVolume != -1) {
@@ -988,6 +1000,22 @@
         }
     }
 
+    /**
+     * @return the {@link android.media.audiopolicy.AudioProductStrategies} discovered from the
+     * platform configuration file.
+     */
+    public @NonNull AudioProductStrategies getAudioProductStrategies() {
+        return sAudioProductStrategies;
+    }
+
+    /**
+     * @return the {@link android.media.audiopolicy.AudioVolumeGroups} discovered from the
+     * platform configuration file.
+     */
+    public @NonNull AudioVolumeGroups listAudioVolumeGroups() {
+        return sAudioVolumeGroups;
+    }
+
     private void checkAllAliasStreamVolumes() {
         synchronized (mSettingsLock) {
             synchronized (VolumeStreamState.class) {
@@ -1878,6 +1906,62 @@
         mStreamStates[stream].mute(index == 0);
     }
 
+    private void enforceModifyAudioRoutingPermission() {
+        if (mContext.checkCallingPermission(
+                    android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Missing MODIFY_AUDIO_ROUTING permission");
+        }
+    }
+
+    /** @see AudioManager#setVolumeIndexForAttributes(attr, int, int) */
+    public void setVolumeIndexForAttributes(@NonNull AudioAttributes attr, int index, int flags,
+                                            String callingPackage) {
+        enforceModifyAudioRoutingPermission();
+        Preconditions.checkNotNull(attr, "attr must not be null");
+        // @todo not hold the caller context, post message
+        int stream = sAudioProductStrategies.getLegacyStreamTypeForAudioAttributes(attr);
+        final int device = getDeviceForStream(stream);
+
+        int oldIndex = AudioSystem.getVolumeIndexForAttributes(attr, device);
+
+        AudioSystem.setVolumeIndexForAttributes(attr, index, device);
+
+        final int volumeGroup = sAudioProductStrategies.getVolumeGroupIdForAttributes(attr);
+        final AudioVolumeGroup avg = sAudioVolumeGroups.getById(volumeGroup);
+        if (avg == null) {
+            return;
+        }
+        for (final int groupedStream : avg.getLegacyStreamTypes()) {
+            setStreamVolume(stream, index, flags, callingPackage, callingPackage,
+                            Binder.getCallingUid());
+        }
+    }
+
+    /** @see AudioManager#getVolumeIndexForAttributes(attr) */
+    public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
+        enforceModifyAudioRoutingPermission();
+        Preconditions.checkNotNull(attr, "attr must not be null");
+        int stream = sAudioProductStrategies.getLegacyStreamTypeForAudioAttributes(attr);
+        final int device = getDeviceForStream(stream);
+
+        return AudioSystem.getVolumeIndexForAttributes(attr, device);
+    }
+
+    /** @see AudioManager#getMaxVolumeIndexForAttributes(attr) */
+    public int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
+        enforceModifyAudioRoutingPermission();
+        Preconditions.checkNotNull(attr, "attr must not be null");
+        return AudioSystem.getMaxVolumeIndexForAttributes(attr);
+    }
+
+    /** @see AudioManager#getMinVolumeIndexForAttributes(attr) */
+    public int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
+        enforceModifyAudioRoutingPermission();
+        Preconditions.checkNotNull(attr, "attr must not be null");
+        return AudioSystem.getMinVolumeIndexForAttributes(attr);
+    }
+
     /** @see AudioManager#setStreamVolume(int, int, int) */
     public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
         if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
@@ -5787,7 +5871,7 @@
     // - wired: logged before onSetWiredDeviceConnectionState() is executed
     // - A2DP: logged at reception of method call
     /*package*/ static final AudioEventLogger sDeviceLogger = new AudioEventLogger(
-            LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP/hearing aid device connection BLABLI");
+            LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP/hearing aid device connection");
 
     static final AudioEventLogger sForceUseLogger = new AudioEventLogger(
             LOG_NB_EVENTS_FORCE_USE,
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index 9d9b1cf..2646d76 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -18,19 +18,24 @@
 
 import android.net.ConnectivityManager;
 import android.net.INetd;
+import android.net.InetAddresses;
 import android.net.InterfaceConfiguration;
+import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
 import android.net.RouteInfo;
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.net.BaseNetworkObserver;
 
 import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.util.Objects;
 
 /**
@@ -67,15 +72,16 @@
     private final NetworkAgentInfo mNetwork;
 
     private enum State {
-        IDLE,       // start() not called. Base iface and stacked iface names are null.
-        STARTING,   // start() called. Base iface and stacked iface names are known.
-        RUNNING,    // start() called, and the stacked iface is known to be up.
-        STOPPING;   // stop() called, this Nat464Xlat is still registered as a network observer for
-                    // the stacked interface.
+        IDLE,         // start() not called. Base iface and stacked iface names are null.
+        DISCOVERING,  // same as IDLE, except prefix discovery in progress.
+        STARTING,     // start() called. Base iface and stacked iface names are known.
+        RUNNING,      // start() called, and the stacked iface is known to be up.
     }
 
+    private IpPrefix mNat64Prefix;
     private String mBaseIface;
     private String mIface;
+    private Inet6Address mIPv6Address;
     private State mState = State.IDLE;
 
     public Nat464Xlat(NetworkAgentInfo nai, INetd netd, INetworkManagementService nmService) {
@@ -85,20 +91,51 @@
     }
 
     /**
-     * Determines whether a network requires clat.
+     * Whether to attempt 464xlat on this network. This is true for an IPv6-only network that is
+     * currently connected and where the NetworkAgent has not disabled 464xlat. It is the signal to
+     * enable NAT64 prefix discovery.
+     *
      * @param network the NetworkAgentInfo corresponding to the network.
      * @return true if the network requires clat, false otherwise.
      */
-    public static boolean requiresClat(NetworkAgentInfo nai) {
+    @VisibleForTesting
+    protected static boolean requiresClat(NetworkAgentInfo nai) {
         // TODO: migrate to NetworkCapabilities.TRANSPORT_*.
         final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType());
         final boolean connected = ArrayUtils.contains(NETWORK_STATES, nai.networkInfo.getState());
-        // We only run clat on networks that don't have a native IPv4 address.
-        final boolean hasIPv4Address =
-                (nai.linkProperties != null) && nai.linkProperties.hasIPv4Address();
-        final boolean skip464xlat =
-                (nai.netMisc() != null) && nai.netMisc().skip464xlat;
-        return supported && connected && !hasIPv4Address && !skip464xlat;
+
+        // Only run clat on networks that have a global IPv6 address and don't have a native IPv4
+        // address.
+        LinkProperties lp = nai.linkProperties;
+        final boolean isIpv6OnlyNetwork = (lp != null) && lp.hasGlobalIPv6Address()
+                && !lp.hasIPv4Address();
+
+        // If the network tells us it doesn't use clat, respect that.
+        final boolean skip464xlat = (nai.netMisc() != null) && nai.netMisc().skip464xlat;
+
+        return supported && connected && isIpv6OnlyNetwork && !skip464xlat;
+    }
+
+    /**
+     * Whether the clat demon should be started on this network now. This is true if requiresClat is
+     * true and a NAT64 prefix has been discovered.
+     *
+     * @param nai the NetworkAgentInfo corresponding to the network.
+     * @return true if the network should start clat, false otherwise.
+     */
+    @VisibleForTesting
+    protected static boolean shouldStartClat(NetworkAgentInfo nai) {
+        LinkProperties lp = nai.linkProperties;
+        return requiresClat(nai) && lp != null && lp.getNat64Prefix() != null;
+    }
+
+    /**
+     * @return true if we have started prefix discovery and not yet stopped it (regardless of
+     * whether it is still running or has succeeded).
+     * A true result corresponds to internal states DISCOVERING, STARTING and RUNNING.
+     */
+    public boolean isPrefixDiscoveryStarted() {
+        return mState == State.DISCOVERING || isStarted();
     }
 
     /**
@@ -106,7 +143,7 @@
      * A true result corresponds to internal states STARTING and RUNNING.
      */
     public boolean isStarted() {
-        return mState != State.IDLE;
+        return (mState == State.STARTING || mState == State.RUNNING);
     }
 
     /**
@@ -124,32 +161,31 @@
     }
 
     /**
-     * @return true if clatd has been stopped.
-     */
-    public boolean isStopping() {
-        return mState == State.STOPPING;
-    }
-
-    /**
      * Start clatd, register this Nat464Xlat as a network observer for the stacked interface,
      * and set internal state.
      */
     private void enterStartingState(String baseIface) {
         try {
             mNMService.registerObserver(this);
-        } catch(RemoteException e) {
-            Slog.e(TAG,
-                    "startClat: Can't register interface observer for clat on " + mNetwork.name());
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Can't register interface observer for clat on " + mNetwork.name());
             return;
         }
+
+        String addrStr = null;
         try {
-            mNetd.clatdStart(baseIface);
-        } catch(RemoteException|IllegalStateException e) {
-            Slog.e(TAG, "Error starting clatd on " + baseIface, e);
+            addrStr = mNetd.clatdStart(baseIface, mNat64Prefix.toString());
+        } catch (RemoteException | ServiceSpecificException e) {
+            Slog.e(TAG, "Error starting clatd on " + baseIface + ": " + e);
         }
         mIface = CLAT_PREFIX + baseIface;
         mBaseIface = baseIface;
         mState = State.STARTING;
+        try {
+            mIPv6Address = (Inet6Address) InetAddresses.parseNumericAddress(addrStr);
+        } catch (ClassCastException | IllegalArgumentException | NullPointerException e) {
+            Slog.e(TAG, "Invalid IPv6 address " + addrStr);
+        }
     }
 
     /**
@@ -161,37 +197,27 @@
     }
 
     /**
-     * Stop clatd, and turn ND offload on if it had been turned off.
-     */
-    private void enterStoppingState() {
-        try {
-            mNetd.clatdStop(mBaseIface);
-        } catch(RemoteException|IllegalStateException e) {
-            Slog.e(TAG, "Error stopping clatd on " + mBaseIface, e);
-        }
-
-        mState = State.STOPPING;
-    }
-
-    /**
      * Unregister as a base observer for the stacked interface, and clear internal state.
      */
-    private void enterIdleState() {
+    private void leaveStartedState() {
         try {
             mNMService.unregisterObserver(this);
-        } catch(RemoteException|IllegalStateException e) {
-            Slog.e(TAG, "Error unregistering clatd observer on " + mBaseIface, e);
+        } catch (RemoteException | IllegalStateException e) {
+            Slog.e(TAG, "Error unregistering clatd observer on " + mBaseIface + ": " + e);
         }
-
         mIface = null;
         mBaseIface = null;
         mState = State.IDLE;
+        if (requiresClat(mNetwork)) {
+            mState = State.DISCOVERING;
+        } else {
+            stopPrefixDiscovery();
+            mState = State.IDLE;
+        }
     }
 
-    /**
-     * Starts the clat daemon.
-     */
-    public void start() {
+    @VisibleForTesting
+    protected void start() {
         if (isStarted()) {
             Slog.e(TAG, "startClat: already started");
             return;
@@ -212,20 +238,82 @@
         enterStartingState(baseIface);
     }
 
-    /**
-     * Stops the clat daemon.
-     */
-    public void stop() {
+    @VisibleForTesting
+    protected void stop() {
         if (!isStarted()) {
+            Slog.e(TAG, "stopClat: already stopped");
             return;
         }
-        Slog.i(TAG, "Stopping clatd on " + mBaseIface);
 
-        boolean wasStarting = isStarting();
-        enterStoppingState();
-        if (wasStarting) {
-            enterIdleState();
+        Slog.i(TAG, "Stopping clatd on " + mBaseIface);
+        try {
+            mNetd.clatdStop(mBaseIface);
+        } catch (RemoteException | ServiceSpecificException e) {
+            Slog.e(TAG, "Error stopping clatd on " + mBaseIface + ": " + e);
         }
+
+        String iface = mIface;
+        boolean wasRunning = isRunning();
+
+        // Change state before updating LinkProperties. handleUpdateLinkProperties ends up calling
+        // fixupLinkProperties, and if at that time the state is still RUNNING, fixupLinkProperties
+        // would wrongly inform ConnectivityService that there is still a stacked interface.
+        leaveStartedState();
+
+        if (wasRunning) {
+            LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
+            lp.removeStackedLink(iface);
+            mNetwork.connService().handleUpdateLinkProperties(mNetwork, lp);
+        }
+    }
+
+    private void startPrefixDiscovery() {
+        try {
+            mNetd.resolverStartPrefix64Discovery(getNetId());
+            mState = State.DISCOVERING;
+        } catch (RemoteException | ServiceSpecificException e) {
+            Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e);
+        }
+    }
+
+    private void stopPrefixDiscovery() {
+        try {
+            mNetd.resolverStopPrefix64Discovery(getNetId());
+        } catch (RemoteException | ServiceSpecificException e) {
+            Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e);
+        }
+    }
+
+    /**
+     * Starts/stops NAT64 prefix discovery and clatd as necessary.
+     */
+    public void update() {
+        // TODO: turn this class into a proper StateMachine. // http://b/126113090
+        if (requiresClat(mNetwork)) {
+            if (!isPrefixDiscoveryStarted()) {
+                startPrefixDiscovery();
+            } else if (shouldStartClat(mNetwork)) {
+                // NAT64 prefix detected. Start clatd.
+                // TODO: support the NAT64 prefix changing after it's been discovered. There is no
+                // need to support this at the moment because it cannot happen without changes to
+                // the Dns64Configuration code in netd.
+                start();
+            } else {
+                // NAT64 prefix removed. Stop clatd and go back into DISCOVERING state.
+                stop();
+            }
+        } else {
+            // Network no longer requires clat. Stop clat and prefix discovery.
+            if (isStarted()) {
+                stop();
+            } else if (isPrefixDiscoveryStarted()) {
+                leaveStartedState();
+            }
+        }
+    }
+
+    public void setNat64Prefix(IpPrefix nat64Prefix) {
+        mNat64Prefix = nat64Prefix;
     }
 
     /**
@@ -234,6 +322,8 @@
      * has no idea that 464xlat is running on top of it.
      */
     public void fixupLinkProperties(LinkProperties oldLp, LinkProperties lp) {
+        lp.setNat64Prefix(mNat64Prefix);
+
         if (!isRunning()) {
             return;
         }
@@ -272,7 +362,7 @@
         try {
             InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
             return config.getLinkAddress();
-        } catch(RemoteException|IllegalStateException e) {
+        } catch (RemoteException | IllegalStateException e) {
             Slog.e(TAG, "Error getting link properties: " + e);
             return null;
         }
@@ -282,6 +372,20 @@
      * Adds stacked link on base link and transitions to RUNNING state.
      */
     private void handleInterfaceLinkStateChanged(String iface, boolean up) {
+        // TODO: if we call start(), then stop(), then start() again, and the
+        // interfaceLinkStateChanged notification for the first start is delayed past the first
+        // stop, then the code becomes out of sync with system state and will behave incorrectly.
+        //
+        // This is not trivial to fix because:
+        // 1. It is not guaranteed that start() will eventually result in the interface coming up,
+        //    because there could be an error starting clat (e.g., if the interface goes down before
+        //    the packet socket can be bound).
+        // 2. If start is called multiple times, there is nothing in the interfaceLinkStateChanged
+        //    notification that says which start() call the interface was created by.
+        //
+        // Once this code is converted to StateMachine, it will be possible to use deferMessage to
+        // ensure it stays in STARTING state until the interfaceLinkStateChanged notification fires,
+        // and possibly use a timeout (or provide some guarantees at the lower layer) to address #1.
         if (!isStarting() || !up || !Objects.equals(mIface, iface)) {
             return;
         }
@@ -307,20 +411,16 @@
         if (!Objects.equals(mIface, iface)) {
             return;
         }
-        if (!isRunning() && !isStopping()) {
+        if (!isRunning()) {
             return;
         }
 
         Slog.i(TAG, "interface " + iface + " removed");
-        if (!isStopping()) {
-            // Ensure clatd is stopped if stop() has not been called: this likely means that clatd
-            // has crashed.
-            enterStoppingState();
-        }
-        enterIdleState();
-        LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
-        lp.removeStackedLink(iface);
-        mNetwork.connService().handleUpdateLinkProperties(mNetwork, lp);
+        // If we're running, and the interface was removed, then we didn't call stop(), and it's
+        // likely that clatd crashed. Ensure we call stop() so we can start clatd again. Calling
+        // stop() will also update LinkProperties, and if clatd crashed, the LinkProperties update
+        // will cause ConnectivityService to call start() again.
+        stop();
     }
 
     @Override
@@ -337,4 +437,9 @@
     public String toString() {
         return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mState: " + mState;
     }
+
+    @VisibleForTesting
+    protected int getNetId() {
+        return mNetwork.network.netId;
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index cd4ce2d..6ef9fbb 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -238,7 +238,7 @@
     public final int factorySerialNumber;
 
     // Used by ConnectivityService to keep track of 464xlat.
-    public Nat464Xlat clatd;
+    public final Nat464Xlat clatd;
 
     // Set after asynchronous creation of the NetworkMonitor.
     private volatile INetworkMonitor mNetworkMonitor;
@@ -246,8 +246,6 @@
     private static final String TAG = ConnectivityService.class.getSimpleName();
     private static final boolean VDBG = false;
     private final ConnectivityService mConnService;
-    private final INetd mNetd;
-    private final INetworkManagementService mNMS;
     private final Context mContext;
     private final Handler mHandler;
 
@@ -262,9 +260,8 @@
         linkProperties = lp;
         networkCapabilities = nc;
         currentScore = score;
+        clatd = new Nat464Xlat(this, netd, nms);
         mConnService = connService;
-        mNetd = netd;
-        mNMS = nms;
         mContext = context;
         mHandler = handler;
         networkMisc = misc;
@@ -598,32 +595,6 @@
         for (LingerTimer timer : mLingerTimers) { pw.println(timer); }
     }
 
-    public void updateClat(INetworkManagementService netd) {
-        if (Nat464Xlat.requiresClat(this)) {
-            maybeStartClat();
-        } else {
-            maybeStopClat();
-        }
-    }
-
-    /** Ensure clat has started for this network. */
-    public void maybeStartClat() {
-        if (clatd != null && clatd.isStarted()) {
-            return;
-        }
-        clatd = new Nat464Xlat(this, mNetd, mNMS);
-        clatd.start();
-    }
-
-    /** Ensure clat has stopped for this network. */
-    public void maybeStopClat() {
-        if (clatd == null) {
-            return;
-        }
-        clatd.stop();
-        clatd = null;
-    }
-
     public String toString() {
         return "NetworkAgentInfo{ ni{" + networkInfo + "}  "
                 + "network{" + network + "}  nethandle{" + network.getNetworkHandle() + "}  "
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 01d19c0..1aaaf41 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -96,7 +96,6 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.UiThread;
-import com.android.server.display.ColorDisplayService.ColorDisplayServiceInternal;
 import com.android.server.wm.SurfaceAnimationThread;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -357,7 +356,6 @@
         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
                 true /*allowIsolated*/);
         publishLocalService(DisplayManagerInternal.class, new LocalService());
-        publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
     }
 
     @Override
@@ -1535,13 +1533,6 @@
 
             pw.println();
             mPersistentDataStore.dump(pw);
-
-            final ColorDisplayServiceInternal cds = LocalServices.getService(
-                    ColorDisplayServiceInternal.class);
-            if (cds != null) {
-                pw.println();
-                cds.dump(pw);
-            }
         }
     }
 
diff --git a/services/core/java/com/android/server/display/OWNERS b/services/core/java/com/android/server/display/OWNERS
index 0d64dbd..25cb5ae 100644
--- a/services/core/java/com/android/server/display/OWNERS
+++ b/services/core/java/com/android/server/display/OWNERS
@@ -2,5 +2,3 @@
 dangittik@google.com
 hackbod@google.com
 ogunwale@google.com
-
-per-file ColorDisplayService.java=christyfranks@google.com
diff --git a/services/core/java/com/android/server/display/AppSaturationController.java b/services/core/java/com/android/server/display/color/AppSaturationController.java
similarity index 98%
rename from services/core/java/com/android/server/display/AppSaturationController.java
rename to services/core/java/com/android/server/display/color/AppSaturationController.java
index 5d5e4f7..e42be02 100644
--- a/services/core/java/com/android/server/display/AppSaturationController.java
+++ b/services/core/java/com/android/server/display/color/AppSaturationController.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.color;
 
 import android.annotation.UserIdInt;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.display.ColorDisplayService.ColorTransformController;
+import com.android.server.display.color.ColorDisplayService.ColorTransformController;
 
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
similarity index 96%
rename from services/core/java/com/android/server/display/ColorDisplayService.java
rename to services/core/java/com/android/server/display/color/ColorDisplayService.java
index 7dd3b36..b1e5510 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.color;
 
 import static android.hardware.display.ColorDisplayManager.AUTO_MODE_CUSTOM_TIME;
 import static android.hardware.display.ColorDisplayManager.AUTO_MODE_DISABLED;
@@ -24,9 +24,9 @@
 import static android.hardware.display.ColorDisplayManager.COLOR_MODE_NATURAL;
 import static android.hardware.display.ColorDisplayManager.COLOR_MODE_SATURATED;
 
-import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
-import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
-import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION;
+import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
+import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
+import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION;
 
 import android.Manifest;
 import android.animation.Animator;
@@ -233,6 +233,7 @@
     public void onStart() {
         publishBinderService(Context.COLOR_DISPLAY_SERVICE, new BinderService());
         publishLocalService(ColorDisplayServiceInternal.class, new ColorDisplayServiceInternal());
+        publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
     }
 
     @Override
@@ -632,9 +633,9 @@
     @VisibleForTesting
     void updateDisplayWhiteBalanceStatus() {
         boolean oldActivated = mDisplayWhiteBalanceTintController.isActivated();
-        mDisplayWhiteBalanceTintController.setActivated(isDisplayWhiteBalanceSettingEnabled() &&
-                !mNightDisplayTintController.isActivated() &&
-                DisplayTransformManager.needsLinearColorMatrix());
+        mDisplayWhiteBalanceTintController.setActivated(isDisplayWhiteBalanceSettingEnabled()
+                && !mNightDisplayTintController.isActivated()
+                && DisplayTransformManager.needsLinearColorMatrix());
         boolean activated = mDisplayWhiteBalanceTintController.isActivated();
 
         if (mDisplayWhiteBalanceListener != null && oldActivated != activated) {
@@ -819,7 +820,7 @@
     /**
      * Get the current color mode from system properties, or return -1 if invalid.
      *
-     * See {@link com.android.server.display.DisplayTransformManager}
+     * See {@link DisplayTransformManager}
      */
     private @ColorMode int getCurrentColorModeFromSystemProperties() {
         final int displayColorSetting = SystemProperties.getInt("persist.sys.sf.native_mode", 0);
@@ -851,7 +852,7 @@
     private void dumpInternal(PrintWriter pw) {
         pw.println("COLOR DISPLAY MANAGER dumpsys (color_display)");
 
-        pw.println("Night Display:");
+        pw.println("Night display:");
         if (mNightDisplayTintController.isAvailable(getContext())) {
             pw.println("    Activated: " + mNightDisplayTintController.isActivated());
             pw.println("    Color temp: " + mNightDisplayTintController.getColorTemperature());
@@ -923,14 +924,15 @@
 
             if (mLastActivatedTime != null) {
                 // Maintain the existing activated state if within the current period.
-                if (mLastActivatedTime.isBefore(now) && mLastActivatedTime.isAfter(start)
+                if (mLastActivatedTime.isBefore(now)
+                        && mLastActivatedTime.isAfter(start)
                         && (mLastActivatedTime.isAfter(end) || now.isBefore(end))) {
                     activate = mNightDisplayTintController.isActivatedSetting();
                 }
             }
 
-            if (mNightDisplayTintController.isActivatedStateNotSet() || (
-                    mNightDisplayTintController.isActivated() != activate)) {
+            if (mNightDisplayTintController.isActivatedStateNotSet()
+                    || (mNightDisplayTintController.isActivated() != activate)) {
                 mNightDisplayTintController.setActivated(activate);
             }
 
@@ -1305,10 +1307,11 @@
     }
 
     final class DisplayWhiteBalanceTintController extends TintController {
+
         // Three chromaticity coordinates per color: X, Y, and Z
-        private final int NUM_VALUES_PER_PRIMARY = 3;
+        private static final int NUM_VALUES_PER_PRIMARY = 3;
         // Four colors: red, green, blue, and white
-        private final int NUM_DISPLAY_PRIMARIES_VALS = 4 * NUM_VALUES_PER_PRIMARY;
+        private static final int NUM_DISPLAY_PRIMARIES_VALS = 4 * NUM_VALUES_PER_PRIMARY;
 
         private final Object mLock = new Object();
         @VisibleForTesting
@@ -1478,25 +1481,25 @@
                 pw.println("    mTemperatureMax = " + mTemperatureMax);
                 pw.println("    mTemperatureDefault = " + mTemperatureDefault);
                 pw.println("    mCurrentColorTemperature = " + mCurrentColorTemperature);
-                pw.println("    mCurrentColorTemperatureXYZ = " +
-                        matrixToString(mCurrentColorTemperatureXYZ, 3));
-                pw.println("    mDisplayColorSpaceRGB RGB-to-XYZ = " +
-                        matrixToString(mDisplayColorSpaceRGB.getTransform(), 3));
-                pw.println("    mChromaticAdaptationMatrix = " +
-                        matrixToString(mChromaticAdaptationMatrix, 3));
-                pw.println("    mDisplayColorSpaceRGB XYZ-to-RGB = " +
-                        matrixToString(mDisplayColorSpaceRGB.getInverseTransform(), 3));
-                pw.println("    mMatrixDisplayWhiteBalance = " +
-                        matrixToString(mMatrixDisplayWhiteBalance, 4));
+                pw.println("    mCurrentColorTemperatureXYZ = "
+                        + matrixToString(mCurrentColorTemperatureXYZ, 3));
+                pw.println("    mDisplayColorSpaceRGB RGB-to-XYZ = "
+                        + matrixToString(mDisplayColorSpaceRGB.getTransform(), 3));
+                pw.println("    mChromaticAdaptationMatrix = "
+                        + matrixToString(mChromaticAdaptationMatrix, 3));
+                pw.println("    mDisplayColorSpaceRGB XYZ-to-RGB = "
+                        + matrixToString(mDisplayColorSpaceRGB.getInverseTransform(), 3));
+                pw.println("    mMatrixDisplayWhiteBalance = "
+                        + matrixToString(mMatrixDisplayWhiteBalance, 4));
             }
         }
 
         private ColorSpace.Rgb makeRgbColorSpaceFromXYZ(float[] redGreenBlueXYZ, float[] whiteXYZ) {
             return new ColorSpace.Rgb(
-                "Display Color Space",
-                redGreenBlueXYZ,
-                whiteXYZ,
-                2.2f // gamma, unused for display white balance
+                    "Display Color Space",
+                    redGreenBlueXYZ,
+                    whiteXYZ,
+                    2.2f // gamma, unused for display white balance
             );
         }
 
@@ -1507,19 +1510,19 @@
             }
 
             DisplayPrimaries primaries = SurfaceControl.getDisplayNativePrimaries(displayToken);
-            if (primaries == null || primaries.red == null || primaries.green == null ||
-                primaries.blue == null || primaries.white == null) {
+            if (primaries == null || primaries.red == null || primaries.green == null
+                    || primaries.blue == null || primaries.white == null) {
                 return null;
             }
 
             return makeRgbColorSpaceFromXYZ(
-                    new float[] {
-                        primaries.red.X, primaries.red.Y, primaries.red.Z,
-                        primaries.green.X, primaries.green.Y, primaries.green.Z,
-                        primaries.blue.X, primaries.blue.Y, primaries.blue.Z,
+                    new float[]{
+                            primaries.red.X, primaries.red.Y, primaries.red.Z,
+                            primaries.green.X, primaries.green.Y, primaries.green.Z,
+                            primaries.blue.X, primaries.blue.Y, primaries.blue.Z,
                     },
-                    new float[] { primaries.white.X, primaries.white.Y, primaries.white.Z }
-                    );
+                    new float[]{primaries.white.X, primaries.white.Y, primaries.white.Z}
+            );
         }
 
         private ColorSpace.Rgb getDisplayColorSpaceFromResources(Resources res) {
@@ -1540,7 +1543,7 @@
 
             return makeRgbColorSpaceFromXYZ(displayRedGreenBlueXYZ, displayWhiteXYZ);
         }
-    };
+    }
 
     /**
      * Local service that allows color transforms to be enabled from other system services.
@@ -1572,10 +1575,6 @@
             return mDisplayWhiteBalanceTintController.isActivated();
         }
 
-        public void dump(PrintWriter pw) {
-            mDisplayWhiteBalanceTintController.dump(pw);
-        }
-
         /**
          * Adds a {@link WeakReference<ColorTransformController>} for a newly started activity, and
          * invokes {@link ColorTransformController#applyAppSaturation(float[], float[])} if needed.
diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
similarity index 96%
rename from services/core/java/com/android/server/display/DisplayTransformManager.java
rename to services/core/java/com/android/server/display/color/DisplayTransformManager.java
index ef92401..026837f 100644
--- a/services/core/java/com/android/server/display/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.color;
 
 import android.app.ActivityTaskManager;
 import android.hardware.display.ColorDisplayManager;
@@ -117,12 +117,12 @@
     /**
      * Sets and applies a current color transform matrix for a given level.
      * <p>
-     * Note: all color transforms are first composed to a single matrix in ascending order based
-     * on level before being applied to the display.
+     * Note: all color transforms are first composed to a single matrix in ascending order based on
+     * level before being applied to the display.
      *
      * @param level the level used to identify and compose the color transform (low -> high)
      * @param value the 4x4 color transform matrix (in column-major order), or {@code null} to
-     *              remove the color transform matrix associated with the provided level
+     * remove the color transform matrix associated with the provided level
      */
     public void setColorMatrix(int level, float[] value) {
         if (value != null && value.length != 16) {
@@ -235,13 +235,15 @@
     }
 
     /**
-     * Return true when the specified colorMode requires the color matrix to
-     * work in linear space.
+     * Return true when the specified colorMode requires the color matrix to work in linear space.
      */
     public static boolean needsLinearColorMatrix(int colorMode) {
         return colorMode != ColorDisplayManager.COLOR_MODE_SATURATED;
     }
 
+    /**
+     * Sets color mode and updates night display transform values.
+     */
     public boolean setColorMode(int colorMode, float[] nightDisplayMatrix) {
         if (colorMode == ColorDisplayManager.COLOR_MODE_NATURAL) {
             applySaturation(COLOR_SATURATION_NATURAL);
@@ -264,8 +266,8 @@
     }
 
     /**
-     * Returns whether the screen is color managed via SurfaceFlinger's
-     * {@link #SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGED}.
+     * Returns whether the screen is color managed via SurfaceFlinger's {@link
+     * #SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGED}.
      */
     public boolean isDeviceColorManaged() {
         final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
diff --git a/services/core/java/com/android/server/display/color/OWNERS b/services/core/java/com/android/server/display/color/OWNERS
new file mode 100644
index 0000000..27adf12
--- /dev/null
+++ b/services/core/java/com/android/server/display/color/OWNERS
@@ -0,0 +1,4 @@
+christyfranks@google.com
+justinklaassen@google.com
+
+per-file DisplayTransformManager.java=michaelwr@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index d95e92b..e7181e2 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -22,7 +22,7 @@
 
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
-import com.android.server.display.ColorDisplayService.ColorDisplayServiceInternal;
+import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
 import com.android.server.display.utils.History;
 
 import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
index a53e91c..1b7251c 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
@@ -29,8 +29,8 @@
 
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
-import com.android.server.display.ColorDisplayService;
-import com.android.server.display.ColorDisplayService.ColorDisplayServiceInternal;
+import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController.Callbacks;
 
 import java.io.PrintWriter;
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/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 5156300..ae91503 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -687,7 +687,7 @@
         }
     }
 
-    private void handleRequestLocation(boolean independentFromGnss) {
+    private void handleRequestLocation(boolean independentFromGnss, boolean isUserEmergency) {
         if (isRequestLocationRateLimited()) {
             if (DEBUG) {
                 Log.d(TAG, "RequestLocation is denied due to too frequent requests.");
@@ -723,9 +723,17 @@
                 String.format(
                         "GNSS HAL Requesting location updates from %s provider for %d millis.",
                         provider, durationMillis));
+
+        LocationRequest locationRequest = LocationRequest.createFromDeprecatedProvider(provider,
+                LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /* minDistance= */ 0,
+                /* singleShot= */ false);
+
+        // Ignore location settings if in emergency mode.
+        if (isUserEmergency && mNIHandler.getInEmergency()) {
+            locationRequest.setLocationSettingsIgnored(true);
+        }
         try {
-            locationManager.requestLocationUpdates(provider,
-                    LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /*minDistance=*/ 0,
+            locationManager.requestLocationUpdates(locationRequest,
                     locationListener, mHandler.getLooper());
             locationListener.mNumLocationUpdateRequest++;
             mHandler.postDelayed(() -> {
@@ -1828,11 +1836,13 @@
     }
 
     @NativeEntryPoint
-    private void requestLocation(boolean independentFromGnss) {
+    private void requestLocation(boolean independentFromGnss, boolean isUserEmergency) {
         if (DEBUG) {
-            Log.d(TAG, "requestLocation. independentFromGnss: " + independentFromGnss);
+            Log.d(TAG, "requestLocation. independentFromGnss: " + independentFromGnss
+                    + ", isUserEmergency: "
+                    + isUserEmergency);
         }
-        sendMessage(REQUEST_LOCATION, 0, independentFromGnss);
+        sendMessage(REQUEST_LOCATION, independentFromGnss ? 1 : 0, isUserEmergency);
     }
 
     @NativeEntryPoint
@@ -1923,7 +1933,7 @@
                     mNtpTimeHelper.retrieveAndInjectNtpTime();
                     break;
                 case REQUEST_LOCATION:
-                    handleRequestLocation((boolean) msg.obj);
+                    handleRequestLocation(msg.arg1 == 1, (boolean) msg.obj);
                     break;
                 case DOWNLOAD_XTRA_DATA:
                     handleDownloadXtraData();
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/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index fccff57..270fbc6 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -16,17 +16,15 @@
 
 package com.android.server.media.projection;
 
-import com.android.server.Watchdog;
-
 import android.Manifest;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.hardware.display.DisplayManager;
 import android.media.MediaRouter;
-import android.media.projection.IMediaProjectionManager;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionCallback;
+import android.media.projection.IMediaProjectionManager;
 import android.media.projection.IMediaProjectionWatcherCallback;
 import android.media.projection.MediaProjectionInfo;
 import android.media.projection.MediaProjectionManager;
@@ -41,6 +39,7 @@
 
 import com.android.internal.util.DumpUtils;
 import com.android.server.SystemService;
+import com.android.server.Watchdog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -361,8 +360,9 @@
 
         @Override // Binder call
         public boolean canProjectAudio() {
-            return mType == MediaProjectionManager.TYPE_MIRRORING ||
-                    mType == MediaProjectionManager.TYPE_PRESENTATION;
+            return mType == MediaProjectionManager.TYPE_MIRRORING
+                || mType == MediaProjectionManager.TYPE_PRESENTATION
+                || mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE;
         }
 
         @Override // Binder call
diff --git a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
index d53d81c..a1ff76fc 100644
--- a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
+++ b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
@@ -61,7 +61,7 @@
     private static final Pattern EXECUTE_NATIVE_AUDIT_PATTERN =
             Pattern.compile(".*\\bavc: granted \\{ execute(?:_no_trans|) \\} .*"
                     + "\\bpath=(?:\"([^\" ]*)\"|([0-9A-F]+)) .*"
-                    + "\\bscontext=u:r:untrusted_app_2(?:5|7):.*"
+                    + "\\bscontext=u:r:untrusted_app(?:_25|_27)?:.*"
                     + "\\btcontext=u:object_r:app_data_file:.*"
                     + "\\btclass=file\\b.*");
 
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..b3b7f25 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);
     }
@@ -14346,27 +14346,8 @@
                 }
 
                 if (dataOwnerPkg != null) {
-                    // If installed, the package will get access to data left on the device by its
-                    // predecessor. As a security measure, this is permited only if this is not a
-                    // version downgrade or if the predecessor package is marked as debuggable and
-                    // a downgrade is explicitly requested.
-                    //
-                    // On debuggable platform builds, downgrades are permitted even for
-                    // non-debuggable packages to make testing easier. Debuggable platform builds do
-                    // not offer security guarantees and thus it's OK to disable some security
-                    // mechanisms to make debugging/testing easier on those builds. However, even on
-                    // debuggable builds downgrades of packages are permitted only if requested via
-                    // installFlags. This is because we aim to keep the behavior of debuggable
-                    // platform builds as close as possible to the behavior of non-debuggable
-                    // platform builds.
-                    final boolean downgradeRequested =
-                            (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
-                    final boolean packageDebuggable =
-                                (dataOwnerPkg.applicationInfo.flags
-                                        & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-                    final boolean downgradePermitted =
-                            (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable));
-                    if (!downgradePermitted) {
+                    if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
+                            dataOwnerPkg.applicationInfo.flags)) {
                         try {
                             checkDowngrade(dataOwnerPkg, pkgLite);
                         } catch (PackageManagerException e) {
@@ -16324,7 +16305,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),
@@ -23119,6 +23100,18 @@
             }
             return 0;
         }
+
+        @Override
+        public boolean[] isAudioPlaybackCaptureAllowed(String[] packageNames)
+                throws RemoteException {
+            int callingUser = UserHandle.getUserId(Binder.getCallingUid());
+            boolean[] results = new boolean[packageNames.length];
+            for (int i = results.length - 1; i >= 0; --i) {
+                ApplicationInfo appInfo = getApplicationInfo(packageNames[i], 0, callingUser);
+                results[i] = appInfo == null ? false : appInfo.isAudioPlaybackCaptureAllowed();
+            }
+            return results;
+        }
     }
 
     private class PackageManagerInternalImpl extends PackageManagerInternal {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 6134d30..3218c86 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -32,6 +32,7 @@
 import android.app.AppGlobals;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
@@ -796,6 +797,36 @@
     }
 
     /**
+     * Checks whenever downgrade of an app is permitted.
+     *
+     * @param installFlags flags of the current install.
+     * @param applicationFlags flags of the currently installed version of the app.
+     * @return {@code true} if downgrade is permitted according to the {@code installFlags} and
+     *         {@code applicationFlags}.
+     */
+    public static boolean isDowngradePermitted(int installFlags, int applicationFlags) {
+        // If installed, the package will get access to data left on the device by its
+        // predecessor. As a security measure, this is permited only if this is not a
+        // version downgrade or if the predecessor package is marked as debuggable and
+        // a downgrade is explicitly requested.
+        //
+        // On debuggable platform builds, downgrades are permitted even for
+        // non-debuggable packages to make testing easier. Debuggable platform builds do
+        // not offer security guarantees and thus it's OK to disable some security
+        // mechanisms to make debugging/testing easier on those builds. However, even on
+        // debuggable builds downgrades of packages are permitted only if requested via
+        // installFlags. This is because we aim to keep the behavior of debuggable
+        // platform builds as close as possible to the behavior of non-debuggable
+        // platform builds.
+        final boolean downgradeRequested =
+                (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+        final boolean packageDebuggable =
+                (applicationFlags
+                        & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+        return (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable));
+    }
+
+    /**
      * Copy package to the target location.
      *
      * @param packagePath absolute path to the package to be copied. Can be
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 92fe377..59e5d77 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4372,6 +4372,7 @@
             ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE, "PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE",
             ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION, "PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION",
             ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE, "PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE",
+            ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE, "ALLOW_AUDIO_PLAYBACK_CAPTURE",
             ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND, "BACKUP_IN_FOREGROUND",
             ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
             ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE, "DEFAULT_TO_DEVICE_PROTECTED_STORAGE",
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index cbf5e9e..22a85eb 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();
     }
 
@@ -140,12 +144,40 @@
     private boolean submitSessionToApexService(@NonNull PackageInstallerSession session,
                                                List<PackageInstallerSession> childSessions,
                                                ApexInfoList apexInfoList) {
-        return mApexManager.submitStagedSession(
+        boolean submittedToApexd = mApexManager.submitStagedSession(
                 session.sessionId,
                 childSessions != null
                         ? childSessions.stream().mapToInt(s -> s.sessionId).toArray() :
                         new int[]{},
                 apexInfoList);
+        if (!submittedToApexd) {
+            session.setStagedSessionFailed(
+                    SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+                    "APEX staging failed, check logcat messages from apexd for more details.");
+            return false;
+        }
+        for (ApexInfo newPackage : apexInfoList.apexInfos) {
+            PackageInfo activePackage = mApexManager.getActivePackage(newPackage.packageName);
+            if (activePackage == null) {
+                continue;
+            }
+            long activeVersion = activePackage.applicationInfo.longVersionCode;
+            boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted(
+                    session.params.installFlags, activePackage.applicationInfo.flags);
+            if (activeVersion > newPackage.versionCode && !allowsDowngrade) {
+                session.setStagedSessionFailed(
+                        SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+                        "Downgrade of APEX package " + newPackage.packageName
+                                + " is not allowed. Active version: " + activeVersion
+                                + " attempted: " + newPackage.versionCode);
+
+                if (!mApexManager.abortActiveSession()) {
+                    Slog.e(TAG, "Failed to abort apex session " + session.sessionId);
+                }
+                return false;
+            }
+        }
+        return true;
     }
 
     private static boolean isApexSession(@NonNull PackageInstallerSession session) {
@@ -180,9 +212,7 @@
         }
 
         if (!success) {
-            session.setStagedSessionFailed(
-                    SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
-                    "APEX staging failed, check logcat messages from apexd for more details.");
+            // submitSessionToApexService will populate error.
             return;
         }
 
@@ -286,6 +316,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;
         }
 
@@ -473,8 +517,10 @@
     }
 
     private static boolean isApexSessionFailed(ApexSessionInfo apexSessionInfo) {
+        // isRollbackInProgress is included to cover the scenario, when a device is rebooted in
+        // during the rollback, and apexd fails to resume the rollback after reboot.
         return apexSessionInfo.isActivationFailed || apexSessionInfo.isUnknown
-                || apexSessionInfo.isRolledBack;
+                || apexSessionInfo.isRolledBack || apexSessionInfo.isRollbackInProgress;
     }
 
     @GuardedBy("mStagedSessions")
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/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index e9ccea54..36f18f0 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -166,7 +166,7 @@
         List<RollbackData> rd = new ArrayList<>();
 
         for (RollbackData data : availableRollbacks) {
-            for (PackageRollbackInfo info : data.packages) {
+            for (PackageRollbackInfo info : data.info.getPackages()) {
                 final IntArray pendingBackupUsers = info.getPendingBackups();
                 if (pendingBackupUsers != null) {
                     final int idx = pendingBackupUsers.indexOf(userId);
@@ -246,13 +246,13 @@
 
         if (!pendingBackupPackages.isEmpty()) {
             for (RollbackData data : pendingBackups) {
-                for (PackageRollbackInfo info : data.packages) {
+                for (PackageRollbackInfo info : data.info.getPackages()) {
                     final IntArray pendingBackupUsers = info.getPendingBackups();
                     final int idx = pendingBackupUsers.indexOf(userId);
                     if (idx != -1) {
                         try {
                             long ceSnapshotInode = mInstaller.snapshotAppData(info.getPackageName(),
-                                    userId, data.rollbackId, Installer.FLAG_STORAGE_CE);
+                                    userId, data.info.getRollbackId(), Installer.FLAG_STORAGE_CE);
                             info.putCeSnapshotInode(userId, ceSnapshotInode);
                             pendingBackupUsers.remove(idx);
                         } catch (InstallerException ie) {
diff --git a/services/core/java/com/android/server/rollback/RollbackData.java b/services/core/java/com/android/server/rollback/RollbackData.java
index fcd5297..655bf4a 100644
--- a/services/core/java/com/android/server/rollback/RollbackData.java
+++ b/services/core/java/com/android/server/rollback/RollbackData.java
@@ -16,12 +16,11 @@
 
 package com.android.server.rollback;
 
-import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.RollbackInfo;
 
 import java.io.File;
 import java.time.Instant;
 import java.util.ArrayList;
-import java.util.List;
 
 /**
  * Information about a rollback available for a set of atomically installed
@@ -29,14 +28,9 @@
  */
 class RollbackData {
     /**
-     * A unique identifier for this rollback.
+     * The rollback info for this rollback.
      */
-    public final int rollbackId;
-
-    /**
-     * The per-package rollback information.
-     */
-    public final List<PackageRollbackInfo> packages = new ArrayList<>();
+    public final RollbackInfo info;
 
     /**
      * The directory where the rollback data is stored.
@@ -69,24 +63,49 @@
     public int apkSessionId = -1;
 
     /**
-     * Whether this Rollback is currently in progress. This field is true from the point
-     * we commit a {@code PackageInstaller} session containing these packages to the point the
-     * {@code PackageInstaller} calls into the {@code onFinished} callback.
+     * True if we are expecting the package manager to call restoreUserData
+     * for this rollback because it has just been committed but the rollback
+     * has not yet been fully applied.
      */
     // NOTE: All accesses to this field are from the RollbackManager handler thread.
-    public boolean inProgress = false;
+    public boolean restoreUserDataInProgress = false;
 
-    RollbackData(int rollbackId, File backupDir, int stagedSessionId, boolean isAvailable) {
-        this.rollbackId = rollbackId;
+    /**
+     * Constructs a new, empty RollbackData instance.
+     *
+     * @param rollbackId the id of the rollback.
+     * @param backupDir the directory where the rollback data is stored.
+     * @param stagedSessionId the session id if this is a staged rollback, -1 otherwise.
+     */
+    RollbackData(int rollbackId, File backupDir, int stagedSessionId) {
+        this.info = new RollbackInfo(rollbackId,
+                /* packages */ new ArrayList<>(),
+                /* isStaged */ stagedSessionId != -1,
+                /* causePackages */ new ArrayList<>(),
+                /* committedSessionId */ -1);
         this.backupDir = backupDir;
         this.stagedSessionId = stagedSessionId;
+        this.isAvailable = (stagedSessionId == -1);
+    }
+
+    /**
+     * Constructs a RollbackData instance with full rollback data information.
+     */
+    RollbackData(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
+            boolean isAvailable, int apkSessionId, boolean restoreUserDataInProgress) {
+        this.info = info;
+        this.backupDir = backupDir;
+        this.timestamp = timestamp;
+        this.stagedSessionId = stagedSessionId;
         this.isAvailable = isAvailable;
+        this.apkSessionId = apkSessionId;
+        this.restoreUserDataInProgress = restoreUserDataInProgress;
     }
 
     /**
      * Whether the rollback is for rollback of a staged install.
      */
     public boolean isStaged() {
-        return stagedSessionId != -1;
+        return info.isStaged();
     }
 }
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 88a5fb4..52d4412 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -243,8 +243,7 @@
             for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
                 RollbackData data = mAvailableRollbacks.get(i);
                 if (data.isAvailable) {
-                    rollbacks.add(new RollbackInfo(data.rollbackId,
-                                data.packages, data.isStaged()));
+                    rollbacks.add(data.info);
                 }
             }
             return new ParceledListSlice<>(rollbacks);
@@ -297,12 +296,12 @@
 
                         data.timestamp = data.timestamp.plusMillis(timeDifference);
                         try {
-                            mRollbackStore.saveAvailableRollback(data);
+                            mRollbackStore.saveRollbackData(data);
                         } catch (IOException ioe) {
                             // TODO: figure out the right way to deal with this, especially if
                             //  it fails for some data and succeeds for others.
-                            Log.e(TAG, "Unable to save rollback info for : " + data.rollbackId,
-                                    ioe);
+                            Log.e(TAG, "Unable to save rollback info for : "
+                                    + data.info.getRollbackId(), ioe);
                         }
                     }
 
@@ -335,7 +334,7 @@
             return;
         }
 
-        if (data.inProgress) {
+        if (data.restoreUserDataInProgress) {
             sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
                     "Rollback for package is already in progress.");
             return;
@@ -349,7 +348,7 @@
         // rollback racing with a roll-forward fix of a buggy package.
         // Figure out how to ensure we don't commit the rollback if
         // roll forward happens at the same time.
-        for (PackageRollbackInfo info : data.packages) {
+        for (PackageRollbackInfo info : data.info.getPackages()) {
             VersionedPackage installedVersion = getInstalledPackageVersion(info.getPackageName());
             if (installedVersion == null) {
                 // TODO: Test this case
@@ -391,7 +390,7 @@
             int parentSessionId = packageInstaller.createSession(parentParams);
             PackageInstaller.Session parentSession = packageInstaller.openSession(parentSessionId);
 
-            for (PackageRollbackInfo info : data.packages) {
+            for (PackageRollbackInfo info : data.info.getPackages()) {
                 PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                         PackageInstaller.SessionParams.MODE_FULL_INSTALL);
                 // TODO: We can't get the installerPackageName for apex
@@ -441,7 +440,7 @@
                         getHandler().post(() -> {
                             // We've now completed the rollback, so we mark it as no longer in
                             // progress.
-                            data.inProgress = false;
+                            data.restoreUserDataInProgress = false;
 
                             int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
                                     PackageInstaller.STATUS_FAILURE);
@@ -453,9 +452,9 @@
                                 return;
                             }
 
-                            addRecentlyExecutedRollback(new RollbackInfo(
-                                        data.rollbackId, data.packages, data.isStaged(),
-                                        causePackages, parentSessionId));
+                            data.info.setCommittedSessionId(parentSessionId);
+                            data.info.getCausePackages().addAll(causePackages);
+                            addRecentlyExecutedRollback(data.info);
                             sendSuccess(statusReceiver);
 
                             Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
@@ -469,7 +468,7 @@
                     }
             );
 
-            data.inProgress = true;
+            data.restoreUserDataInProgress = true;
             parentSession.commit(receiver.getIntentSender());
         } catch (IOException e) {
             Log.e(TAG, "Rollback failed", e);
@@ -510,7 +509,7 @@
             Iterator<RollbackData> iter = mAvailableRollbacks.iterator();
             while (iter.hasNext()) {
                 RollbackData data = iter.next();
-                for (PackageRollbackInfo info : data.packages) {
+                for (PackageRollbackInfo info : data.info.getPackages()) {
                     if (info.getPackageName().equals(packageName)) {
                         iter.remove();
                         deleteRollback(data);
@@ -537,9 +536,10 @@
 
             for (RollbackData rd : changed) {
                 try {
-                    mRollbackStore.saveAvailableRollback(rd);
+                    mRollbackStore.saveRollbackData(rd);
                 } catch (IOException ioe) {
-                    Log.e(TAG, "Unable to save rollback info for : " + rd.rollbackId, ioe);
+                    Log.e(TAG, "Unable to save rollback info for : "
+                            + rd.info.getRollbackId(), ioe);
                 }
             }
 
@@ -575,7 +575,7 @@
             synchronized (mLock) {
                 ensureRollbackDataLoadedLocked();
                 for (RollbackData data : mAvailableRollbacks) {
-                    if (data.stagedSessionId != -1) {
+                    if (!data.isAvailable && data.isStaged()) {
                         staged.add(data);
                     }
                 }
@@ -591,10 +591,10 @@
                             data.isAvailable = true;
                         }
                         try {
-                            mRollbackStore.saveAvailableRollback(data);
+                            mRollbackStore.saveRollbackData(data);
                         } catch (IOException ioe) {
                             Log.e(TAG, "Unable to save rollback info for : "
-                                    + data.rollbackId, ioe);
+                                    + data.info.getRollbackId(), ioe);
                         }
                     } else if (session.isStagedSessionFailed()) {
                         // TODO: Do we need to remove this from
@@ -641,7 +641,7 @@
     private void loadAllRollbackDataLocked() {
         mAvailableRollbacks = mRollbackStore.loadAvailableRollbacks();
         for (RollbackData data : mAvailableRollbacks) {
-            mAllocatedRollbackIds.put(data.rollbackId, true);
+            mAllocatedRollbackIds.put(data.info.getRollbackId(), true);
         }
 
         mRecentlyExecutedRollbacks = mRollbackStore.loadRecentlyExecutedRollbacks();
@@ -665,7 +665,7 @@
             Iterator<RollbackData> iter = mAvailableRollbacks.iterator();
             while (iter.hasNext()) {
                 RollbackData data = iter.next();
-                for (PackageRollbackInfo info : data.packages) {
+                for (PackageRollbackInfo info : data.info.getPackages()) {
                     if (info.getPackageName().equals(packageName)
                             && !packageVersionsEqual(
                                         info.getVersionRolledBackFrom(),
@@ -897,18 +897,19 @@
                 return false;
             }
             String packageName = newPackage.packageName;
-            for (PackageRollbackInfo info : rd.packages) {
+            for (PackageRollbackInfo info : rd.info.getPackages()) {
                 if (info.getPackageName().equals(packageName)) {
                     info.getInstalledUsers().addAll(IntArray.wrap(installedUsers));
-                    mAppDataRollbackHelper.snapshotAppData(rd.rollbackId, info);
+                    mAppDataRollbackHelper.snapshotAppData(rd.info.getRollbackId(), info);
                     try {
-                        mRollbackStore.saveAvailableRollback(rd);
+                        mRollbackStore.saveRollbackData(rd);
                     } catch (IOException ioe) {
                         // TODO: Hopefully this is okay because we will try
                         // again to save the rollback when the staged session
                         // is applied. Just so long as the device doesn't
                         // reboot before then.
-                        Log.e(TAG, "Unable to save rollback info for : " + rd.rollbackId, ioe);
+                        Log.e(TAG, "Unable to save rollback info for : "
+                                + rd.info.getRollbackId(), ioe);
                     }
                     return true;
                 }
@@ -989,14 +990,13 @@
                 if (data == null) {
                     int rollbackId = allocateRollbackIdLocked();
                     if (session.isStaged()) {
-                        data = mRollbackStore.createPendingStagedRollback(rollbackId,
-                            parentSessionId);
+                        data = mRollbackStore.createStagedRollback(rollbackId, parentSessionId);
                     } else {
-                        data = mRollbackStore.createAvailableRollback(rollbackId);
+                        data = mRollbackStore.createNonStagedRollback(rollbackId);
                     }
                     mPendingRollbacks.put(parentSessionId, data);
                 }
-                data.packages.add(info);
+                data.info.getPackages().add(info);
             }
         } catch (IOException e) {
             Log.e(TAG, "Unable to create rollback for " + packageName, e);
@@ -1004,7 +1004,7 @@
         }
 
         if (snapshotUserData && !isApex) {
-            mAppDataRollbackHelper.snapshotAppData(data.rollbackId, info);
+            mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), info);
         }
 
         try {
@@ -1044,7 +1044,7 @@
             return;
         }
 
-        if (!rollbackData.inProgress) {
+        if (!rollbackData.restoreUserDataInProgress) {
             Log.e(TAG, "Request to restore userData for: " + packageName
                     + ", but no rollback in progress.");
             return;
@@ -1053,12 +1053,12 @@
         for (int userId : userIds) {
             final PackageRollbackInfo info = getPackageRollbackInfo(rollbackData, packageName);
             final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData(
-                    rollbackData.rollbackId, info, userId, appId, seInfo);
+                    rollbackData.info.getRollbackId(), info, userId, appId, seInfo);
 
             // We've updated metadata about this rollback, so save it to flash.
             if (changedRollbackData) {
                 try {
-                    mRollbackStore.saveAvailableRollback(rollbackData);
+                    mRollbackStore.saveRollbackData(rollbackData);
                 } catch (IOException ioe) {
                     // TODO(narayan): What is the right thing to do here ? This isn't a fatal
                     // error, since it will only result in us trying to restore data again,
@@ -1137,9 +1137,10 @@
 
             if (rd != null) {
                 try {
-                    mRollbackStore.saveAvailableRollback(rd);
+                    mRollbackStore.saveRollbackData(rd);
                 } catch (IOException ioe) {
-                    Log.e(TAG, "Unable to save rollback info for : " + rd.rollbackId, ioe);
+                    Log.e(TAG, "Unable to save rollback info for : "
+                            + rd.info.getRollbackId(), ioe);
                 }
             }
         });
@@ -1212,7 +1213,7 @@
                 try {
                     data.timestamp = Instant.now();
 
-                    mRollbackStore.saveAvailableRollback(data);
+                    mRollbackStore.saveRollbackData(data);
                     synchronized (mLock) {
                         // Note: There is a small window of time between when
                         // the session has been committed by the package
@@ -1233,8 +1234,8 @@
                     // After enabling and commiting any rollback, observe packages and
                     // prepare to rollback if packages crashes too frequently.
                     List<String> packages = new ArrayList<>();
-                    for (int i = 0; i < data.packages.size(); i++) {
-                        packages.add(data.packages.get(i).getPackageName());
+                    for (int i = 0; i < data.info.getPackages().size(); i++) {
+                        packages.add(data.info.getPackages().get(i).getPackageName());
                     }
                     mPackageHealthObserver.startObservingHealth(packages,
                             mRollbackLifetimeDurationInMillis);
@@ -1307,7 +1308,7 @@
             ensureRollbackDataLoadedLocked();
             for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
                 RollbackData data = mAvailableRollbacks.get(i);
-                if (data.isAvailable && data.rollbackId == rollbackId) {
+                if (data.isAvailable && data.info.getRollbackId() == rollbackId) {
                     return data;
                 }
             }
@@ -1322,7 +1323,7 @@
      */
     private static PackageRollbackInfo getPackageRollbackInfo(RollbackData data,
             String packageName) {
-        for (PackageRollbackInfo info : data.packages) {
+        for (PackageRollbackInfo info : data.info.getPackages()) {
             if (info.getPackageName().equals(packageName)) {
                 return info;
             }
@@ -1347,14 +1348,14 @@
     }
 
     private void deleteRollback(RollbackData rollbackData) {
-        for (PackageRollbackInfo info : rollbackData.packages) {
+        for (PackageRollbackInfo info : rollbackData.info.getPackages()) {
             IntArray installedUsers = info.getInstalledUsers();
             for (int i = 0; i < installedUsers.size(); i++) {
                 int userId = installedUsers.get(i);
-                mAppDataRollbackHelper.destroyAppDataSnapshot(rollbackData.rollbackId, info,
-                        userId);
+                mAppDataRollbackHelper.destroyAppDataSnapshot(rollbackData.info.getRollbackId(),
+                        info, userId);
             }
         }
-        mRollbackStore.deleteAvailableRollback(rollbackData);
+        mRollbackStore.deleteRollbackData(rollbackData);
     }
 }
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index bb4e89e..ecdb2cc 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -183,6 +183,25 @@
         return ceSnapshotInodes;
     }
 
+    private static JSONObject rollbackInfoToJson(RollbackInfo rollback) throws JSONException {
+        JSONObject json = new JSONObject();
+        json.put("rollbackId", rollback.getRollbackId());
+        json.put("packages", toJson(rollback.getPackages()));
+        json.put("isStaged", rollback.isStaged());
+        json.put("causePackages", versionedPackagesToJson(rollback.getCausePackages()));
+        json.put("committedSessionId", rollback.getCommittedSessionId());
+        return json;
+    }
+
+    private static RollbackInfo rollbackInfoFromJson(JSONObject json) throws JSONException {
+        return new RollbackInfo(
+                json.getInt("rollbackId"),
+                packageRollbackInfosFromJson(json.getJSONArray("packages")),
+                json.getBoolean("isStaged"),
+                versionedPackagesFromJson(json.getJSONArray("causePackages")),
+                json.getInt("committedSessionId"));
+    }
+
     /**
      * Reads the list of recently executed rollbacks from persistent storage.
      */
@@ -197,17 +216,7 @@
                 JSONObject object = new JSONObject(jsonString);
                 JSONArray array = object.getJSONArray("recentlyExecuted");
                 for (int i = 0; i < array.length(); ++i) {
-                    JSONObject element = array.getJSONObject(i);
-                    int rollbackId = element.getInt("rollbackId");
-                    List<PackageRollbackInfo> packages = packageRollbackInfosFromJson(
-                            element.getJSONArray("packages"));
-                    boolean isStaged = element.getBoolean("isStaged");
-                    List<VersionedPackage> causePackages = versionedPackagesFromJson(
-                            element.getJSONArray("causePackages"));
-                    int committedSessionId = element.getInt("committedSessionId");
-                    RollbackInfo rollback = new RollbackInfo(rollbackId, packages, isStaged,
-                            causePackages, committedSessionId);
-                    recentlyExecutedRollbacks.add(rollback);
+                    recentlyExecutedRollbacks.add(rollbackInfoFromJson(array.getJSONObject(i)));
                 }
             } catch (IOException | JSONException e) {
                 // TODO: What to do here? Surely we shouldn't just forget about
@@ -220,17 +229,22 @@
     }
 
     /**
-     * Creates a new RollbackData instance with backupDir assigned.
+     * Creates a new RollbackData instance for a non-staged rollback with
+     * backupDir assigned.
      */
-    RollbackData createAvailableRollback(int rollbackId) throws IOException {
+    RollbackData createNonStagedRollback(int rollbackId) throws IOException {
         File backupDir = new File(mAvailableRollbacksDir, Integer.toString(rollbackId));
-        return new RollbackData(rollbackId, backupDir, -1, true);
+        return new RollbackData(rollbackId, backupDir, -1);
     }
 
-    RollbackData createPendingStagedRollback(int rollbackId, int stagedSessionId)
+    /**
+     * Creates a new RollbackData instance for a staged rollback with
+     * backupDir assigned.
+     */
+    RollbackData createStagedRollback(int rollbackId, int stagedSessionId)
             throws IOException {
         File backupDir = new File(mAvailableRollbacksDir, Integer.toString(rollbackId));
-        return new RollbackData(rollbackId, backupDir, stagedSessionId, false);
+        return new RollbackData(rollbackId, backupDir, stagedSessionId);
     }
 
     /**
@@ -263,17 +277,17 @@
     }
 
     /**
-     * Writes the metadata for an available rollback to persistent storage.
+     * Saves the rollback data to persistent storage.
      */
-    void saveAvailableRollback(RollbackData data) throws IOException {
+    void saveRollbackData(RollbackData data) throws IOException {
         try {
             JSONObject dataJson = new JSONObject();
-            dataJson.put("rollbackId", data.rollbackId);
-            dataJson.put("packages", toJson(data.packages));
+            dataJson.put("info", rollbackInfoToJson(data.info));
             dataJson.put("timestamp", data.timestamp.toString());
             dataJson.put("stagedSessionId", data.stagedSessionId);
             dataJson.put("isAvailable", data.isAvailable);
             dataJson.put("apkSessionId", data.apkSessionId);
+            dataJson.put("restoreUserDataInProgress", data.restoreUserDataInProgress);
 
             PrintWriter pw = new PrintWriter(new File(data.backupDir, "rollback.json"));
             pw.println(dataJson.toString());
@@ -284,10 +298,9 @@
     }
 
     /**
-     * Removes all persistant storage associated with the given available
-     * rollback.
+     * Removes all persistant storage associated with the given rollback data.
      */
-    void deleteAvailableRollback(RollbackData data) {
+    void deleteRollbackData(RollbackData data) {
         removeFile(data.backupDir);
     }
 
@@ -302,13 +315,7 @@
 
             for (int i = 0; i < recentlyExecutedRollbacks.size(); ++i) {
                 RollbackInfo rollback = recentlyExecutedRollbacks.get(i);
-                JSONObject element = new JSONObject();
-                element.put("rollbackId", rollback.getRollbackId());
-                element.put("packages", toJson(rollback.getPackages()));
-                element.put("isStaged", rollback.isStaged());
-                element.put("causePackages", versionedPackagesToJson(rollback.getCausePackages()));
-                element.put("committedSessionId", rollback.getCommittedSessionId());
-                array.put(element);
+                array.put(rollbackInfoToJson(rollback));
             }
 
             PrintWriter pw = new PrintWriter(mRecentlyExecutedRollbacksFile);
@@ -324,40 +331,39 @@
      * Reads the metadata for a rollback from the given directory.
      * @throws IOException in case of error reading the data.
      */
-    private RollbackData loadRollbackData(File backupDir) throws IOException {
+    private static RollbackData loadRollbackData(File backupDir) throws IOException {
         try {
             File rollbackJsonFile = new File(backupDir, "rollback.json");
             JSONObject dataJson = new JSONObject(
                     IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath()));
 
-            int rollbackId = dataJson.getInt("rollbackId");
-            int stagedSessionId = dataJson.getInt("stagedSessionId");
-            boolean isAvailable = dataJson.getBoolean("isAvailable");
-            RollbackData data = new RollbackData(rollbackId, backupDir,
-                    stagedSessionId, isAvailable);
-            data.packages.addAll(packageRollbackInfosFromJson(dataJson.getJSONArray("packages")));
-            data.timestamp = Instant.parse(dataJson.getString("timestamp"));
-            data.apkSessionId = dataJson.getInt("apkSessionId");
-            return data;
+            return new RollbackData(
+                    rollbackInfoFromJson(dataJson.getJSONObject("info")),
+                    backupDir,
+                    Instant.parse(dataJson.getString("timestamp")),
+                    dataJson.getInt("stagedSessionId"),
+                    dataJson.getBoolean("isAvailable"),
+                    dataJson.getInt("apkSessionId"),
+                    dataJson.getBoolean("restoreUserDataInProgress"));
         } catch (JSONException | DateTimeParseException e) {
             throw new IOException(e);
         }
     }
 
-    private JSONObject toJson(VersionedPackage pkg) throws JSONException {
+    private static JSONObject toJson(VersionedPackage pkg) throws JSONException {
         JSONObject json = new JSONObject();
         json.put("packageName", pkg.getPackageName());
         json.put("longVersionCode", pkg.getLongVersionCode());
         return json;
     }
 
-    private VersionedPackage versionedPackageFromJson(JSONObject json) throws JSONException {
+    private static VersionedPackage versionedPackageFromJson(JSONObject json) throws JSONException {
         String packageName = json.getString("packageName");
         long longVersionCode = json.getLong("longVersionCode");
         return new VersionedPackage(packageName, longVersionCode);
     }
 
-    private JSONObject toJson(PackageRollbackInfo info) throws JSONException {
+    private static JSONObject toJson(PackageRollbackInfo info) throws JSONException {
         JSONObject json = new JSONObject();
         json.put("versionRolledBackFrom", toJson(info.getVersionRolledBackFrom()));
         json.put("versionRolledBackTo", toJson(info.getVersionRolledBackTo()));
@@ -376,7 +382,8 @@
         return json;
     }
 
-    private PackageRollbackInfo packageRollbackInfoFromJson(JSONObject json) throws JSONException {
+    private static PackageRollbackInfo packageRollbackInfoFromJson(JSONObject json)
+            throws JSONException {
         VersionedPackage versionRolledBackFrom = versionedPackageFromJson(
                 json.getJSONObject("versionRolledBackFrom"));
         VersionedPackage versionRolledBackTo = versionedPackageFromJson(
@@ -397,7 +404,7 @@
                 pendingBackups, pendingRestores, isApex, installedUsers, ceSnapshotInodes);
     }
 
-    private JSONArray versionedPackagesToJson(List<VersionedPackage> packages)
+    private static JSONArray versionedPackagesToJson(List<VersionedPackage> packages)
             throws JSONException {
         JSONArray json = new JSONArray();
         for (VersionedPackage pkg : packages) {
@@ -406,7 +413,8 @@
         return json;
     }
 
-    private List<VersionedPackage> versionedPackagesFromJson(JSONArray json) throws JSONException {
+    private static List<VersionedPackage> versionedPackagesFromJson(JSONArray json)
+            throws JSONException {
         List<VersionedPackage> packages = new ArrayList<>();
         for (int i = 0; i < json.length(); ++i) {
             packages.add(versionedPackageFromJson(json.getJSONObject(i)));
@@ -414,7 +422,7 @@
         return packages;
     }
 
-    private JSONArray toJson(List<PackageRollbackInfo> infos) throws JSONException {
+    private static JSONArray toJson(List<PackageRollbackInfo> infos) throws JSONException {
         JSONArray json = new JSONArray();
         for (PackageRollbackInfo info : infos) {
             json.put(toJson(info));
@@ -422,7 +430,7 @@
         return json;
     }
 
-    private List<PackageRollbackInfo> packageRollbackInfosFromJson(JSONArray json)
+    private static List<PackageRollbackInfo> packageRollbackInfosFromJson(JSONArray json)
             throws JSONException {
         List<PackageRollbackInfo> infos = new ArrayList<>();
         for (int i = 0; i < json.length(); ++i) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index df76030..7ae48a5 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2351,6 +2351,9 @@
                 // Suppress the warning toast if the preferredDisplay was set to singleTask.
                 // The singleTaskInstance displays will only contain one task and any attempt to
                 // launch new task will re-route to the default display.
+                mService.getTaskChangeNotificationController()
+                        .notifyActivityLaunchOnSecondaryDisplayRerouted(task.getTaskInfo(),
+                                preferredDisplayId);
                 return;
             }
 
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 5519729..bbbf11d 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -118,7 +118,8 @@
         anim.scaleCurrentDuration(mAppToken.mWmService.getTransitionAnimationScaleLocked());
         mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
                 new WindowAnimationSpec(anim, position,
-                        mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame()),
+                        mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame(),
+                        mAppToken.mWmService.mWindowCornerRadius),
                 mAppToken.mWmService.mSurfaceAnimationRunner), false /* hidden */);
     }
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index ce5a047..78199d44 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -118,7 +118,7 @@
 import com.android.internal.util.ToBooleanFunction;
 import com.android.server.AttributeCache;
 import com.android.server.LocalServices;
-import com.android.server.display.ColorDisplayService;
+import com.android.server.display.color.ColorDisplayService;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.policy.WindowManagerPolicy.StartingSurface;
 import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
@@ -2548,7 +2548,8 @@
                             new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
                                     getDisplayContent().mAppTransition.canSkipFirstFrame(),
                                     appStackClipMode,
-                                    true /* isAppAnimation */),
+                                    true /* isAppAnimation */,
+                                    mWmService.mWindowCornerRadius),
                             mWmService.mSurfaceAnimationRunner);
                     if (a.getZAdjustment() == Animation.ZORDER_TOP) {
                         mNeedsZBoost = true;
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index feb711a..8c8b05f 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -29,6 +29,7 @@
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
 
+import static com.android.server.am.KeyguardControllerProto.AOD_SHOWING;
 import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
 import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
 import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID;
@@ -86,7 +87,7 @@
 
     /**
      * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
-     *         on the given display, false otherwise
+     *         on the given display, false otherwise.
      */
     boolean isKeyguardOrAodShowing(int displayId) {
         return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
@@ -94,6 +95,16 @@
     }
 
     /**
+     * @return {@code true} if 1) Keyguard is showing, not going away, and not being occluded on the
+     *         given display, or 2) AOD is showing, {@code false} otherwise.
+     * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic.
+     */
+    boolean isKeyguardUnoccludedOrAodShowing(int displayId) {
+        return (mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId))
+                || mAodShowing;
+    }
+
+    /**
      * @return true if Keyguard is showing, not going away, and not being occluded on the given
      *         display, false otherwise
      */
@@ -380,10 +391,11 @@
         for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
              displayNdx >= 0; displayNdx--) {
             final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
-            final KeyguardDisplayState state = getDisplay(display.mDisplayId);
-            if (isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken == null) {
+            final int displayId = display.mDisplayId;
+            final KeyguardDisplayState state = getDisplay(displayId);
+            if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) {
                 state.acquiredSleepToken();
-            } else if (!isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken != null) {
+            } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) {
                 state.releaseSleepToken();
             }
         }
@@ -528,6 +540,7 @@
 
     void writeToProto(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
+        proto.write(AOD_SHOWING, mAodShowing);
         proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
         writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
         proto.end(token);
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 789f987..42d2583 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -50,6 +50,7 @@
     private static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
     private static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
     private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
+    private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG = 19;
 
     // Delay in notifying task stack change listeners (in millis)
     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -130,6 +131,10 @@
         l.onActivityLaunchOnSecondaryDisplayFailed((RunningTaskInfo) m.obj, m.arg1);
     };
 
+    private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayRerouted = (l, m) -> {
+        l.onActivityLaunchOnSecondaryDisplayRerouted((RunningTaskInfo) m.obj, m.arg1);
+    };
+
     private final TaskStackConsumer mNotifyTaskProfileLocked = (l, m) -> {
         l.onTaskProfileLocked(m.arg1, m.arg2);
     };
@@ -202,6 +207,9 @@
                 case NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG:
                     forAllRemoteListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
                     break;
+                case NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG:
+                    forAllRemoteListeners(mNotifyActivityLaunchOnSecondaryDisplayRerouted, msg);
+                    break;
                 case NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG:
                     forAllRemoteListeners(mNotifyTaskProfileLocked, msg);
                     break;
@@ -355,6 +363,15 @@
         msg.sendToTarget();
     }
 
+    void notifyActivityLaunchOnSecondaryDisplayRerouted(TaskInfo ti, int requestedDisplayId) {
+        mHandler.removeMessages(NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG);
+        final Message msg = mHandler.obtainMessage(
+                NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG, requestedDisplayId,
+                0 /* unused */, ti);
+        forAllLocalListeners(mNotifyActivityLaunchOnSecondaryDisplayRerouted, msg);
+        msg.sendToTarget();
+    }
+
     void notifyTaskCreated(int taskId, ComponentName componentName) {
         final Message msg = mHandler.obtainMessage(NOTIFY_TASK_ADDED_LISTENERS_MSG,
                 taskId, 0 /* unused */, componentName);
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index f3050a9..904c503 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -235,8 +235,7 @@
         // STEP 2.3: Adjust launch parameters as needed for freeform display. We enforce the policy
         // that legacy (pre-D) apps and those apps that can't handle multiple screen density well
         // are forced to be maximized. The rest of this step is to define the default policy when
-        // there is no initial bounds or a fully resolved current params from callers. Right now we
-        // launch all possible tasks/activities that can handle freeform into freeform mode.
+        // there is no initial bounds or a fully resolved current params from callers.
         if (display.inFreeformWindowingMode()) {
             if (launchMode == WINDOWING_MODE_PINNED) {
                 if (DEBUG) appendLog("picture-in-picture");
@@ -247,17 +246,6 @@
                 launchMode = WINDOWING_MODE_FULLSCREEN;
                 outParams.mBounds.setEmpty();
                 if (DEBUG) appendLog("forced-maximize");
-            } else if (fullyResolvedCurrentParam) {
-                // Don't adjust launch mode if that's inherited, except when we're launching an
-                // activity that should be forced to maximize.
-                if (DEBUG) appendLog("skip-adjustment-fully-resolved-params");
-            } else if (launchMode != WINDOWING_MODE_FREEFORM
-                    && (isNOrGreater(root) || isPreNResizeable(root))) {
-                // We're launching a pre-N and post-D activity that supports resizing, or a post-N
-                // activity. They can handle freeform nicely so launch them in freeform.
-                // Use undefined because we know we're in a freeform display.
-                launchMode = WINDOWING_MODE_UNDEFINED;
-                if (DEBUG) appendLog("should-be-freeform");
             }
         } else {
             if (DEBUG) appendLog("non-freeform-display");
@@ -441,10 +429,6 @@
         return !root.isResizeable();
     }
 
-    private boolean isNOrGreater(@NonNull ActivityRecord root) {
-        return root.appInfo.targetSdkVersion >= Build.VERSION_CODES.N;
-    }
-
     /**
      * Resolves activity requested orientation to 4 categories:
      * 1) {@link ActivityInfo#SCREEN_ORIENTATION_LOCKED} indicating app wants to lock down
@@ -485,10 +469,6 @@
         return orientation;
     }
 
-    private boolean isPreNResizeable(ActivityRecord root) {
-        return root.appInfo.targetSdkVersion < Build.VERSION_CODES.N && root.isResizeable();
-    }
-
     private void cascadeBounds(@NonNull Rect srcBounds, @NonNull ActivityDisplay display,
             @NonNull Rect outBounds) {
         outBounds.set(srcBounds);
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 98c77ac..57311e1 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -17,10 +17,10 @@
 package com.android.server.wm;
 
 import static com.android.server.wm.AnimationAdapter.STATUS_BAR_TRANSITION_DURATION;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
 import static com.android.server.wm.AnimationSpecProto.WINDOW;
 import static com.android.server.wm.WindowAnimationSpecProto.ANIMATION;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
 
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -51,18 +51,22 @@
     private final Rect mStackBounds = new Rect();
     private int mStackClipMode;
     private final Rect mTmpRect = new Rect();
+    private final float mWindowCornerRadius;
 
-    public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame)  {
+    public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame,
+            float windowCornerRadius)  {
         this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE,
-                false /* isAppAnimation */);
+                false /* isAppAnimation */, windowCornerRadius);
     }
 
     public WindowAnimationSpec(Animation animation, Point position, Rect stackBounds,
-            boolean canSkipFirstFrame, int stackClipMode, boolean isAppAnimation) {
+            boolean canSkipFirstFrame, int stackClipMode, boolean isAppAnimation,
+            float windowCornerRadius) {
         mAnimation = animation;
         if (position != null) {
             mPosition.set(position.x, position.y);
         }
+        mWindowCornerRadius = windowCornerRadius;
         mCanSkipFirstFrame = canSkipFirstFrame;
         mIsAppAnimation = isAppAnimation;
         mStackClipMode = stackClipMode;
@@ -101,6 +105,9 @@
             mTmpRect.intersect(tmp.transformation.getClipRect());
             t.setWindowCrop(leash, mTmpRect);
         }
+        if (mAnimation.hasRoundedCorners() && mWindowCornerRadius > 0) {
+            t.setCornerRadius(leash, mWindowCornerRadius);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 76f080b..05d4760 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1292,6 +1292,7 @@
      * Called when an animation has finished running.
      */
     protected void onAnimationFinished() {
+        mWmService.onAnimationFinished();
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e19c7c6..cbafb3f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -234,6 +234,7 @@
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
+import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.LatencyTracker;
@@ -372,6 +373,8 @@
     private static final int TRANSITION_ANIMATION_SCALE = 1;
     private static final int ANIMATION_DURATION_SCALE = 2;
 
+    private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
+
     final WindowTracing mWindowTracing;
 
     final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -751,24 +754,27 @@
     final DisplayManager mDisplayManager;
     final ActivityTaskManagerService mAtmService;
 
-    // Indicates whether this device supports wide color gamut / HDR rendering
+    /** Corner radius that windows should have in order to match the display. */
+    final float mWindowCornerRadius;
+
+    /** Indicates whether this device supports wide color gamut / HDR rendering */
     private boolean mHasWideColorGamutSupport;
     private boolean mHasHdrSupport;
 
-    // Who is holding the screen on.
+    /** Who is holding the screen on. */
     private Session mHoldingScreenOn;
     private PowerManager.WakeLock mHoldingScreenWakeLock;
 
-    // Whether or not a layout can cause a wake up when theater mode is enabled.
+    /** Whether or not a layout can cause a wake up when theater mode is enabled. */
     boolean mAllowTheaterModeWakeFromLayout;
 
     final TaskPositioningController mTaskPositioningController;
     final DragDropController mDragDropController;
 
-    // For frozen screen animations.
+    /** For frozen screen animations. */
     private int mExitAnimId, mEnterAnimId;
 
-    // The display that the rotation animation is applying to.
+    /** The display that the rotation animation is applying to. */
     private int mFrozenDisplayId;
 
     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
@@ -975,7 +981,7 @@
         mInputManager = inputManager; // Must be before createDisplayContentLocked.
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
         mDisplayWindowSettings = new DisplayWindowSettings(this);
-
+        mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context.getResources());
 
         mTransactionFactory = transactionFactory;
         mTransaction = mTransactionFactory.make();
@@ -7424,13 +7430,38 @@
 
     @Override
     public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
+        waitForAnimationsToComplete();
+
         synchronized (mGlobalLock) {
             mWindowPlacerLocked.performSurfacePlacementIfScheduled();
-            new SurfaceControl.Transaction()
-                    .syncInputWindows()
-                    .apply(true);
         }
 
+        new SurfaceControl.Transaction().syncInputWindows().apply(true);
+
         return mInputManager.injectInputEvent(ev, mode);
     }
+
+    private void waitForAnimationsToComplete() {
+        synchronized (mGlobalLock) {
+            long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS;
+            while (mRoot.isSelfOrChildAnimating() && timeoutRemaining > 0) {
+                long startTime = System.currentTimeMillis();
+                try {
+                    mGlobalLock.wait(timeoutRemaining);
+                } catch (InterruptedException e) {
+                }
+                timeoutRemaining -= (System.currentTimeMillis() - startTime);
+            }
+
+            if (mRoot.isSelfOrChildAnimating()) {
+                Log.w(TAG, "Timed out waiting for animations to complete.");
+            }
+        }
+    }
+
+    void onAnimationFinished() {
+        synchronized (mGlobalLock) {
+            mGlobalLock.notifyAll();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ab1b6ae..b7925f20 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) {
@@ -4454,7 +4458,8 @@
         anim.restrictDuration(MAX_ANIMATION_DURATION);
         anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked());
         final AnimationAdapter adapter = new LocalAnimationAdapter(
-                new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */),
+                new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */,
+                        mWmService.mWindowCornerRadius),
                 mWmService.mSurfaceAnimationRunner);
         startAnimation(mPendingTransaction, adapter);
         commitPendingTransaction();
@@ -4485,6 +4490,7 @@
 
     @Override
     protected void onAnimationFinished() {
+        super.onAnimationFinished();
         mWinAnimator.onAnimationFinished();
     }
 
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/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 03240c0..d39f20c 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -548,12 +548,15 @@
     Return<void> gnssReleaseWakelockCb() override;
     Return<void> gnssRequestTimeCb() override;
     Return<void> gnssRequestLocationCb(const bool independentFromGnss) override;
+
     Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
 
     // New in 1.1
     Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
 
     // New in 2.0
+    Return<void> gnssRequestLocationCb_2_0(const bool independentFromGnss, const bool isUserEmergency)
+            override;
     Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
     Return<void> gnssLocationCb_2_0(const GnssLocation_V2_0& location) override;
 
@@ -713,8 +716,15 @@
 }
 
 Return<void> GnssCallback::gnssRequestLocationCb(const bool independentFromGnss) {
+    return GnssCallback::gnssRequestLocationCb_2_0(independentFromGnss, /* isUserEmergency= */
+            false);
+}
+
+Return<void> GnssCallback::gnssRequestLocationCb_2_0(const bool independentFromGnss, const bool
+        isUserEmergency) {
     JNIEnv* env = getJniEnv();
-    env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss));
+    env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss),
+            boolToJbool(isUserEmergency));
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
 }
@@ -1422,7 +1432,7 @@
     method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
     method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
             "(IIIIILjava/lang/String;Ljava/lang/String;II)V");
-    method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(Z)V");
+    method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(ZZ)V");
     method_requestRefLocation = env->GetMethodID(clazz, "requestRefLocation", "()V");
     method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
     method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()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/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 8d88c5a..512a745 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -89,8 +89,8 @@
 import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.coverage.CoverageService;
 import com.android.server.devicepolicy.DevicePolicyManagerService;
-import com.android.server.display.ColorDisplayService;
 import com.android.server.display.DisplayManagerService;
+import com.android.server.display.color.ColorDisplayService;
 import com.android.server.dreams.DreamManagerService;
 import com.android.server.emergency.EmergencyAffordanceService;
 import com.android.server.gpu.GpuService;
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/display/AppSaturationControllerTest.java b/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java
similarity index 95%
rename from services/tests/servicestests/src/com/android/server/display/AppSaturationControllerTest.java
rename to services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java
index e518844..7c9a81d 100644
--- a/services/tests/servicestests/src/com/android/server/display/AppSaturationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.color;
 
-import static com.android.server.display.AppSaturationController.TRANSLATION_VECTOR;
+import static com.android.server.display.color.AppSaturationController.TRANSLATION_VECTOR;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
@@ -29,7 +29,7 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.server.display.ColorDisplayService.ColorTransformController;
+import com.android.server.display.color.ColorDisplayService.ColorTransformController;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
similarity index 95%
rename from services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
rename to services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
index 01759d2..2f427b0 100644
--- a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.color;
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
@@ -70,7 +70,7 @@
 
     private MockTwilightManager mTwilightManager;
 
-    private ColorDisplayService mColorDisplayService;
+    private ColorDisplayService mCds;
     private ColorDisplayService.BinderService mBinderService;
 
     @BeforeClass
@@ -96,17 +96,17 @@
         mTwilightManager = new MockTwilightManager();
         LocalServices.addService(TwilightManager.class, mTwilightManager);
 
-        mColorDisplayService = new ColorDisplayService(mContext);
-        mBinderService = mColorDisplayService.new BinderService();
+        mCds = new ColorDisplayService(mContext);
+        mBinderService = mCds.new BinderService();
         LocalServices.addService(ColorDisplayService.ColorDisplayServiceInternal.class,
-                        mColorDisplayService.new ColorDisplayServiceInternal());
+                mCds.new ColorDisplayServiceInternal());
     }
 
     @After
     public void tearDown() {
         LocalServices.removeServiceForTest(TwilightManager.class);
 
-        mColorDisplayService = null;
+        mCds = null;
 
         mTwilightManager = null;
 
@@ -1003,7 +1003,7 @@
 
         /* Since we are using FakeSettingsProvider which could not trigger observer change,
          * force an update here.*/
-        mColorDisplayService.updateDisplayWhiteBalanceStatus();
+        mCds.updateDisplayWhiteBalanceStatus();
         assertDwbActive(false);
     }
 
@@ -1015,12 +1015,12 @@
         setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
         setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
 
-        mColorDisplayService.updateDisplayWhiteBalanceStatus();
+        mCds.updateDisplayWhiteBalanceStatus();
         assertDwbActive(false);
 
         /* Disable nightlight */
         setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
-        mColorDisplayService.updateDisplayWhiteBalanceStatus();
+        mCds.updateDisplayWhiteBalanceStatus();
         assertDwbActive(true);
     }
 
@@ -1031,48 +1031,48 @@
         startService();
         mBinderService.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
 
-        mColorDisplayService.updateDisplayWhiteBalanceStatus();
+        mCds.updateDisplayWhiteBalanceStatus();
         assertDwbActive(true);
     }
 
     @Test
     public void displayWhiteBalance_setTemperatureOverMax() {
-        int max = mColorDisplayService.mDisplayWhiteBalanceTintController.mTemperatureMax;
+        int max = mCds.mDisplayWhiteBalanceTintController.mTemperatureMax;
 
         ColorDisplayService.ColorDisplayServiceInternal cdsInternal = LocalServices.getService(
-                        ColorDisplayService.ColorDisplayServiceInternal.class);
-        cdsInternal.setDisplayWhiteBalanceColorTemperature(max+1);
+                ColorDisplayService.ColorDisplayServiceInternal.class);
+        cdsInternal.setDisplayWhiteBalanceColorTemperature(max + 1);
 
         assertWithMessage("Unexpected temperature set")
-                .that(mColorDisplayService.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
+                .that(mCds.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
                 .isEqualTo(max);
     }
 
     @Test
     public void displayWhiteBalance_setTemperatureBelowMin() {
-        int min = mColorDisplayService.mDisplayWhiteBalanceTintController.mTemperatureMin;
+        int min = mCds.mDisplayWhiteBalanceTintController.mTemperatureMin;
 
         ColorDisplayService.ColorDisplayServiceInternal cdsInternal = LocalServices.getService(
-                        ColorDisplayService.ColorDisplayServiceInternal.class);
+                ColorDisplayService.ColorDisplayServiceInternal.class);
         cdsInternal.setDisplayWhiteBalanceColorTemperature(min - 1);
 
         assertWithMessage("Unexpected temperature set")
-                .that(mColorDisplayService.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
+                .that(mCds.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
                 .isEqualTo(min);
     }
 
     @Test
     public void displayWhiteBalance_setValidTemperature() {
-        int min = mColorDisplayService.mDisplayWhiteBalanceTintController.mTemperatureMin;
-        int max = mColorDisplayService.mDisplayWhiteBalanceTintController.mTemperatureMax;
+        int min = mCds.mDisplayWhiteBalanceTintController.mTemperatureMin;
+        int max = mCds.mDisplayWhiteBalanceTintController.mTemperatureMax;
         int valToSet = (min + max) / 2;
 
         ColorDisplayService.ColorDisplayServiceInternal cdsInternal = LocalServices.getService(
-                        ColorDisplayService.ColorDisplayServiceInternal.class);
+                ColorDisplayService.ColorDisplayServiceInternal.class);
         cdsInternal.setDisplayWhiteBalanceColorTemperature(valToSet);
 
         assertWithMessage("Unexpected temperature set")
-                .that(mColorDisplayService.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
+                .that(mCds.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
                 .isEqualTo(valToSet);
     }
 
@@ -1171,14 +1171,14 @@
     }
 
     /**
-     * Convenience method to start {@link #mColorDisplayService}.
+     * Convenience method to start {@link #mCds}.
      */
     private void startService() {
         Secure.putIntForUser(mContext.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, mUserId);
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            mColorDisplayService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
-            mColorDisplayService.onStartUser(mUserId);
+            mCds.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+            mCds.onStartUser(mUserId);
         });
     }
 
@@ -1224,7 +1224,7 @@
      */
     private void assertDwbActive(boolean enabled) {
         assertWithMessage("Incorrect Display White Balance state")
-                .that(mColorDisplayService.mDisplayWhiteBalanceTintController.isActivated())
+                .that(mCds.mDisplayWhiteBalanceTintController.isActivated())
                 .isEqualTo(enabled);
     }
 
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/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
index d848b2d..fc7ccc5 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
@@ -236,20 +236,20 @@
         wasRecentlyRestored.getPendingRestores().add(
                 new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo"));
 
-        RollbackData dataWithPendingBackup = new RollbackData(101, new File("/does/not/exist"), -1,
-                true);
-        dataWithPendingBackup.packages.add(pendingBackup);
+        RollbackData dataWithPendingBackup = new RollbackData(101, new File("/does/not/exist"), -1);
+        dataWithPendingBackup.info.getPackages().add(pendingBackup);
 
         RollbackData dataWithRecentRestore = new RollbackData(17239, new File("/does/not/exist"),
-                -1, true);
-        dataWithRecentRestore.packages.add(wasRecentlyRestored);
+                -1);
+        dataWithRecentRestore.info.getPackages().add(wasRecentlyRestored);
 
         RollbackData dataForDifferentUser = new RollbackData(17239, new File("/does/not/exist"),
-                -1, true);
-        dataForDifferentUser.packages.add(ignoredInfo);
+                -1);
+        dataForDifferentUser.info.getPackages().add(ignoredInfo);
 
         RollbackInfo rollbackInfo = new RollbackInfo(17239,
-                Arrays.asList(pendingRestore, wasRecentlyRestored), false);
+                Arrays.asList(pendingRestore, wasRecentlyRestored), false,
+                new ArrayList<>(), -1);
 
         List<RollbackData> changed = helper.commitPendingBackupAndRestoreForUser(37,
                 Arrays.asList(dataWithPendingBackup, dataWithRecentRestore, dataForDifferentUser),
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index 6cce9f0..c483489 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -213,7 +213,8 @@
         final Animation a = new TranslateAnimation(-10, 10, 0, 0);
         a.initialize(0, 0, 0, 0);
         a.setDuration(50);
-        return new WindowAnimationSpec(a, new Point(0, 0), false /* canSkipFirstFrame */);
+        return new WindowAnimationSpec(a, new Point(0, 0), false /* canSkipFirstFrame */,
+                0 /* windowCornerRadius */);
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index ace179a..cdbb121 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -29,13 +29,11 @@
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
 
 import android.app.ActivityOptions;
 import android.content.pm.ActivityInfo;
@@ -474,6 +472,22 @@
     }
 
     @Test
+    public void testUsesFullscreenWhenRequestedOnFreeformDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
     public void testUsesFreeformByDefaultForPostNApp() {
         final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
                 WINDOWING_MODE_FREEFORM);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
index 9a825e0..897f0a2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -24,6 +24,8 @@
 
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
 
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -56,7 +58,7 @@
         Animation a = createClipRectAnimation(windowCrop, windowCrop);
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
                 mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE,
-                true /* isAppAnimation */);
+                true /* isAppAnimation */, 0 /* windowCornerRadius */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
                 argThat(rect -> rect.equals(windowCrop)));
@@ -66,7 +68,7 @@
     public void testApply_clipAfter() {
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
                 mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM,
-                true /* isAppAnimation */);
+                true /* isAppAnimation */, 0 /* windowCornerRadius */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
     }
@@ -76,8 +78,7 @@
         // Stack bounds is (0, 0, 10, 10) position is (20, 40)
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation,
                 new Point(20, 40), mStackBounds, false /* canSkipFirstFrame */,
-                STACK_CLIP_AFTER_ANIM,
-                true /* isAppAnimation */);
+                STACK_CLIP_AFTER_ANIM, true /* isAppAnimation */, 0 /* windowCornerRadius */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
     }
@@ -87,7 +88,7 @@
         // Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 0, 0)
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
                 mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
-                true /* isAppAnimation */);
+                true /* isAppAnimation */, 0 /* windowCornerRadius */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
                 argThat(rect -> rect.equals(mStackBounds)));
@@ -101,19 +102,32 @@
         a.initialize(0, 0, 0, 0);
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
                 null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
-                true /* isAppAnimation */);
+                true /* isAppAnimation */, 0 /* windowCornerRadius */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
     }
 
     @Test
+    public void testApply_setCornerRadius() {
+        final float windowCornerRadius = 30f;
+        WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
+                mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+                true /* isAppAnimation */, windowCornerRadius);
+        windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
+        verify(mTransaction, never()).setCornerRadius(eq(mSurfaceControl), eq(windowCornerRadius));
+        when(mAnimation.hasRoundedCorners()).thenReturn(true);
+        windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
+        verify(mTransaction).setCornerRadius(eq(mSurfaceControl), eq(windowCornerRadius));
+    }
+
+    @Test
     public void testApply_clipBeforeSmallerAnimationClip() {
         // Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 5, 5)
         Rect windowCrop = new Rect(0, 0, 5, 5);
         Animation a = createClipRectAnimation(windowCrop, windowCrop);
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
                 mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
-                true /* isAppAnimation */);
+                true /* isAppAnimation */, 0 /* windowCornerRadius */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
                 argThat(rect -> rect.equals(windowCrop)));
@@ -126,7 +140,7 @@
         Animation a = createClipRectAnimation(windowCrop, windowCrop);
         WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
                 mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
-                true /* isAppAnimation */);
+                true /* isAppAnimation */, 0 /* windowCornerRadius */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
                 argThat(rect -> rect.equals(mStackBounds)));
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 5030f90..93eea56 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -182,6 +182,7 @@
     /**
      * @see TelecomServiceImpl#getCallState
      */
+    @UnsupportedAppUsage
     int getCallState();
 
     /**
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
index d6a8065..c3387f3 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
@@ -1,5 +1,7 @@
 package android.telephony;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -10,14 +12,17 @@
  * Class that stores information specific to data network registration.
  * @hide
  */
-public class DataSpecificRegistrationStates implements Parcelable{
+@SystemApi
+public final class DataSpecificRegistrationStates implements Parcelable{
     /**
+     * @hide
      * The maximum number of simultaneous Data Calls that
      * must be established using setupDataCall().
      */
     public final int maxDataCalls;
 
     /**
+     * @hide
      * Indicates if the use of dual connectivity with NR is restricted.
      * Reference: 3GPP TS 24.301 v15.03 section 9.3.3.12A.
      */
@@ -25,7 +30,7 @@
 
     /**
      * Indicates if NR is supported by the selected PLMN.
-     *
+     * @hide
      * {@code true} if the bit N is in the PLMN-InfoList-r15 is true and the selected PLMN is
      * present in plmn-IdentityList at position N.
      * Reference: 3GPP TS 36.331 v15.2.2 section 6.3.1 PLMN-InfoList-r15.
@@ -34,6 +39,7 @@
     public final boolean isNrAvailable;
 
     /**
+     * @hide
      * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the primary serving
      * cell.
      *
@@ -47,8 +53,11 @@
     /**
      * Provides network support info for LTE VoPS and LTE Emergency bearer support
      */
-    public final LteVopsSupportInfo lteVopsSupportInfo;
+    private final LteVopsSupportInfo lteVopsSupportInfo;
 
+    /**
+     * @hide
+     */
     DataSpecificRegistrationStates(
             int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable,
             boolean isEnDcAvailable, LteVopsSupportInfo lteVops) {
@@ -126,4 +135,12 @@
                     return new DataSpecificRegistrationStates[size];
                 }
             };
+
+    /**
+     * @return LteVopsSupportInfo
+     */
+    @NonNull
+    public LteVopsSupportInfo getLteVopsSupportInfo() {
+        return lteVopsSupportInfo;
+    }
 }
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index 6e6d59e..84d6628 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -349,7 +349,7 @@
     }
 
     /**
-     * @hide
+     * @return Data registration related info
      */
     @Nullable
     public DataSpecificRegistrationStates getDataSpecificStates() {
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 17acf2b..108af61 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -467,7 +467,7 @@
      * @return group UUID a String of group UUID if it belongs to a group. Otherwise
      * it will return null.
      */
-    public String getGroupUuid() {
+    public @Nullable String getGroupUuid() {
         return mGroupUUID;
     }
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c28d1fb..d6d3a89 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -63,14 +63,17 @@
 import com.android.internal.telephony.ISub;
 import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
@@ -1066,7 +1069,8 @@
      * @param listener that is to be unregistered.
      */
     public void removeOnOpportunisticSubscriptionsChangedListener(
-            OnOpportunisticSubscriptionsChangedListener listener) {
+            @NonNull OnOpportunisticSubscriptionsChangedListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         if (DBG) {
             logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug="
@@ -2682,7 +2686,8 @@
      *  @param callbackIntent pending intent that will be sent after operation is done.
      */
     @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
-    public void switchToSubscription(int subId, PendingIntent callbackIntent) {
+    public void switchToSubscription(int subId, @NonNull PendingIntent callbackIntent) {
+        Preconditions.checkNotNull(callbackIntent, "callbackIntent cannot be null");
         EuiccManager euiccManager = new EuiccManager(mContext);
         euiccManager.switchToSubscription(subId, callbackIntent);
     }
@@ -2900,8 +2905,33 @@
         if (availableList == null) {
             return null;
         } else {
-            return availableList.stream().filter(subInfo -> !shouldHideSubscription(subInfo))
-                    .collect(Collectors.toList());
+            // Multiple subscriptions in a group should only have one representative.
+            // It should be the current active primary subscription if any, or any
+            // primary subscription.
+            List<SubscriptionInfo> selectableList = new ArrayList<>();
+            Map<String, SubscriptionInfo> groupMap = new HashMap<>();
+
+            for (SubscriptionInfo info : availableList) {
+                // Opportunistic subscriptions are considered invisible
+                // to users so they should never be returned.
+                if (isInvisibleSubscription(info)) continue;
+
+                String groupUuid = info.getGroupUuid();
+                if (groupUuid == null) {
+                    // Doesn't belong to any group. Add in the list.
+                    selectableList.add(info);
+                } else if (!groupMap.containsKey(groupUuid)
+                        || (groupMap.get(groupUuid).getSimSlotIndex() == INVALID_SIM_SLOT_INDEX
+                        && info.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX)) {
+                    // If it belongs to a group that has never been recorded or it's the current
+                    // active subscription, add it in the list.
+                    selectableList.remove(groupMap.get(groupUuid));
+                    selectableList.add(info);
+                    groupMap.put(groupUuid, info);
+                }
+
+            }
+            return selectableList;
         }
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c1d1440..31d8ddb 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1366,6 +1366,26 @@
      * Intent sent when an error occurs that debug tools should log and possibly take further
      * action such as capturing vendor-specific logs.
      *
+     * A privileged application that reads these events should take appropriate vendor-specific
+     * action to record the event and collect further information to assist in analysis, debugging,
+     * and resolution of any associated issue.
+     *
+     * <p>This event should not be used for generic logging or diagnostic monitoring purposes and
+     * should generally be sent at a low rate. Instead, this mechanism should be used for the
+     * framework to notify a debugging application that an event (such as a bug) has occured
+     * within the framework if that event should trigger the collection and preservation of other
+     * more detailed device state for debugging.
+     *
+     * <p>At most one application can receive these events and should register a receiver in
+     * in the application manifest. For performance reasons, if no application to receive these
+     * events is detected at boot, then these events will not be sent.
+     *
+     * <p>Each event will include an {@link EXTRA_DEBUG_EVENT_ID} that will uniquely identify the
+     * event that has occurred. Each event will be sent to the diagnostic monitor only once per
+     * boot cycle (as another optimization).
+     *
+     * @see #EXTRA_DEBUG_EVENT_ID
+     * @see #EXTRA_DEBUG_EVENT_DESCRIPTION
      * @hide
      */
     @SystemApi
@@ -1373,21 +1393,23 @@
     public static final String ACTION_DEBUG_EVENT = "android.telephony.action.DEBUG_EVENT";
 
     /**
-     * An arbitrary ParcelUuid which should be consistent for each occurrence of the same event.
+     * An arbitrary ParcelUuid which should be consistent for each occurrence of a DebugEvent.
      *
-     * This field must be included in all events.
+     * This field must be included in all {@link ACTION_DEBUG_EVENT} events.
      *
+     * @see #ACTION_DEBUG_EVENT
      * @hide
      */
     @SystemApi
     public static final String EXTRA_DEBUG_EVENT_ID = "android.telephony.extra.DEBUG_EVENT_ID";
 
     /**
-     * A freeform string description of the event.
+     * A freeform string description of the DebugEvent.
      *
-     * This field is optional for all events and as a guideline should not exceed 80 characters
-     * and should be as short as possible to convey the essence of the event.
+     * This field is optional for all {@link ACTION_DEBUG_EVENT}s, as a guideline should not
+     * exceed 80 characters, and should be as short as possible to convey the essence of the event.
      *
+     * @see #ACTION_DEBUG_EVENT
      * @hide
      */
     @SystemApi
@@ -3227,6 +3249,7 @@
      * the caller does not have adequate permissions for that card.
      */
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @NonNull
     public List<UiccCardInfo> getUiccCardsInfo() {
         try {
             ITelephony telephony = getITelephony();
diff --git a/telephony/java/android/telephony/UiccCardInfo.java b/telephony/java/android/telephony/UiccCardInfo.java
index 0192ffb..d95a499 100644
--- a/telephony/java/android/telephony/UiccCardInfo.java
+++ b/telephony/java/android/telephony/UiccCardInfo.java
@@ -15,6 +15,8 @@
  */
 package android.telephony;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -104,6 +106,7 @@
      * Note that this field may be omitted if the caller does not have the correct permissions
      * (see {@link TelephonyManager#getUiccCardsInfo()}).
      */
+    @Nullable
     public String getEid() {
         if (!mIsEuicc) {
             return null;
@@ -117,6 +120,7 @@
      * Note that this field may be omitted if the caller does not have the correct permissions
      * (see {@link TelephonyManager#getUiccCardsInfo()}).
      */
+    @Nullable
     public String getIccId() {
         return mIccId;
     }
@@ -129,11 +133,12 @@
     }
 
     /**
-     * Returns a copy of the UiccCardinfo with the clears the EID and ICCID set to null. These
-     * values are generally private and require carrier privileges to view.
+     * Returns a copy of the UiccCardinfo with the EID and ICCID set to null. These values are
+     * generally private and require carrier privileges to view.
      *
      * @hide
      */
+    @NonNull
     public UiccCardInfo getUnprivileged() {
         return new UiccCardInfo(mIsEuicc, mCardId, null, null, mSlotIndex, mIsRemovable);
     }
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index eb99d5d..bb85be1 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -139,7 +139,7 @@
                 if (mLocalCallback == null) return;
 
                 Binder.withCleanCallingIdentity(() ->
-                        mExecutor.execute(() -> mLocalCallback.onDeregistered(info)));
+                        mExecutor.execute(() -> mLocalCallback.onUnregistered(info)));
             }
 
             @Override
@@ -199,7 +199,7 @@
          *
          * @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
          */
-        public void onDeregistered(ImsReasonInfo info) {
+        public void onUnregistered(ImsReasonInfo info) {
         }
 
         /**
@@ -485,7 +485,7 @@
      * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL
      * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL
      * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL
-     * @see #setAdvancedCallingSetting(boolean)
+     * @see #setAdvancedCallingSettingEnabled(boolean)
      * @return true if the user's setting for advanced calling is enabled, false otherwise.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -519,9 +519,9 @@
      * @see #isAdvancedCallingSettingEnabled()
      */
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
-    public void setAdvancedCallingSetting(boolean isEnabled) {
+    public void setAdvancedCallingSettingEnabled(boolean isEnabled) {
         try {
-            getITelephony().setAdvancedCallingSetting(mSubId, isEnabled);
+            getITelephony().setAdvancedCallingSettingEnabled(mSubId, isEnabled);
             return;
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
@@ -589,7 +589,7 @@
     /**
      * The user's setting for whether or not they have enabled the "Video Calling" setting.
      * @return true if the user’s “Video Calling” setting is currently enabled.
-     * @see #setVtSetting(boolean)
+     * @see #setVtSettingEnabled(boolean)
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isVtSettingEnabled() {
@@ -605,9 +605,9 @@
      * @see #isVtSettingEnabled()
      */
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
-    public void setVtSetting(boolean isEnabled) {
+    public void setVtSettingEnabled(boolean isEnabled) {
         try {
-            getITelephony().setVtSetting(mSubId, isEnabled);
+            getITelephony().setVtSettingEnabled(mSubId, isEnabled);
             return;
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
@@ -616,7 +616,7 @@
 
     /**
      * @return true if the user's setting for Voice over WiFi is enabled and false if it is not.
-     * @see #setVoWiFiSetting(boolean)
+     * @see #setVoWiFiSettingEnabled(boolean)
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isVoWiFiSettingEnabled() {
@@ -633,9 +633,9 @@
      * @see #isVoWiFiSettingEnabled()
      */
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
-    public void setVoWiFiSetting(boolean isEnabled) {
+    public void setVoWiFiSettingEnabled(boolean isEnabled) {
         try {
-            getITelephony().setVoWiFiSetting(mSubId, isEnabled);
+            getITelephony().setVoWiFiSettingEnabled(mSubId, isEnabled);
             return;
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
@@ -645,7 +645,7 @@
     /**
      * @return true if the user's setting for Voice over WiFi while roaming is enabled, false
      * if disabled.
-     * @see #setVoWiFiRoamingSetting(boolean)
+     * @see #setVoWiFiRoamingSettingEnabled(boolean)
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isVoWiFiRoamingSettingEnabled() {
@@ -663,9 +663,9 @@
      * @see #isVoWiFiRoamingSettingEnabled()
      */
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
-    public void setVoWiFiRoamingSetting(boolean isEnabled) {
+    public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) {
         try {
-            getITelephony().setVoWiFiRoamingSetting(mSubId, isEnabled);
+            getITelephony().setVoWiFiRoamingSettingEnabled(mSubId, isEnabled);
             return;
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
@@ -682,7 +682,7 @@
      * - {@link #WIFI_MODE_WIFI_ONLY}
      * - {@link #WIFI_MODE_CELLULAR_PREFERRED}
      * - {@link #WIFI_MODE_WIFI_PREFERRED}
-     * @see #setVoWiFiSetting(boolean)
+     * @see #setVoWiFiSettingEnabled(boolean)
      */
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setVoWiFiNonPersistent(boolean isCapable, int mode) {
@@ -700,7 +700,7 @@
      * - {@link #WIFI_MODE_WIFI_ONLY}
      * - {@link #WIFI_MODE_CELLULAR_PREFERRED}
      * - {@link #WIFI_MODE_WIFI_PREFERRED}
-     * @see #setVoWiFiSetting(boolean)
+     * @see #setVoWiFiSettingEnabled(boolean)
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public @WiFiCallingMode int getVoWiFiModeSetting() {
@@ -739,7 +739,7 @@
      *     - {@link #WIFI_MODE_WIFI_ONLY}
      *     - {@link #WIFI_MODE_CELLULAR_PREFERRED}
      *     - {@link #WIFI_MODE_WIFI_PREFERRED}
-     * @see #setVoWiFiRoamingSetting(boolean)
+     * @see #setVoWiFiRoamingSettingEnabled(boolean)
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public @WiFiCallingMode int getVoWiFiRoamingModeSetting() {
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
index c90ffc7..c1401272 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
@@ -26,13 +26,17 @@
  */
 interface IMbmsStreamingService
 {
+    @UnsupportedAppUsage
     int initialize(IMbmsStreamingSessionCallback callback, int subId);
 
+    @UnsupportedAppUsage
     int requestUpdateStreamingServices(int subId, in List<String> serviceClasses);
 
+    @UnsupportedAppUsage
     int startStreaming(int subId, String serviceId,
             IStreamingServiceCallback callback);
 
+    @UnsupportedAppUsage
     Uri getPlaybackUri(int subId, String serviceId);
 
     void stopStreaming(int subId, String serviceId);
diff --git a/telephony/java/com/android/ims/ImsConfigListener.aidl b/telephony/java/com/android/ims/ImsConfigListener.aidl
index 64a5015..4f229df 100644
--- a/telephony/java/com/android/ims/ImsConfigListener.aidl
+++ b/telephony/java/com/android/ims/ImsConfigListener.aidl
@@ -47,6 +47,7 @@
      *
      * @return void.
      */
+    @UnsupportedAppUsage
     void onSetFeatureResponse(int feature, int network, int value, int status);
 
     /**
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
index 579369f..b33a9f1 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -34,33 +34,47 @@
     /**
      * Notifies the result of the basic session operation (setup / terminate).
      */
+    @UnsupportedAppUsage
     void callSessionProgressing(in IImsCallSession session, in ImsStreamMediaProfile profile);
+    @UnsupportedAppUsage
     void callSessionStarted(in IImsCallSession session, in ImsCallProfile profile);
+    @UnsupportedAppUsage
     void callSessionStartFailed(in IImsCallSession session, in ImsReasonInfo reasonInfo);
+    @UnsupportedAppUsage
     void callSessionTerminated(in IImsCallSession session, in ImsReasonInfo reasonInfo);
 
     /**
      * Notifies the result of the call hold/resume operation.
      */
+    @UnsupportedAppUsage
     void callSessionHeld(in IImsCallSession session, in ImsCallProfile profile);
+    @UnsupportedAppUsage
     void callSessionHoldFailed(in IImsCallSession session, in ImsReasonInfo reasonInfo);
+    @UnsupportedAppUsage
     void callSessionHoldReceived(in IImsCallSession session, in ImsCallProfile profile);
+    @UnsupportedAppUsage
     void callSessionResumed(in IImsCallSession session, in ImsCallProfile profile);
+    @UnsupportedAppUsage
     void callSessionResumeFailed(in IImsCallSession session, in ImsReasonInfo reasonInfo);
+    @UnsupportedAppUsage
     void callSessionResumeReceived(in IImsCallSession session, in ImsCallProfile profile);
 
     /**
      * Notifies the result of call merge operation.
      */
+    @UnsupportedAppUsage
     void callSessionMergeStarted(in IImsCallSession session,
             in IImsCallSession newSession, in ImsCallProfile profile);
+    @UnsupportedAppUsage
     void callSessionMergeComplete(in IImsCallSession session);
+    @UnsupportedAppUsage
     void callSessionMergeFailed(in IImsCallSession session,
             in ImsReasonInfo reasonInfo);
 
     /**
      * Notifies the result of call upgrade / downgrade or any other call updates.
      */
+    @UnsupportedAppUsage
     void callSessionUpdated(in IImsCallSession session,
             in ImsCallProfile profile);
     void callSessionUpdateFailed(in IImsCallSession session,
@@ -81,7 +95,9 @@
     /**
      * Notifies the result of the participant invitation / removal to/from the conference session.
      */
+    @UnsupportedAppUsage
     void callSessionInviteParticipantsRequestDelivered(in IImsCallSession session);
+    @UnsupportedAppUsage
     void callSessionInviteParticipantsRequestFailed(in IImsCallSession session,
             in ImsReasonInfo reasonInfo);
     void callSessionRemoveParticipantsRequestDelivered(in IImsCallSession session);
@@ -91,6 +107,7 @@
     /**
      * Notifies the changes of the conference info. in the conference session.
      */
+    @UnsupportedAppUsage
     void callSessionConferenceStateUpdated(in IImsCallSession session,
             in ImsConferenceState state);
 
@@ -103,8 +120,10 @@
     /**
      * Notifies of handover information for this call
      */
+    @UnsupportedAppUsage
     void callSessionHandover(in IImsCallSession session,
             in int srcAccessTech, in int targetAccessTech, in ImsReasonInfo reasonInfo);
+    @UnsupportedAppUsage
     void callSessionHandoverFailed(in IImsCallSession session,
             in int srcAccessTech, in int targetAccessTech, in ImsReasonInfo reasonInfo);
     void callSessionMayHandover(in IImsCallSession session,
@@ -118,6 +137,7 @@
      * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO}
      * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
      */
+    @UnsupportedAppUsage
     void callSessionTtyModeReceived(in IImsCallSession session, in int mode);
 
     /**
@@ -126,11 +146,13 @@
      * @param session The call session.
      * @param isMultiParty {@code true} if the session became multiparty, {@code false} otherwise.
      */
+    @UnsupportedAppUsage
     void callSessionMultipartyStateChanged(in IImsCallSession session, in boolean isMultiParty);
 
     /**
      * Notifies the supplementary service information for the current session.
      */
+    @UnsupportedAppUsage
     void callSessionSuppServiceReceived(in IImsCallSession session,
          in ImsSuppServiceNotification suppSrvNotification);
 
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
index 2212109..a7a62a6 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
@@ -32,6 +32,7 @@
      *
      * @deprecated see {@link registrationConnectedWithRadioTech}
      */
+    @UnsupportedAppUsage
     void registrationConnected();
 
     /**
@@ -47,6 +48,7 @@
      * @param imsRadioTech the radio access technology. Valid values are {@code
      * RIL_RADIO_TECHNOLOGY_*} defined in {@link ServiceState}.
      */
+    @UnsupportedAppUsage
     void registrationConnectedWithRadioTech(int imsRadioTech);
 
     /**
@@ -55,12 +57,14 @@
      * @param imsRadioTech the radio access technology. Valid values are {@code
      * RIL_RADIO_TECHNOLOGY_*} defined in {@link ServiceState}.
      */
+    @UnsupportedAppUsage
     void registrationProgressingWithRadioTech(int imsRadioTech);
 
 
     /**
      * Notifies the application when the device is disconnected from the IMS network.
      */
+    @UnsupportedAppUsage
     void registrationDisconnected(in ImsReasonInfo imsReasonInfo);
 
     /**
@@ -94,6 +98,7 @@
      * @param enabledFeatures features enabled as defined in com.android.ims.ImsConfig#FeatureConstants.
      * @param disabledFeatures features disabled as defined in com.android.ims.ImsConfig#FeatureConstants.
      */
+    @UnsupportedAppUsage
     void registrationFeatureCapabilityChanged(int serviceClass,
             in int[] enabledFeatures, in int[] disabledFeatures);
 
@@ -101,11 +106,13 @@
      * Updates the application with the waiting voice message count.
      * @param count The number of waiting voice messages.
      */
+    @UnsupportedAppUsage
     void voiceMessageCountUpdate(int count);
 
     /**
      * Notifies the application when the list of URIs associated with IMS client is updated.
      */
+    @UnsupportedAppUsage
     void registrationAssociatedUriChanged(in Uri[] uris);
 
     /**
@@ -116,5 +123,6 @@
      *         attempted.
      * @param imsReasonInfo Reason for the failure.
      */
+    @UnsupportedAppUsage
     void registrationChangeFailed(in int targetAccessTech, in ImsReasonInfo imsReasonInfo);
 }
diff --git a/telephony/java/com/android/ims/internal/IImsUtListener.aidl b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
index a603cd3..fcb9fb1 100644
--- a/telephony/java/com/android/ims/internal/IImsUtListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
@@ -31,30 +31,37 @@
     /**
      * Notifies the result of the supplementary service configuration udpate.
      */
+    @UnsupportedAppUsage
     void utConfigurationUpdated(in IImsUt ut, int id);
+    @UnsupportedAppUsage
     void utConfigurationUpdateFailed(in IImsUt ut, int id, in ImsReasonInfo error);
 
     /**
      * Notifies the result of the supplementary service configuration query.
      */
+    @UnsupportedAppUsage
     void utConfigurationQueried(in IImsUt ut, int id, in Bundle ssInfo);
+    @UnsupportedAppUsage
     void utConfigurationQueryFailed(in IImsUt ut, int id, in ImsReasonInfo error);
 
     /**
      * Notifies the status of the call barring supplementary service.
      */
+    @UnsupportedAppUsage
     void utConfigurationCallBarringQueried(in IImsUt ut,
             int id, in ImsSsInfo[] cbInfo);
 
     /**
      * Notifies the status of the call forwarding supplementary service.
      */
+    @UnsupportedAppUsage
     void utConfigurationCallForwardQueried(in IImsUt ut,
             int id, in ImsCallForwardInfo[] cfInfo);
 
     /**
      * Notifies the status of the call waiting supplementary service.
      */
+    @UnsupportedAppUsage
     void utConfigurationCallWaitingQueried(in IImsUt ut,
             int id, in ImsSsInfo[] cwInfo);
 
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
index 9499c9f..cf8d637 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
@@ -31,18 +31,25 @@
  * {@hide}
  */
 oneway interface IImsVideoCallCallback {
+    @UnsupportedAppUsage
     void receiveSessionModifyRequest(in VideoProfile videoProfile);
 
+    @UnsupportedAppUsage
     void receiveSessionModifyResponse(int status, in VideoProfile requestedProfile,
         in VideoProfile responseProfile);
 
+    @UnsupportedAppUsage
     void handleCallSessionEvent(int event);
 
+    @UnsupportedAppUsage
     void changePeerDimensions(int width, int height);
 
+    @UnsupportedAppUsage
     void changeCallDataUsage(long dataUsage);
 
+    @UnsupportedAppUsage
     void changeCameraCapabilities(in VideoProfile.CameraCapabilities cameraCapabilities);
 
+    @UnsupportedAppUsage
     void changeVideoQuality(int videoQuality);
 }
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
index 0da27e1..4d20bd6 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
@@ -41,6 +41,7 @@
  * @hide
  */
 oneway interface IImsVideoCallProvider {
+    @UnsupportedAppUsage
     void setCallback(IImsVideoCallCallback callback);
 
     void setCamera(String cameraId, int uid);
diff --git a/telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl b/telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
index 8cb1153..c69d5a9 100644
--- a/telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
+++ b/telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
@@ -29,6 +29,7 @@
      * @param version, version information of the service.
      * @hide
      */
+    @UnsupportedAppUsage
     void getVersionCb(in String version );
 
     /**
@@ -37,6 +38,7 @@
      * @param statusCode, UCE_SUCCESS as service availability.
      * @hide
      */
+    @UnsupportedAppUsage
     void serviceAvailable(in StatusCode statusCode);
 
     /**
@@ -45,6 +47,7 @@
      * @param statusCode, UCE_SUCCESS as service unavailability.
      * @hide
      */
+    @UnsupportedAppUsage
     void serviceUnavailable(in StatusCode statusCode);
 
     /**
@@ -55,6 +58,7 @@
      * @param capInfo, capabilities of the remote entity received.
      * @hide
      */
+    @UnsupportedAppUsage
     void sipResponseReceived( String uri,
                                 in OptionsSipResponse sipResponse, in OptionsCapInfo capInfo);
 
@@ -63,6 +67,7 @@
      * @param cmdStatus, command status of the request placed.
      * @hide
      */
+    @UnsupportedAppUsage
     void cmdStatus(in OptionsCmdStatus cmdStatus);
 
     /**
@@ -73,6 +78,7 @@
      * @param tID, transation of the request received from network.
      * @hide
      */
+    @UnsupportedAppUsage
     void incomingOptions( String uri, in OptionsCapInfo capInfo,
                                             in int tID);
 }
diff --git a/telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl b/telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl
index 839bb55..2e49082 100644
--- a/telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl
+++ b/telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl
@@ -33,6 +33,7 @@
      * @return StatusCode, status of the request placed.
      * @hide
      */
+    @UnsupportedAppUsage
     StatusCode getVersion(int optionsServiceHandle);
 
     /**
@@ -44,6 +45,7 @@
      * The service will fill UceLong.mUceLong with optionsServiceListenerHdl
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode addListener(int optionsServiceHandle, IOptionsListener optionsListener,
                            inout UceLong optionsServiceListenerHdl);
 
@@ -54,6 +56,7 @@
      * @param optionsServiceListenerHdl provided in createOptionsService() or Addlistener().
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode removeListener(int optionsServiceHandle, in UceLong optionsServiceListenerHdl);
 
     /**
@@ -66,6 +69,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode setMyInfo(int optionsServiceHandle , in CapInfo capInfo, int reqUserData);
 
 
@@ -78,6 +82,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode getMyInfo(int optionsServiceHandle , int reqUserdata);
 
     /**
@@ -90,6 +95,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode getContactCap(int optionsServiceHandle , String remoteURI, int reqUserData);
 
 
@@ -103,6 +109,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode getContactListCap(int optionsServiceHandle, in String[] remoteURIList,
                                  int reqUserData);
 
@@ -119,6 +126,7 @@
      * @param bContactInBL, true if the contact is blacklisted, else false.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode responseIncomingOptions(int optionsServiceHandle,  int tId, int sipResponseCode,
                                        String reasonPhrase, in OptionsCapInfo capInfo,
                                        in boolean bContactInBL);
diff --git a/telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl b/telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
index 2ae424f..65e7fc9 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
+++ b/telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
@@ -36,6 +36,7 @@
      * Gets the version of the presence listener implementation.
      * @param version, version information.
      */
+    @UnsupportedAppUsage
     void getVersionCb(in String version );
 
     /**
@@ -43,6 +44,7 @@
      * availability.
      * @param statusCode, UCE_SUCCESS as service availability.
      */
+    @UnsupportedAppUsage
     void serviceAvailable(in StatusCode statusCode);
 
     /**
@@ -50,6 +52,7 @@
      * unavailability.
      * @param statusCode, UCE_SUCCESS as service unAvailability.
      */
+    @UnsupportedAppUsage
     void serviceUnAvailable(in StatusCode statusCode);
 
     /**
@@ -57,12 +60,14 @@
      * publish request.
      * @param publishTrigger, Publish trigger for the network being supported.
      */
+    @UnsupportedAppUsage
     void publishTriggering(in PresPublishTriggerType publishTrigger);
 
     /**
      * Callback function to be invoked to inform the client of the status of an asynchronous call.
      * @param cmdStatus, command status of the request placed.
      */
+    @UnsupportedAppUsage
     void cmdStatus( in PresCmdStatus cmdStatus);
 
     /**
@@ -70,6 +75,7 @@
      * such as PUBLISH or SUBSCRIBE, has been received.
      * @param sipResponse, network response received for the request placed.
      */
+    @UnsupportedAppUsage
     void sipResponseReceived(in PresSipResponse sipResponse);
 
     /**
@@ -78,6 +84,7 @@
      * @param presentityURI, URI of the remote entity the request was placed.
      * @param tupleInfo, array of capability information remote entity supports.
      */
+    @UnsupportedAppUsage
     void capInfoReceived(in String presentityURI,
                          in PresTupleInfo [] tupleInfo);
 
@@ -87,6 +94,7 @@
      * @param rlmiInfo, resource infomation received from network.
      * @param resInfo, array of capabilities received from network for the list of  remore URI.
      */
+    @UnsupportedAppUsage
     void listCapInfoReceived(in PresRlmiInfo rlmiInfo,
                              in PresResInfo [] resInfo);
 
@@ -94,6 +102,7 @@
      * Callback function to be invoked to inform the client when Unpublish message
      * is sent to network.
      */
+    @UnsupportedAppUsage
     void unpublishMessageSent();
 
 }
\ No newline at end of file
diff --git a/telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl b/telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
index fdea6d3..26a3e83 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
+++ b/telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
@@ -33,6 +33,7 @@
      * @param presenceServiceHdl returned in createPresenceService().
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode getVersion(int presenceServiceHdl);
 
     /**
@@ -45,6 +46,7 @@
      *
      * @return StatusCode, status of the request placed
      */
+    @UnsupportedAppUsage
     StatusCode addListener(int presenceServiceHdl, IPresenceListener presenceServiceListener,
                            inout UceLong presenceServiceListenerHdl);
 
@@ -54,6 +56,7 @@
      * @param presenceServiceListenerHdl provided in createPresenceService() or Addlistener().
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode removeListener(int presenceServiceHdl, in UceLong presenceServiceListenerHdl);
 
     /**
@@ -69,6 +72,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode reenableService(int presenceServiceHdl, int userData);
 
     /**
@@ -81,6 +85,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode publishMyCap(int presenceServiceHdl, in PresCapInfo myCapInfo , int userData);
 
     /**
@@ -94,6 +99,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode getContactCap(int presenceServiceHdl , String remoteUri, int userData);
 
     /**
@@ -107,6 +113,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode getContactListCap(int presenceServiceHdl, in String[] remoteUriList, int userData);
 
     /**
@@ -122,6 +129,7 @@
      *                  with original request.
      * @return StatusCode, status of the request placed.
      */
+    @UnsupportedAppUsage
     StatusCode  setNewFeatureTag(int presenceServiceHdl, String featureTag,
                                  in PresServiceInfo serviceInfo, int userData);
 
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl b/telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
index 13707a1..41abf7d 100644
--- a/telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
+++ b/telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
@@ -25,5 +25,6 @@
      * @param serviceStatusValue defined in ImsUceManager
      * @hide
      */
+    @UnsupportedAppUsage
     void setStatus(int serviceStatusValue);
 }
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl b/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
index 1fb8513..ec45371 100644
--- a/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
+++ b/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
@@ -38,6 +38,7 @@
      * Service status is returned in setStatus callback in IUceListener.
      * @hide
      */
+    @UnsupportedAppUsage
     boolean startService(IUceListener uceListener);
 
     /**
@@ -45,6 +46,7 @@
      * @return boolean true if the service stop request is processed successfully, FALSE otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     boolean stopService();
 
 
@@ -54,6 +56,7 @@
      * @return boolean true if service started else false.
      * @hide
      */
+    @UnsupportedAppUsage
     boolean isServiceStarted();
 
     /**
@@ -71,6 +74,7 @@
      *
      * @deprecated This is replaced with new API createOptionsServiceForSubscription()
      */
+    @UnsupportedAppUsage
     int createOptionsService(IOptionsListener optionsListener,
                              inout UceLong optionsServiceListenerHdl);
     /**
@@ -97,6 +101,7 @@
      *        in IOptionsListener
      * @hide
      */
+    @UnsupportedAppUsage
     void destroyOptionsService(int optionsServiceHandle);
 
     /**
@@ -114,6 +119,7 @@
      *
      * @deprecated This is replaced with new API createPresenceServiceForSubscription()
      */
+    @UnsupportedAppUsage
     int createPresenceService(IPresenceListener presenceServiceListener,
                               inout UceLong presenceServiceListenerHdl);
     /**
@@ -141,6 +147,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     void destroyPresenceService(int presenceServiceHdl);
 
 
@@ -152,6 +159,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     boolean getServiceStatus();
 
     /**
@@ -163,6 +171,7 @@
      *
      * @deprecated use API getPresenceServiceForSubscription()
      */
+    @UnsupportedAppUsage
     IPresenceService getPresenceService();
 
     /**
@@ -185,6 +194,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     IOptionsService getOptionsService();
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index 5cd67d9..8e50a8f 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -23,6 +23,7 @@
  */
 interface ICarrierConfigLoader {
 
+    @UnsupportedAppUsage
     PersistableBundle getConfigForSubId(int subId, String callingPackage);
 
     void overrideConfig(int subId, in PersistableBundle overrides);
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index abcb15a..5b509b7 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -60,6 +60,7 @@
     /**
      * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
      */
+    @UnsupportedAppUsage
     String getSubscriberId(String callingPackage);
 
     /**
@@ -75,6 +76,7 @@
     /**
      * Retrieves the serial number of the ICC, if applicable.
      */
+    @UnsupportedAppUsage
     String getIccSerialNumber(String callingPackage);
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index d183837..5c5d44a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -76,6 +76,7 @@
      * @param number the number to be dialed. If null, this
      * would display the Dialer screen with no number pre-filled.
      */
+    @UnsupportedAppUsage
     void dial(String number);
 
     /**
@@ -83,6 +84,7 @@
      * @param callingPackage The package making the call.
      * @param number the number to be called.
      */
+    @UnsupportedAppUsage
     void call(String callingPackage, String number);
 
     /**
@@ -98,6 +100,7 @@
      * @param callingPackage the name of the package making the call.
      * @return returns true if the radio is on.
      */
+    @UnsupportedAppUsage
     boolean isRadioOnForSubscriber(int subId, String callingPackage);
 
     /**
@@ -105,6 +108,7 @@
      * @param pin The pin to check.
      * @return whether the operation was a success.
      */
+    @UnsupportedAppUsage
     boolean supplyPin(String pin);
 
     /**
@@ -182,6 +186,7 @@
      * @param dialString the MMI command to be executed.
      * @return true if MMI command is executed.
      */
+    @UnsupportedAppUsage
     boolean handlePinMmi(String dialString);
 
 
@@ -202,11 +207,13 @@
      * @param subId user preferred subId.
      * @return true if MMI command is executed.
      */
+    @UnsupportedAppUsage
     boolean handlePinMmiForSubscriber(int subId, String dialString);
 
     /**
      * Toggles the radio on or off.
      */
+    @UnsupportedAppUsage
     void toggleRadioOnOff();
 
     /**
@@ -218,6 +225,7 @@
     /**
      * Set the radio to on or off
      */
+    @UnsupportedAppUsage
     boolean setRadio(boolean turnOn);
 
     /**
@@ -234,6 +242,7 @@
     /**
      * Request to update location information in service state
      */
+    @UnsupportedAppUsage
     void updateServiceLocation();
 
     /**
@@ -245,6 +254,7 @@
     /**
      * Enable location update notifications.
      */
+    @UnsupportedAppUsage
     void enableLocationUpdates();
 
     /**
@@ -256,6 +266,7 @@
     /**
      * Disable location update notifications.
      */
+    @UnsupportedAppUsage
     void disableLocationUpdates();
 
     /**
@@ -267,11 +278,13 @@
     /**
      * Allow mobile data connections.
      */
+    @UnsupportedAppUsage
     boolean enableDataConnectivity();
 
     /**
      * Disallow mobile data connections.
      */
+    @UnsupportedAppUsage
     boolean disableDataConnectivity();
 
     /**
@@ -293,6 +306,7 @@
      */
     List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
 
+     @UnsupportedAppUsage
      int getCallState();
 
     /**
@@ -300,7 +314,9 @@
      */
      int getCallStateForSlot(int slotIndex);
 
+     @UnsupportedAppUsage
      int getDataActivity();
+     @UnsupportedAppUsage
      int getDataState();
 
     /**
@@ -308,6 +324,7 @@
      * Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE
      * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
      */
+    @UnsupportedAppUsage
     int getActivePhoneType();
 
     /**
@@ -444,6 +461,7 @@
      * Returns the network type for data transmission
      * Legacy call, permission-free
      */
+    @UnsupportedAppUsage
     int getNetworkType();
 
     /**
@@ -477,6 +495,7 @@
     /**
      * Return true if an ICC card is present
      */
+    @UnsupportedAppUsage
     boolean hasIccCard();
 
     /**
@@ -557,6 +576,7 @@
      *            successful iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
      */
+    @UnsupportedAppUsage
     boolean iccCloseLogicalChannel(int subId, int channel);
 
     /**
@@ -577,6 +597,7 @@
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
      */
+    @UnsupportedAppUsage
     String iccTransmitApduLogicalChannel(int subId, int channel, int cla, int instruction,
             int p1, int p2, int p3, String data);
 
@@ -829,6 +850,7 @@
      *
      * @return true on enabled
      */
+    @UnsupportedAppUsage
     boolean getDataEnabled(int subId);
 
     /**
@@ -1679,7 +1701,7 @@
     /**
      * Modify the user's setting for whether or not 4G LTE is enabled.
      */
-    void setAdvancedCallingSetting(int subId, boolean isEnabled);
+    void setAdvancedCallingSettingEnabled(int subId, boolean isEnabled);
 
     /**
      * return true if the user's setting for VT is enabled for the subscription.
@@ -1689,7 +1711,7 @@
     /**
      * Modify the user's setting for whether or not VT is available for the subscrption specified.
      */
-    void setVtSetting(int subId, boolean isEnabled);
+    void setVtSettingEnabled(int subId, boolean isEnabled);
 
     /**
      * return true if the user's setting for whether or not Voice over WiFi is currently enabled.
@@ -1699,7 +1721,7 @@
     /**
      * sets the user's setting for Voice over WiFi enabled state.
      */
-    void setVoWiFiSetting(int subId, boolean isEnabled);
+    void setVoWiFiSettingEnabled(int subId, boolean isEnabled);
 
     /**
      * return true if the user's setting for Voice over WiFi while roaming is enabled.
@@ -1710,7 +1732,7 @@
      * Sets the user's preference for whether or not Voice over WiFi is enabled for the current
      * subscription while roaming.
      */
-    void setVoWiFiRoamingSetting(int subId, boolean isEnabled);
+    void setVoWiFiRoamingSettingEnabled(int subId, boolean isEnabled);
 
     /**
      * Set the Voice over WiFi enabled state, but do not persist the setting.
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 6de608e..0610c5d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -38,9 +38,11 @@
             IOnSubscriptionsChangedListener callback);
     void removeOnSubscriptionsChangedListener(String pkg,
             IOnSubscriptionsChangedListener callback);
+    @UnsupportedAppUsage
     void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
     void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events,
             boolean notifyNow);
+    @UnsupportedAppUsage
     void notifyCallState(int state, String incomingNumber);
     void notifyCallStateForPhoneId(in int phoneId, in int subId, int state, String incomingNumber);
     void notifyServiceStateForPhoneId(in int phoneId, in int subId, in ServiceState state);
@@ -57,11 +59,13 @@
     void notifyDataConnectionForSubscriber(int subId, int state, boolean isDataConnectivityPossible,
             String apn, String apnType, in LinkProperties linkProperties,
             in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
+    @UnsupportedAppUsage
     void notifyDataConnectionFailed(String apnType);
     void notifyDataConnectionFailedForSubscriber(int subId, String apnType);
     void notifyCellLocation(in Bundle cellLocation);
     void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
     void notifyOtaspChanged(in int otaspMode);
+    @UnsupportedAppUsage
     void notifyCellInfo(in List<CellInfo> cellInfo);
     void notifyPhysicalChannelConfiguration(in List<PhysicalChannelConfig> configs);
     void notifyPhysicalChannelConfigurationForSubscriber(in int subId,
diff --git a/telephony/java/com/android/internal/telephony/IWapPushManager.aidl b/telephony/java/com/android/internal/telephony/IWapPushManager.aidl
index d5ecb94..1c3df65 100644
--- a/telephony/java/com/android/internal/telephony/IWapPushManager.aidl
+++ b/telephony/java/com/android/internal/telephony/IWapPushManager.aidl
@@ -30,6 +30,7 @@
      * Returns true if inserting the information is successfull. Inserting the duplicated
      * record in the application ID table is not allowed. Use update/delete method.
      */
+    @UnsupportedAppUsage
     boolean addPackage(String x_app_id, String content_type,
             String package_name, String class_name,
             int app_type, boolean need_signature, boolean further_processing);
@@ -38,6 +39,7 @@
      * Updates receiver application that is last added.
      * Returns true if updating the information is successfull.
      */
+    @UnsupportedAppUsage
     boolean updatePackage(String x_app_id, String content_type,
             String package_name, String class_name,
             int app_type, boolean need_signature, boolean further_processing);
@@ -46,6 +48,7 @@
      * Delites receiver application information.
      * Returns true if deleting is successfull.
      */
+    @UnsupportedAppUsage
     boolean deletePackage(String x_app_id, String content_type,
                             String package_name, String class_name);
 }
diff --git a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
index 8ef15d8..4f9aeea 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
+++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
@@ -235,6 +235,34 @@
     }
 
     @Test
+    public void testGeneratesEvents_spoofed_validFile_untrustedApp() throws Exception {
+        File privateCopyFile = privateFile("spoofed2");
+
+        String expectedContentHash = copyAndHashResource(
+                "/DynamicCodeLoggerNativeExecutable", privateCopyFile);
+
+        EventLog.writeEvent(EventLog.getTagCode("auditd"),
+                "type=1400 avc: granted { execute_no_trans } "
+                        + "path=\"" + privateCopyFile + "\" "
+                        + "scontext=u:r:untrusted_app: "
+                        + "tcontext=u:object_r:app_data_file: "
+                        + "tclass=file ");
+
+        String expectedNameHash =
+                "3E57AA59249154C391316FDCF07C1D499C26A564E4D305833CCD9A98ED895AC9";
+
+        // Run the job to scan generated audit log entries
+        runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
+
+        // And then make sure we log events about it
+        long previousEventNanos = mostRecentEventTimeNanos();
+        runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
+
+        assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG,
+                expectedNameHash, expectedContentHash);
+    }
+
+    @Test
     public void testGeneratesEvents_spoofed_pathTraversal() throws Exception {
         File privateDir = privateFile("x").getParentFile();
 
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index ed524f6..129416f 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -17,10 +17,10 @@
 package com.android.server;
 
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.NETID_UNSET;
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
-import static android.net.ConnectivityManager.NETID_UNSET;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
@@ -1828,6 +1828,12 @@
                     fn.test((NetworkCapabilities) cbi.arg));
         }
 
+        void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
+            CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
+            assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
+                    fn.test((LinkProperties) cbi.arg));
+        }
+
         void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
             CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
             boolean actualBlocked = (boolean) cbi.arg;
@@ -5176,6 +5182,9 @@
     public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
+        final String kNat64PrefixString = "2001:db8:64:64:64:64::";
+        final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
+
         final NetworkRequest networkRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_CELLULAR)
                 .addCapability(NET_CAPABILITY_INTERNET)
@@ -5183,8 +5192,9 @@
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
         mCm.registerNetworkCallback(networkRequest, networkCallback);
 
-        // Prepare ipv6 only link properties and connect.
+        // Prepare ipv6 only link properties.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        final int cellNetId = mCellNetworkAgent.getNetwork().netId;
         final LinkProperties cellLp = new LinkProperties();
         cellLp.setInterfaceName(MOBILE_IFNAME);
         cellLp.addLinkAddress(myIpv6);
@@ -5194,15 +5204,44 @@
         when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
                 .thenReturn(getClatInterfaceConfig(myIpv4));
 
-        // Connect with ipv6 link properties, then expect clat setup ipv4 and update link
-        // properties properly.
+        // Connect with ipv6 link properties. Expect prefix discovery to be started.
         mCellNetworkAgent.sendLinkProperties(cellLp);
         mCellNetworkAgent.connect(true);
         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME);
-        Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
+        verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
 
-        // Clat iface up, expect stack link updated.
+        // Switching default network updates TCP buffer sizes.
+        verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
+
+        // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
+        // the NAT64 prefix was removed because one was never discovered.
+        cellLp.addLinkAddress(myIpv4);
+        mCellNetworkAgent.sendLinkProperties(cellLp);
+        networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+        verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
+
+        verifyNoMoreInteractions(mMockNetd);
+        reset(mMockNetd);
+
+        // Remove IPv4 address. Expect prefix discovery to be started again.
+        cellLp.removeLinkAddress(myIpv4);
+        cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
+        mCellNetworkAgent.sendLinkProperties(cellLp);
+        networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+        verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
+
+        // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
+        Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
+        assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
+        mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
+                kNat64PrefixString, 96);
+        LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
+                CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
+        assertEquals(0, lpBeforeClat.getStackedLinks().size());
+        assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
+        verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
+
+        // Clat iface comes up. Expect stacked link to be added.
         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
@@ -5219,20 +5258,66 @@
         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
 
-        // Add ipv4 address, expect stacked linkproperties be cleaned up
+        // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
+        // linkproperties are cleaned up.
         cellLp.addLinkAddress(myIpv4);
         cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
         mCellNetworkAgent.sendLinkProperties(cellLp);
         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
+        verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
 
-        // Clat iface removed, expect linkproperties revert to original one
-        clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
+        // As soon as stop is called, the linkproperties lose the stacked interface.
         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
-        assertEquals(cellLp, actualLpAfterIpv4);
+        LinkProperties expected = new LinkProperties(cellLp);
+        expected.setNat64Prefix(kNat64Prefix);
+        assertEquals(expected, actualLpAfterIpv4);
+        assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
 
-        // Clean up
+        // The interface removed callback happens but has no effect after stop is called.
+        clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
+        networkCallback.assertNoCallback();
+
+        verifyNoMoreInteractions(mMockNetd);
+        reset(mMockNetd);
+
+        // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
+        mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
+                kNat64PrefixString, 96);
+        networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
+                mCellNetworkAgent);
+
+        // Remove IPv4 address and expect prefix discovery and clatd to be started again.
+        cellLp.removeLinkAddress(myIpv4);
+        cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
+        cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
+        mCellNetworkAgent.sendLinkProperties(cellLp);
+        networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+        verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
+        mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
+                kNat64PrefixString, 96);
+        networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+        verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
+
+
+        // Clat iface comes up. Expect stacked link to be added.
+        clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
+        networkCallback.expectLinkPropertiesLike(
+                (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
+                mCellNetworkAgent);
+
+        // NAT64 prefix is removed. Expect that clat is stopped.
+        mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
+                kNat64PrefixString, 96);
+        networkCallback.expectLinkPropertiesLike(
+                (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
+                mCellNetworkAgent);
+        verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
+        networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
+                mCellNetworkAgent);
+
+        // Clean up.
         mCellNetworkAgent.disconnect();
         networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
         networkCallback.assertNoCallback();
@@ -5313,30 +5398,34 @@
         mCm.unregisterNetworkCallback(networkCallback);
     }
 
-    private static final String TEST_TCP_BUFFER_SIZES = "1,2,3,4,5,6";
-
-    private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
+    private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
         String[] values = tcpBufferSizes.split(",");
         String rmemValues = String.join(" ", values[0], values[1], values[2]);
         String wmemValues = String.join(" ", values[3], values[4], values[5]);
         waitForIdle();
-        verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
+        try {
+            verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
+        } catch (RemoteException e) {
+            fail("mMockNetd should never throw RemoteException");
+        }
         reset(mMockNetd);
     }
 
     @Test
-    public void testTcpBufferReset() throws Exception {
+    public void testTcpBufferReset() {
+        final String testTcpBufferSizes = "1,2,3,4,5,6";
+
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         reset(mMockNetd);
-        // Simple connection should have updated tcp buffer size.
+        // Switching default network updates TCP buffer sizes.
         mCellNetworkAgent.connect(false);
         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
 
         // Change link Properties should have updated tcp buffer size.
         LinkProperties lp = new LinkProperties();
-        lp.setTcpBufferSizes(TEST_TCP_BUFFER_SIZES);
+        lp.setTcpBufferSizes(testTcpBufferSizes);
         mCellNetworkAgent.sendLinkProperties(lp);
-        verifyTcpBufferSizeChange(TEST_TCP_BUFFER_SIZES);
+        verifyTcpBufferSizeChange(testTcpBufferSizes);
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index 07b1d05..37c0df8 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -16,9 +16,11 @@
 
 package com.android.server.connectivity;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -27,6 +29,7 @@
 import android.net.ConnectivityManager;
 import android.net.INetd;
 import android.net.InterfaceConfiguration;
+import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
@@ -43,6 +46,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -53,6 +57,8 @@
     static final String BASE_IFACE = "test0";
     static final String STACKED_IFACE = "v4-test0";
     static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29");
+    static final String NAT64_PREFIX = "64:ff9b::/96";
+    static final int NETID = 42;
 
     @Mock ConnectivityService mConnectivity;
     @Mock NetworkMisc mMisc;
@@ -65,7 +71,11 @@
     Handler mHandler;
 
     Nat464Xlat makeNat464Xlat() {
-        return new Nat464Xlat(mNai, mNetd, mNms);
+        return new Nat464Xlat(mNai, mNetd, mNms) {
+            @Override protected int getNetId() {
+                return NETID;
+            }
+        };
     }
 
     @Before
@@ -87,6 +97,24 @@
         when(mConfig.getLinkAddress()).thenReturn(ADDR);
     }
 
+    private void assertRequiresClat(boolean expected, NetworkAgentInfo nai) {
+        String msg = String.format("requiresClat expected %b for type=%d state=%s skip=%b "
+                + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(),
+                nai.networkInfo.getDetailedState(),
+                mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(),
+                nai.linkProperties.getLinkAddresses());
+        assertEquals(msg, expected, Nat464Xlat.requiresClat(nai));
+    }
+
+    private void assertShouldStartClat(boolean expected, NetworkAgentInfo nai) {
+        String msg = String.format("shouldStartClat expected %b for type=%d state=%s skip=%b "
+                + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(),
+                nai.networkInfo.getDetailedState(),
+                mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(),
+                nai.linkProperties.getLinkAddresses());
+        assertEquals(msg, expected, Nat464Xlat.shouldStartClat(nai));
+    }
+
     @Test
     public void testRequiresClat() throws Exception {
         final int[] supportedTypes = {
@@ -102,20 +130,45 @@
             NetworkInfo.DetailedState.SUSPENDED,
         };
 
+        LinkProperties oldLp = new LinkProperties(mNai.linkProperties);
         for (int type : supportedTypes) {
             mNai.networkInfo.setType(type);
             for (NetworkInfo.DetailedState state : supportedDetailedStates) {
                 mNai.networkInfo.setDetailedState(state, "reason", "extraInfo");
-                String msg = String.format("requiresClat expected for type=%d state=%s",
-                        type, state);
+
+                mNai.linkProperties.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
+                assertRequiresClat(false, mNai);
+                assertShouldStartClat(false, mNai);
+
+                mNai.linkProperties.addLinkAddress(new LinkAddress("fc00::1/64"));
+                assertRequiresClat(false, mNai);
+                assertShouldStartClat(false, mNai);
+
+                mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64"));
+                assertRequiresClat(true, mNai);
+                assertShouldStartClat(true, mNai);
 
                 mMisc.skip464xlat = true;
-                String errorMsg = msg + String.format(" skip464xlat=%b", mMisc.skip464xlat);
-                assertFalse(errorMsg, Nat464Xlat.requiresClat(mNai));
+                assertRequiresClat(false, mNai);
+                assertShouldStartClat(false, mNai);
 
                 mMisc.skip464xlat = false;
-                errorMsg = msg + String.format(" skip464xlat=%b", mMisc.skip464xlat);
-                assertTrue(errorMsg, Nat464Xlat.requiresClat(mNai));
+                assertRequiresClat(true, mNai);
+                assertShouldStartClat(true, mNai);
+
+                mNai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.2/24"));
+                assertRequiresClat(false, mNai);
+                assertShouldStartClat(false, mNai);
+
+                mNai.linkProperties.removeLinkAddress(new LinkAddress("192.0.2.2/24"));
+                assertRequiresClat(true, mNai);
+                assertShouldStartClat(true, mNai);
+
+                mNai.linkProperties.setNat64Prefix(null);
+                assertRequiresClat(true, mNai);
+                assertShouldStartClat(false, mNai);
+
+                mNai.linkProperties = new LinkProperties(oldLp);
             }
         }
     }
@@ -125,11 +178,13 @@
         Nat464Xlat nat = makeNat464Xlat();
         ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
 
-        // ConnectivityService starts clat.
+        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+
+        // Start clat.
         nat.start();
 
         verify(mNms).registerObserver(eq(nat));
-        verify(mNetd).clatdStart(eq(BASE_IFACE));
+        verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
 
         // Stacked interface up notification arrives.
         nat.interfaceLinkStateChanged(STACKED_IFACE, true);
@@ -141,22 +196,109 @@
         assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
         assertRunning(nat);
 
-        // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...).
+        // Stop clat (Network disconnects, IPv4 addr appears, ...).
         nat.stop();
 
         verify(mNetd).clatdStop(eq(BASE_IFACE));
+        verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
+        verify(mNms).unregisterObserver(eq(nat));
+        assertTrue(c.getValue().getStackedLinks().isEmpty());
+        assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+        verify(mNetd).resolverStopPrefix64Discovery(eq(NETID));
+        assertIdle(nat);
 
-        // Stacked interface removed notification arrives.
+        // Stacked interface removed notification arrives and is ignored.
         nat.interfaceRemoved(STACKED_IFACE);
         mLooper.dispatchNext();
 
-        verify(mNms).unregisterObserver(eq(nat));
-        verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
+        verifyNoMoreInteractions(mNetd, mNms, mConnectivity);
+    }
+
+    private void checkStartStopStart(boolean interfaceRemovedFirst) throws Exception {
+        Nat464Xlat nat = makeNat464Xlat();
+        ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
+        InOrder inOrder = inOrder(mNetd, mConnectivity);
+
+        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+
+        nat.start();
+
+        inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
+
+        // Stacked interface up notification arrives.
+        nat.interfaceLinkStateChanged(STACKED_IFACE, true);
+        mLooper.dispatchNext();
+
+        inOrder.verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture());
+        assertFalse(c.getValue().getStackedLinks().isEmpty());
+        assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+        assertRunning(nat);
+
+        // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...).
+        nat.stop();
+
+        inOrder.verify(mNetd).clatdStop(eq(BASE_IFACE));
+
+        inOrder.verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture());
         assertTrue(c.getValue().getStackedLinks().isEmpty());
         assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
         assertIdle(nat);
 
-        verifyNoMoreInteractions(mNetd, mNms, mConnectivity);
+        if (interfaceRemovedFirst) {
+            // Stacked interface removed notification arrives and is ignored.
+            nat.interfaceRemoved(STACKED_IFACE);
+            mLooper.dispatchNext();
+            nat.interfaceLinkStateChanged(STACKED_IFACE, false);
+            mLooper.dispatchNext();
+        }
+
+        assertTrue(c.getValue().getStackedLinks().isEmpty());
+        assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+        assertIdle(nat);
+        inOrder.verifyNoMoreInteractions();
+
+        nat.start();
+
+        inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
+
+        if (!interfaceRemovedFirst) {
+            // Stacked interface removed notification arrives and is ignored.
+            nat.interfaceRemoved(STACKED_IFACE);
+            mLooper.dispatchNext();
+            nat.interfaceLinkStateChanged(STACKED_IFACE, false);
+            mLooper.dispatchNext();
+        }
+
+        // Stacked interface up notification arrives.
+        nat.interfaceLinkStateChanged(STACKED_IFACE, true);
+        mLooper.dispatchNext();
+
+        inOrder.verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture());
+        assertFalse(c.getValue().getStackedLinks().isEmpty());
+        assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+        assertRunning(nat);
+
+        // ConnectivityService stops clat again.
+        nat.stop();
+
+        inOrder.verify(mNetd).clatdStop(eq(BASE_IFACE));
+
+        inOrder.verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture());
+        assertTrue(c.getValue().getStackedLinks().isEmpty());
+        assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+        assertIdle(nat);
+
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testStartStopStart() throws Exception {
+        checkStartStopStart(true);
+    }
+
+    @Test
+    public void testStartStopStartBeforeInterfaceRemoved() throws Exception {
+        checkStartStopStart(false);
     }
 
     @Test
@@ -164,11 +306,12 @@
         Nat464Xlat nat = makeNat464Xlat();
         ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
 
-        // ConnectivityService starts clat.
+        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+
         nat.start();
 
         verify(mNms).registerObserver(eq(nat));
-        verify(mNetd).clatdStart(eq(BASE_IFACE));
+        verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
 
         // Stacked interface up notification arrives.
         nat.interfaceLinkStateChanged(STACKED_IFACE, true);
@@ -184,9 +327,10 @@
         nat.interfaceRemoved(STACKED_IFACE);
         mLooper.dispatchNext();
 
-        verify(mNms).unregisterObserver(eq(nat));
         verify(mNetd).clatdStop(eq(BASE_IFACE));
         verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
+        verify(mNms).unregisterObserver(eq(nat));
+        verify(mNetd).resolverStopPrefix64Discovery(eq(NETID));
         assertTrue(c.getValue().getStackedLinks().isEmpty());
         assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
         assertIdle(nat);
@@ -201,24 +345,25 @@
     public void testStopBeforeClatdStarts() throws Exception {
         Nat464Xlat nat = makeNat464Xlat();
 
-        // ConnectivityService starts clat.
+        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+
         nat.start();
 
         verify(mNms).registerObserver(eq(nat));
-        verify(mNetd).clatdStart(eq(BASE_IFACE));
+        verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
 
         // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
         nat.stop();
 
-        verify(mNms).unregisterObserver(eq(nat));
         verify(mNetd).clatdStop(eq(BASE_IFACE));
+        verify(mNms).unregisterObserver(eq(nat));
+        verify(mNetd).resolverStopPrefix64Discovery(eq(NETID));
         assertIdle(nat);
 
         // In-flight interface up notification arrives: no-op
         nat.interfaceLinkStateChanged(STACKED_IFACE, true);
         mLooper.dispatchNext();
 
-
         // Interface removed notification arrives after stopClatd() takes effect: no-op.
         nat.interfaceRemoved(STACKED_IFACE);
         mLooper.dispatchNext();
@@ -232,17 +377,19 @@
     public void testStopAndClatdNeverStarts() throws Exception {
         Nat464Xlat nat = makeNat464Xlat();
 
-        // ConnectivityService starts clat.
+        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+
         nat.start();
 
         verify(mNms).registerObserver(eq(nat));
-        verify(mNetd).clatdStart(eq(BASE_IFACE));
+        verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX));
 
         // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
         nat.stop();
 
-        verify(mNms).unregisterObserver(eq(nat));
         verify(mNetd).clatdStop(eq(BASE_IFACE));
+        verify(mNms).unregisterObserver(eq(nat));
+        verify(mNetd).resolverStopPrefix64Discovery(eq(NETID));
         assertIdle(nat);
 
         verifyNoMoreInteractions(mNetd, mNms, mConnectivity);
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 59e89f5..295e3de 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -79,6 +79,7 @@
                 self.value = raw[3].strip(';"')
             else:
                 self.value = None
+            self.annotations = []
 
         self.ident = "-".join((self.typ, self.name, self.value or ""))
 
@@ -88,6 +89,18 @@
     def __repr__(self):
         return self.raw
 
+
+class Argument(object):
+
+    __slots__ = ["type", "annotations", "name", "default"]
+
+    def __init__(self, type):
+        self.type = type
+        self.annotations = []
+        self.name = None
+        self.default = None
+
+
 class Method():
     def __init__(self, clazz, line, raw, blame, sig_format = 1):
         self.clazz = clazz
@@ -118,21 +131,24 @@
             self.name = raw[1]
 
             # parse args
-            self.args = []
+            self.detailed_args = []
             for arg in re.split(",\s*", raw_args):
                 arg = re.split("\s", arg)
                 # ignore annotations for now
                 arg = [ a for a in arg if not a.startswith("@") ]
                 if len(arg[0]) > 0:
-                    self.args.append(arg[0])
+                    self.detailed_args.append(Argument(arg[0]))
 
             # parse throws
             self.throws = []
             for throw in re.split(",\s*", raw_throws):
                 self.throws.append(throw)
+
+            self.annotations = []
         else:
             raise ValueError("Unknown signature format: " + sig_format)
 
+        self.args = map(lambda a: a.type, self.detailed_args)
         self.ident = "-".join((self.typ, self.name, "-".join(self.args)))
 
     def sig_matches(self, typ, name, args):
@@ -208,13 +224,14 @@
 
 
 class Package():
+    NAME = re.compile("package(?: .*)? ([A-Za-z.]+)")
+
     def __init__(self, line, raw, blame):
         self.line = line
         self.raw = raw.strip(" {;")
         self.blame = blame
 
-        raw = raw.split()
-        self.name = raw[raw.index("package")+1]
+        self.name = Package.NAME.match(raw).group(1)
         self.name_path = self.name.split(".")
 
     def __repr__(self):
@@ -311,10 +328,10 @@
         method.split = []
         kind = self.parse_one_of("ctor", "method")
         method.split.append(kind)
-        annotations = self.parse_annotations()
+        method.annotations = self.parse_annotations()
         method.split.extend(self.parse_modifiers())
         self.parse_matching_paren("<", ">")
-        if "@Deprecated" in annotations:
+        if "@Deprecated" in method.annotations:
             method.split.append("deprecated")
         if kind == "ctor":
             method.typ = "ctor"
@@ -324,7 +341,7 @@
         method.name = self.parse_name()
         method.split.append(method.name)
         self.parse_token("(")
-        method.args = self.parse_args()
+        method.detailed_args = self.parse_args()
         self.parse_token(")")
         method.throws = self.parse_throws()
         if "@interface" in method.clazz.split:
@@ -359,8 +376,8 @@
     def parse_into_field(self, field):
         kind = self.parse_one_of(*V2LineParser.FIELD_KINDS)
         field.split = [kind]
-        annotations = self.parse_annotations()
-        if "@Deprecated" in annotations:
+        field.annotations = self.parse_annotations()
+        if "@Deprecated" in field.annotations:
             field.split.append("deprecated")
         field.split.extend(self.parse_modifiers())
         field.typ = self.parse_type()
@@ -487,15 +504,16 @@
 
     def parse_arg(self):
         self.parse_if("vararg")  # kotlin vararg
-        self.parse_annotations()
-        type = self.parse_arg_type()
+        annotations = self.parse_annotations()
+        arg = Argument(self.parse_arg_type())
+        arg.annotations = annotations
         l = self.lookahead()
         if l != "," and l != ")":
             if self.lookahead() != '=':
-                self.parse_token()  # kotlin argument name
+                arg.name = self.parse_token()  # kotlin argument name
             if self.parse_if('='): # kotlin default value
-                self.parse_expression()
-        return type
+                arg.default = self.parse_expression()
+        return arg
 
     def parse_expression(self):
         while not self.lookahead() in [')', ',', ';']:
@@ -592,7 +610,7 @@
     blame = None
     sig_format = 1
 
-    re_blame = re.compile("^([a-z0-9]{7,}) \(<([^>]+)>.+?\) (.+?)$")
+    re_blame = re.compile(r"^(\^?[a-z0-9]{7,}) \(<([^>]+)>.+?\) (.+?)$")
 
     field_prefixes = map(lambda kind: "    %s" % (kind,), V2LineParser.FIELD_KINDS)
     def startsWithFieldPrefix(raw):
@@ -607,11 +625,13 @@
         match = re_blame.match(raw)
         if match is not None:
             blame = match.groups()[0:2]
+            if blame[0].startswith("^"):  # Outside of blame range
+              blame = None
             raw = match.groups()[2]
         else:
             blame = None
 
-        if line == 1 and raw.startswith("// Signature format: "):
+        if line == 1 and V2Tokenizer.SIGNATURE_PREFIX in raw:
             sig_format_string = raw[len(V2Tokenizer.SIGNATURE_PREFIX):]
             if sig_format_string in ["2.0", "3.0"]:
                 sig_format = 2
@@ -1108,6 +1128,9 @@
     if not has_build:
         warn(clazz, None, None, "Missing build() method")
 
+    if "final" not in clazz.split:
+        error(clazz, None, None, "Builder should be final")
+
 
 def verify_aidl(clazz):
     """Catch people exposing raw AIDL."""
@@ -1867,6 +1890,35 @@
             if arg in discouraged:
                 warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead")
 
+PRIMITIVES = {"void", "int", "float", "boolean", "short", "char", "byte", "long", "double"}
+
+def verify_nullability(clazz):
+    """Catches missing nullability annotations"""
+
+    for f in clazz.fields:
+        if f.value is not None and 'static' in f.split and 'final' in f.split:
+            continue  # Nullability of constants can be inferred.
+        if f.typ not in PRIMITIVES and not has_nullability(f.annotations):
+            error(clazz, f, "M12", "Field must be marked either @NonNull or @Nullable")
+
+    for c in clazz.ctors:
+        verify_nullability_args(clazz, c)
+
+    for m in clazz.methods:
+        if m.name == "writeToParcel" or m.name == "onReceive":
+            continue  # Parcelable.writeToParcel() and BroadcastReceiver.onReceive() are not yet annotated
+
+        if m.typ not in PRIMITIVES and not has_nullability(m.annotations):
+            error(clazz, m, "M12", "Return value must be marked either @NonNull or @Nullable")
+        verify_nullability_args(clazz, m)
+
+def verify_nullability_args(clazz, m):
+    for i, arg in enumerate(m.detailed_args):
+        if arg.type not in PRIMITIVES and not has_nullability(arg.annotations):
+            error(clazz, m, "M12", "Argument %d must be marked either @NonNull or @Nullable" % (i+1,))
+
+def has_nullability(annotations):
+    return "@NonNull" in annotations or "@Nullable" in annotations
 
 def verify_singleton(clazz):
     """Catch singleton objects with constructors."""
@@ -1955,6 +2007,7 @@
     verify_pfd(clazz)
     verify_numbers(clazz)
     verify_singleton(clazz)
+    verify_nullability(clazz)
 
 
 def examine_stream(stream, base_stream=None, in_classes_with_base=[], out_classes_with_base=None):
diff --git a/tools/apilint/apilint_test.py b/tools/apilint/apilint_test.py
index 3716bf9..f34492d 100644
--- a/tools/apilint/apilint_test.py
+++ b/tools/apilint/apilint_test.py
@@ -88,20 +88,22 @@
 
 
 faulty_current_txt = """
+// Signature format: 2.0
 package android.app {
   public final class Activity {
   }
 
   public final class WallpaperColors implements android.os.Parcelable {
-    ctor public WallpaperColors(android.os.Parcel);
+    ctor public WallpaperColors(@NonNull android.os.Parcel);
     method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
   }
 }
-""".split('\n')
+""".strip().split('\n')
 
 ok_current_txt = """
+// Signature format: 2.0
 package android.app {
   public final class Activity {
   }
@@ -109,19 +111,20 @@
   public final class WallpaperColors implements android.os.Parcelable {
     ctor public WallpaperColors();
     method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
   }
 }
-""".split('\n')
+""".strip().split('\n')
 
 system_current_txt = """
+// Signature format: 2.0
 package android.app {
   public final class WallpaperColors implements android.os.Parcelable {
     method public int getSomething();
   }
 }
-""".split('\n')
+""".strip().split('\n')
 
 
 
@@ -369,5 +372,21 @@
         m = self._method('method @NonNull public @NonNull String @NonNull [] split(@NonNull String, int);')
         self.assertEquals('java.lang.String[]', m.typ)
 
+class PackageTests(unittest.TestCase):
+    def _package(self, raw):
+        return apilint.Package(123, raw, "blame")
+
+    def test_regular_package(self):
+        p = self._package("package an.pref.int {")
+        self.assertEquals('an.pref.int', p.name)
+
+    def test_annotation_package(self):
+        p = self._package("package @RestrictTo(a.b.C) an.pref.int {")
+        self.assertEquals('an.pref.int', p.name)
+
+    def test_multi_annotation_package(self):
+        p = self._package("package @Rt(a.b.L_G_P) @RestrictTo(a.b.C) an.pref.int {")
+        self.assertEquals('an.pref.int', p.name)
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/bit/main.cpp b/tools/bit/main.cpp
index 860094ae..082ccf3 100644
--- a/tools/bit/main.cpp
+++ b/tools/bit/main.cpp
@@ -33,6 +33,8 @@
 
 using namespace std;
 
+#define NATIVE_TESTS "NATIVE_TESTS"
+
 /**
  * An entry from the command line for something that will be built, installed,
  * and/or tested.
@@ -132,6 +134,32 @@
 {
 }
 
+struct PushedFile
+{
+    TrackedFile file;
+    string dest;
+
+    PushedFile();
+    PushedFile(const PushedFile& that);
+    PushedFile(const string& filename, const string& dest);
+    ~PushedFile() {};
+};
+
+PushedFile::PushedFile()
+{
+}
+
+PushedFile::PushedFile(const PushedFile& that)
+    :file(that.file),
+     dest(that.dest)
+{
+}
+
+PushedFile::PushedFile(const string& f, const string& d)
+    :file(f),
+     dest(d)
+{
+}
 
 /**
  * Record for an test that is going to be launched.
@@ -658,12 +686,14 @@
     }
 
     // Figure out whether we need to sync the system and which apks to install
-    string systemPath = buildOut + "/target/product/" + buildDevice + "/system/";
-    string dataPath = buildOut + "/target/product/" + buildDevice + "/data/";
+    string deviceTargetPath = buildOut + "/target/product/" + buildDevice;
+    string systemPath = deviceTargetPath + "/system/";
+    string dataPath = deviceTargetPath + "/data/";
     bool syncSystem = false;
     bool alwaysSyncSystem = false;
     vector<string> systemFiles;
     vector<InstallApk> installApks;
+    vector<PushedFile> pushedFiles;
     for (size_t i=0; i<targets.size(); i++) {
         Target* target = targets[i];
         if (target->install) {
@@ -687,6 +717,11 @@
                     installApks.push_back(InstallApk(file, !target->build));
                     continue;
                 }
+                // If it's a native test module, push it.
+                if (target->module.HasClass(NATIVE_TESTS) && starts_with(file, dataPath)) {
+                    string installedPath(file.c_str() + deviceTargetPath.length());
+                    pushedFiles.push_back(PushedFile(file, installedPath));
+                }
             }
         }
     }
@@ -701,6 +736,13 @@
             printf("  %s\n", systemFiles[i].c_str());
         }
     }
+    if (pushedFiles.size() > 0){
+        print_info("Files to push:");
+        for (size_t i=0; i<pushedFiles.size(); i++) {
+            printf("  %s\n", pushedFiles[i].file.filename.c_str());
+            printf("    --> %s\n", pushedFiles[i].dest.c_str());
+        }
+    }
     if (installApks.size() > 0){
         print_info("APKs to install:");
         for (size_t i=0; i<installApks.size(); i++) {
@@ -784,6 +826,25 @@
         }
     }
 
+    // Push files
+    if (pushedFiles.size() > 0) {
+        print_status("Pushing files");
+        for (size_t i=0; i<pushedFiles.size(); i++) {
+            const PushedFile& pushed = pushedFiles[i];
+            string dir = dirname(pushed.dest);
+            if (dir.length() == 0 || dir == "/") {
+                // This isn't really a file inside the data directory. Just skip it.
+                continue;
+            }
+            // TODO: if (!apk.file.fileInfo.exists || apk.file.HasChanged())
+            err = run_adb("shell", "mkdir", "-p", dir.c_str(), NULL);
+            check_error(err);
+            err = run_adb("push", pushed.file.filename.c_str(), pushed.dest.c_str());
+            check_error(err);
+            // pushed.installed = true;
+        }
+    }
+
     // Install APKs
     if (installApks.size() > 0) {
         print_status("Installing APKs");
@@ -804,6 +865,74 @@
     // Actions
     //
 
+    // Whether there have been any tests run, so we can print a summary.
+    bool testsRun = false;
+
+    // Run the native tests.
+    // TODO: We don't have a good way of running these and capturing the output of
+    // them live.  It'll take some work.  On the other hand, if they're gtest tests,
+    // the output of gtest is not completely insane like the text output of the
+    // instrumentation tests.  So for now, we'll just live with that.
+    for (size_t i=0; i<targets.size(); i++) {
+        Target* target = targets[i];
+        if (target->test && target->module.HasClass(NATIVE_TESTS)) {
+            // We don't have a clear signal from the build system which of the installed
+            // files is actually the test, so we guess by looking for one with the same
+            // leaf name as the module that is executable.
+            for (size_t j=0; j<target->module.installed.size(); j++) {
+                string filename = target->module.installed[j];
+                if (!starts_with(filename, dataPath)) {
+                    // Native tests go into the data directory.
+                    continue;
+                }
+                if (leafname(filename) != target->module.name) {
+                    // This isn't the test executable.
+                    continue;
+                }
+                if (!is_executable(filename)) {
+                    continue;
+                }
+                string installedPath(filename.c_str() + deviceTargetPath.length());
+                printf("the magic one is: %s\n", filename.c_str());
+                printf("  and it's installed at: %s\n", installedPath.c_str());
+
+                // Convert bit-style actions to gtest test filter arguments
+                if (target->actions.size() > 0) {
+                    testsRun = true;
+                    target->testActionCount++;
+                    bool runAll = false;
+                    string filterArg("--gtest_filter=");
+                    for (size_t k=0; k<target->actions.size(); k++) {
+                        string actionString = target->actions[k];
+                        if (actionString == "*") {
+                            runAll = true;
+                        } else {
+                            filterArg += actionString;
+                            if (k != target->actions.size()-1) {
+                                // We would otherwise have to worry about this condition
+                                // being true, and appending an extra ':', but we know that
+                                // if the extra action is "*", then we'll just run all and
+                                // won't use filterArg anyway, so just keep this condition
+                                // simple.
+                                filterArg += ':';
+                            }
+                        }
+                    }
+                    if (runAll) {
+                        err = run_adb("shell", installedPath.c_str(), NULL);
+                    } else {
+                        err = run_adb("shell", installedPath.c_str(), filterArg.c_str(), NULL);
+                    }
+                    if (err == 0) {
+                        target->testPassCount++;
+                    } else {
+                        target->testFailCount++;
+                    }
+                }
+            }
+        }
+    }
+
     // Inspect the apks, and figure out what is an activity and what needs a test runner
     bool printedInspecting = false;
     vector<TestAction> testActions;
@@ -872,6 +1001,7 @@
     TestResults testResults;
     if (testActions.size() > 0) {
         print_status("Running tests");
+        testsRun = true;
         for (size_t i=0; i<testActions.size(); i++) {
             TestAction& action = testActions[i];
             testResults.SetCurrentAction(&action);
@@ -969,7 +1099,7 @@
 
     // Tests
     bool hasErrors = false;
-    if (testActions.size() > 0) {
+    if (testsRun) {
         printf("%sRan tests:%s\n", g_escapeBold, g_escapeEndColor);
         size_t maxNameLength = 0;
         for (size_t i=0; i<targets.size(); i++) {
diff --git a/tools/bit/make.cpp b/tools/bit/make.cpp
index 6270913..df64a80 100644
--- a/tools/bit/make.cpp
+++ b/tools/bit/make.cpp
@@ -51,6 +51,18 @@
     return filename + "/.bit_cache";
 }
 
+bool
+Module::HasClass(const string& cl)
+{
+    for (vector<string>::const_iterator c = classes.begin(); c != classes.end(); c++) {
+        if (*c == cl) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
 BuildVars::BuildVars(const string& outDir, const string& buildProduct,
         const string& buildVariant, const string& buildType)
     :m_filename(),
diff --git a/tools/bit/make.h b/tools/bit/make.h
index db0b69f..785912a 100644
--- a/tools/bit/make.h
+++ b/tools/bit/make.h
@@ -29,6 +29,8 @@
     vector<string> classes;
     vector<string> paths;
     vector<string> installed;
+
+    bool HasClass(const string& cl);
 };
 
 /**
diff --git a/tools/bit/util.cpp b/tools/bit/util.cpp
index a502a9d..63399d6 100644
--- a/tools/bit/util.cpp
+++ b/tools/bit/util.cpp
@@ -254,4 +254,42 @@
     return result;
 }
 
+bool
+is_executable(const string& filename)
+{
+    int err;
+    struct stat st;
 
+    err = stat(filename.c_str(), &st);
+    if (err != 0) {
+        return false;
+    }
+
+    return (st.st_mode & S_IXUSR) != 0;
+}
+
+string
+dirname(const string& filename)
+{
+    size_t slash = filename.rfind('/');
+    if (slash == string::npos) {
+        return "";
+    } else if (slash == 0) {
+        return "/";
+    } else {
+        return string(filename, 0, slash);
+    }
+}
+
+string
+leafname(const string& filename)
+{
+    size_t slash = filename.rfind('/');
+    if (slash == string::npos) {
+        return filename;
+    } else if (slash == filename.length() - 1) {
+        return "";
+    } else {
+        return string(filename, slash + 1);
+    }
+}
diff --git a/tools/bit/util.h b/tools/bit/util.h
index 718f147..7ccdab1 100644
--- a/tools/bit/util.h
+++ b/tools/bit/util.h
@@ -79,5 +79,10 @@
 
 string read_file(const string& filename);
 
+bool is_executable(const string& filename);
+
+string dirname(const string& filename);
+string leafname(const string& filename);
+
 #endif // UTIL_H
 
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index d549799..17948e7 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -147,8 +147,10 @@
 
     void stopWatchLocalOnlyHotspot();
 
+    @UnsupportedAppUsage
     int getWifiApEnabledState();
 
+    @UnsupportedAppUsage
     WifiConfiguration getWifiApConfiguration();
 
     boolean setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
@@ -173,6 +175,7 @@
 
     void factoryReset(String packageName);
 
+    @UnsupportedAppUsage
     Network getCurrentNetwork();
 
     byte[] retrieveBackupData();
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/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 089b59a..c7180c1 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.IntRange;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
@@ -101,6 +102,11 @@
     private int mLinkSpeed;
 
     /**
+     * Constant for unknown link speed.
+     */
+    public static final int LINK_SPEED_UNKNOWN = -1;
+
+    /**
      * Tx(transmit) Link speed in Mbps
      */
     private int mTxLinkSpeed;
@@ -214,7 +220,7 @@
         mNetworkId = -1;
         mSupplicantState = SupplicantState.UNINITIALIZED;
         mRssi = INVALID_RSSI;
-        mLinkSpeed = -1;
+        mLinkSpeed = LINK_SPEED_UNKNOWN;
         mFrequency = -1;
     }
 
@@ -225,9 +231,9 @@
         setSSID(null);
         setNetworkId(-1);
         setRssi(INVALID_RSSI);
-        setLinkSpeed(-1);
-        setTxLinkSpeedMbps(-1);
-        setRxLinkSpeedMbps(-1);
+        setLinkSpeed(LINK_SPEED_UNKNOWN);
+        setTxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
+        setRxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
         setFrequency(-1);
         setMeteredHint(false);
         setEphemeral(false);
@@ -369,8 +375,9 @@
 
     /**
      * Returns the current link speed in {@link #LINK_SPEED_UNITS}.
-     * @return the link speed or -1 if there is no valid value.
+     * @return the link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
      * @see #LINK_SPEED_UNITS
+     * @see #LINK_SPEED_UNKNOWN
      */
     public int getLinkSpeed() {
         return mLinkSpeed;
@@ -384,8 +391,10 @@
 
     /**
      * Returns the current transmit link speed in Mbps.
-     * @return the Tx link speed or -1 if there is no valid value.
+     * @return the Tx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
+     * @see #LINK_SPEED_UNKNOWN
      */
+    @IntRange(from = -1)
     public int getTxLinkSpeedMbps() {
         return mTxLinkSpeed;
     }
@@ -400,8 +409,10 @@
 
     /**
      * Returns the current receive link speed in Mbps.
-     * @return the Rx link speed or -1 if there is no valid value.
+     * @return the Rx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
+     * @see #LINK_SPEED_UNKNOWN
      */
+    @IntRange(from = -1)
     public int getRxLinkSpeedMbps() {
         return mRxLinkSpeed;
     }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6c645fc..5ca30fc 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -4575,7 +4575,8 @@
     public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0;
 
     /**
-     * High movement device mobility state
+     * High movement device mobility state.
+     * e.g. on a bike, in a motor vehicle
      *
      * @see #setDeviceMobilityState(int)
      *
@@ -4585,7 +4586,8 @@
     public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1;
 
     /**
-     * Low movement device mobility state
+     * Low movement device mobility state.
+     * e.g. walking, running
      *
      * @see #setDeviceMobilityState(int)
      *
@@ -4607,6 +4609,8 @@
     /**
      * Updates the device mobility state. Wifi uses this information to adjust the interval between
      * Wifi scans in order to balance power consumption with scan accuracy.
+     * The default mobility state when the device boots is {@link #DEVICE_MOBILITY_STATE_UNKNOWN}.
+     * This API should be called whenever there is a change in the mobility state.
      * @param state the updated device mobility state
      * @hide
      */
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) { }
+    }
+}