Merge "media: add MediaFormat.KEY_PREPEND_HEADERS_TO_SYNC_FRAMES"
diff --git a/Android.bp b/Android.bp
index 05c7dbc..035420f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -384,6 +384,7 @@
         "core/java/android/view/IRecentsAnimationRunner.aidl",
         "core/java/android/view/IRemoteAnimationFinishedCallback.aidl",
         "core/java/android/view/IRotationWatcher.aidl",
+        "core/java/android/view/ISystemGestureExclusionListener.aidl",
         "core/java/android/view/IWallpaperVisibilityListener.aidl",
         "core/java/android/view/IWindow.aidl",
         "core/java/android/view/IWindowFocusObserver.aidl",
@@ -753,10 +754,6 @@
         "android.hardware.radio-V1.2-java",
         "android.hardware.radio-V1.3-java",
         "android.hardware.radio-V1.4-java",
-        "android.hardware.radio.config-V1.0-java",
-        "android.hardware.radio.config-V1.1-java",
-        "android.hardware.radio.config-V1.2-java",
-        "android.hardware.radio.deprecated-V1.0-java",
         "android.hardware.thermal-V1.0-java-constants",
         "android.hardware.thermal-V1.0-java",
         "android.hardware.thermal-V1.1-java",
@@ -771,7 +768,6 @@
         "android.hardware.vibrator-V1.2-java",
         "android.hardware.vibrator-V1.3-java",
         "android.hardware.wifi-V1.0-java-constants",
-        "networkstack-aidl-framework-java",
         "devicepolicyprotosnano",
     ],
 
@@ -1689,6 +1685,7 @@
     srcs: [
         ":openjdk_java_files",
         ":non_openjdk_java_files",
+        ":opt-telephony-common-srcs",
     ],
     arg_files: [
         "core/res/AndroidManifest.xml",
diff --git a/api/current.txt b/api/current.txt
index 118eb4c..e7a8ae3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11051,6 +11051,7 @@
     method public void dump(android.util.Printer, String);
     method public static CharSequence getCategoryTitle(android.content.Context, int);
     method public boolean isProfileableByShell();
+    method public boolean isResourceOverlay();
     method public boolean isVirtualPreload();
     method public CharSequence loadDescription(android.content.pm.PackageManager);
     field public static final int CATEGORY_AUDIO = 1; // 0x1
@@ -11676,7 +11677,6 @@
     field public static final String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
     field public static final String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
     field public static final String FEATURE_FINGERPRINT = "android.hardware.fingerprint";
-    field public static final String FEATURE_FOLDABLE = "android.hardware.type.foldable";
     field public static final String FEATURE_FREEFORM_WINDOW_MANAGEMENT = "android.software.freeform_window_management";
     field public static final String FEATURE_GAMEPAD = "android.hardware.gamepad";
     field public static final String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
@@ -22810,6 +22810,7 @@
     field public static final int CONSTELLATION_GALILEO = 6; // 0x6
     field public static final int CONSTELLATION_GLONASS = 3; // 0x3
     field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_IRNSS = 7; // 0x7
     field public static final int CONSTELLATION_QZSS = 4; // 0x4
     field public static final int CONSTELLATION_SBAS = 2; // 0x2
     field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
@@ -23400,15 +23401,16 @@
   }
 
   public final class AudioPlaybackCaptureConfiguration {
+    method @NonNull public android.media.projection.MediaProjection getMediaProjection();
   }
 
   public static final class AudioPlaybackCaptureConfiguration.Builder {
     ctor public AudioPlaybackCaptureConfiguration.Builder(@NonNull android.media.projection.MediaProjection);
     method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUid(int);
-    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(@NonNull android.media.AudioAttributes);
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(int);
     method @NonNull public android.media.AudioPlaybackCaptureConfiguration build();
     method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUid(int);
-    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(@NonNull android.media.AudioAttributes);
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(int);
   }
 
   public final class AudioPlaybackConfiguration implements android.os.Parcelable {
@@ -24425,9 +24427,10 @@
     field public static final int AV1Level71 = 2097152; // 0x200000
     field public static final int AV1Level72 = 4194304; // 0x400000
     field public static final int AV1Level73 = 8388608; // 0x800000
-    field public static final int AV1Profile0 = 1; // 0x1
-    field public static final int AV1Profile1 = 2; // 0x2
-    field public static final int AV1Profile2 = 4; // 0x4
+    field public static final int AV1ProfileMain10 = 2; // 0x2
+    field public static final int AV1ProfileMain10HDR10 = 4096; // 0x1000
+    field public static final int AV1ProfileMain10HDR10Plus = 8192; // 0x2000
+    field public static final int AV1ProfileMain8 = 1; // 0x1
     field public static final int AVCLevel1 = 1; // 0x1
     field public static final int AVCLevel11 = 4; // 0x4
     field public static final int AVCLevel12 = 8; // 0x8
@@ -24621,42 +24624,39 @@
     ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int);
     method public boolean covers(@NonNull android.media.MediaFormat);
     method public boolean covers(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint);
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_24;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_240;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_25;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_30;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_50;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_60;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_100;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_120;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_200;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_24;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_240;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_25;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_30;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_50;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_60;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_24;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_25;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_30;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_48;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_50;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_60;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_100;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_120;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_200;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_24;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_240;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_25;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_30;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50;
-    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60;
-    field public final int frameRate;
-    field public final long macroBlockRate;
-    field public final int macroBlocks;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_24;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_240;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_25;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_30;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_50;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_60;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_100;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_120;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_200;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_24;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_240;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_25;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_30;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_50;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_60;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_24;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_25;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_30;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_48;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_50;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_60;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_100;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_120;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_200;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_24;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_240;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_25;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_30;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50;
+    field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60;
   }
 
   public final class MediaCodecList {
@@ -25083,6 +25083,7 @@
     field public static final String KEY_LANGUAGE = "language";
     field public static final String KEY_LATENCY = "latency";
     field public static final String KEY_LEVEL = "level";
+    field public static final String KEY_MAX_BFRAMES = "max-bframes";
     field public static final String KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder";
     field public static final String KEY_MAX_HEIGHT = "max-height";
     field public static final String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -26142,10 +26143,11 @@
   }
 
   public final class MediaTimestamp {
+    ctor public MediaTimestamp(long, long, @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE) float);
     method public long getAnchorMediaTimeUs();
     method public long getAnchorSystemNanoTime();
     method @Deprecated public long getAnchorSytemNanoTime();
-    method public float getMediaClockRate();
+    method @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE) public float getMediaClockRate();
     field public static final android.media.MediaTimestamp TIMESTAMP_UNKNOWN;
   }
 
@@ -26473,6 +26475,7 @@
   }
 
   public final class SubtitleData {
+    ctor public SubtitleData(int, long, long, @NonNull byte[]);
     method @NonNull public byte[] getData();
     method public long getDurationUs();
     method public long getStartTimeUs();
@@ -26513,6 +26516,7 @@
   }
 
   public final class TimedMetaData {
+    ctor public TimedMetaData(long, @NonNull byte[]);
     method public byte[] getMetaData();
     method public long getTimestamp();
   }
@@ -30318,13 +30322,11 @@
   }
 
   public static final class WifiAwareNetworkSpecifier.Builder {
-    ctor public WifiAwareNetworkSpecifier.Builder();
+    ctor public WifiAwareNetworkSpecifier.Builder(@NonNull android.net.wifi.aware.DiscoverySession, @NonNull android.net.wifi.aware.PeerHandle);
     method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier build();
-    method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setDiscoverySession(@NonNull android.net.wifi.aware.DiscoverySession);
-    method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPeerHandle(@NonNull android.net.wifi.aware.PeerHandle);
-    method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPort(int);
+    method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPort(@IntRange(from=0, to=65535) int);
     method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPskPassphrase(@NonNull String);
-    method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setTransportProtocol(int);
+    method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setTransportProtocol(@IntRange(from=0, to=255) int);
   }
 
   public class WifiAwareSession implements java.lang.AutoCloseable {
@@ -35434,6 +35436,7 @@
   }
 
   public final class SystemClock {
+    method @NonNull public static java.time.Clock currentGnssTimeClock();
     method public static long currentThreadTimeMillis();
     method public static long elapsedRealtime();
     method public static long elapsedRealtimeNanos();
@@ -42500,12 +42503,12 @@
     method public static java.io.FileDescriptor accept(java.io.FileDescriptor, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException;
     method public static boolean access(String, int) throws android.system.ErrnoException;
     method public static void bind(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
-    method public static void bind(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+    method public static void bind(@NonNull java.io.FileDescriptor, @NonNull java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
     method public static void chmod(String, int) throws android.system.ErrnoException;
     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 void connect(@NonNull java.io.FileDescriptor, @NonNull 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();
@@ -42570,7 +42573,7 @@
     method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.system.Int64Ref, long) throws android.system.ErrnoException;
     method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
     method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
-    method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+    method public static int sendto(@NonNull java.io.FileDescriptor, @NonNull byte[], int, int, int, @Nullable java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
     method @Deprecated public static void setegid(int) throws android.system.ErrnoException;
     method public static void setenv(String, String, boolean) throws android.system.ErrnoException;
     method @Deprecated public static void seteuid(int) throws android.system.ErrnoException;
@@ -45196,7 +45199,7 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled();
     method public boolean isEmergencyNumber(@NonNull String);
     method public boolean isHearingAidCompatibilitySupported();
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isMultisimSupported();
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int isMultiSimSupported();
     method public boolean isNetworkRoaming();
     method public boolean isRttSupported();
     method public boolean isSmsCapable();
@@ -45276,6 +45279,9 @@
     field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID";
     field public static final String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
     field public static final String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU = "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU";
+    field public static final int MULTISIM_ALLOWED = 0; // 0x0
+    field public static final int MULTISIM_NOT_SUPPORTED_BY_CARRIER = 2; // 0x2
+    field public static final int MULTISIM_NOT_SUPPORTED_BY_HARDWARE = 1; // 0x1
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
@@ -45300,7 +45306,7 @@
     field public static final int PHONE_TYPE_GSM = 1; // 0x1
     field public static final int PHONE_TYPE_NONE = 0; // 0x0
     field public static final int PHONE_TYPE_SIP = 3; // 0x3
-    field public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2; // 0x2
+    field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2
     field public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0; // 0x0
     field public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; // 0x1
     field public static final int SIM_STATE_ABSENT = 1; // 0x1
@@ -50444,6 +50450,7 @@
     method protected float getLeftFadingEdgeStrength();
     method protected int getLeftPaddingOffset();
     method public final boolean getLocalVisibleRect(android.graphics.Rect);
+    method public void getLocationInSurface(@NonNull @Size(2) int[]);
     method public void getLocationInWindow(@Size(2) int[]);
     method public void getLocationOnScreen(@Size(2) int[]);
     method public android.graphics.Matrix getMatrix();
@@ -53501,7 +53508,6 @@
 package android.view.inspector {
 
   public interface InspectionCompanion<T> {
-    method @Nullable public default String getNodeName();
     method public void mapProperties(@NonNull android.view.inspector.PropertyMapper);
     method public void readProperties(@NonNull T, @NonNull android.view.inspector.PropertyReader);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index f406879..3e4ccb5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -186,6 +186,7 @@
     field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
     field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON";
     field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
+    field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
     field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
     field public static final String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE";
     field public static final String TV_VIRTUAL_REMOTE_CONTROLLER = "android.permission.TV_VIRTUAL_REMOTE_CONTROLLER";
@@ -338,6 +339,7 @@
     field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
     field public static final String OPSTR_GPS = "android:gps";
     field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
+    field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
     field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
     field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
     field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
@@ -545,6 +547,7 @@
   }
 
   public class NotificationManager {
+    method @NonNull public java.util.List<java.lang.String> getAllowedAssistantCapabilities();
     method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
     method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
     method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
@@ -742,7 +745,8 @@
     method @RequiresPermission(android.Manifest.permission.BACKUP) public String getCurrentTransport();
     method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.ComponentName getCurrentTransportComponent();
     method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getDataManagementIntent(String);
-    method @RequiresPermission(android.Manifest.permission.BACKUP) public String getDataManagementLabel(String);
+    method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public CharSequence getDataManagementIntentLabel(@NonNull String);
+    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public String getDataManagementLabel(@NonNull String);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public String getDestinationString(String);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isAppEligibleForBackup(String);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupEnabled();
@@ -756,7 +760,8 @@
     method @RequiresPermission(android.Manifest.permission.BACKUP) public void setAncestralSerialNumber(long);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public void setAutoRestore(boolean);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public void setBackupEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes(android.content.ComponentName, String, @Nullable android.content.Intent, String, @Nullable android.content.Intent, @Nullable String);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes(@NonNull android.content.ComponentName, @NonNull String, @Nullable android.content.Intent, @NonNull String, @Nullable android.content.Intent, @Nullable String);
+    method @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes(@NonNull android.content.ComponentName, @NonNull String, @Nullable android.content.Intent, @NonNull String, @Nullable android.content.Intent, @Nullable CharSequence);
     field public static final int ERROR_AGENT_FAILURE = -1003; // 0xfffffc15
     field public static final int ERROR_BACKUP_CANCELLED = -2003; // 0xfffff82d
     field public static final int ERROR_BACKUP_NOT_ALLOWED = -2001; // 0xfffff82f
@@ -861,7 +866,8 @@
     method public android.content.Intent configurationIntent();
     method public String currentDestinationString();
     method public android.content.Intent dataManagementIntent();
-    method public String dataManagementLabel();
+    method @Nullable public CharSequence dataManagementIntentLabel();
+    method @Deprecated @Nullable public String dataManagementLabel();
     method public int finishBackup();
     method public void finishRestore();
     method public android.app.backup.RestoreSet[] getAvailableRestoreSets();
@@ -1478,6 +1484,7 @@
   }
 
   public class OverlayManager {
+    method @Nullable public android.content.om.OverlayInfo getOverlayInfo(@NonNull String, @NonNull android.os.UserHandle);
     method public java.util.List<android.content.om.OverlayInfo> getOverlayInfosForTarget(@Nullable String, int);
     method public boolean setEnabled(@Nullable String, boolean, int);
     method public boolean setEnabledExclusiveInCategory(@Nullable String, int);
@@ -1647,6 +1654,7 @@
     field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
     field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
     field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
+    field public static final int FLAG_PERMISSION_HIDDEN = 1024; // 0x400
     field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
     field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
     field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
@@ -1717,7 +1725,7 @@
     method public void onPermissionsChanged(int);
   }
 
-  @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
+  @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
   }
 
   public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
@@ -1836,9 +1844,9 @@
   }
 
   public final class RollbackManager {
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
     field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS";
     field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE";
     field public static final int STATUS_FAILURE = 1; // 0x1
@@ -3066,6 +3074,19 @@
     method public void onLocationBatch(java.util.List<android.location.Location>);
   }
 
+  public final class GnssCapabilities {
+    method public boolean hasCapability(int);
+    field public static final int GEOFENCING = 2; // 0x2
+    field public static final int LOW_POWER_MODE = 0; // 0x0
+    field public static final int MEASUREMENTS = 3; // 0x3
+    field public static final int MEASUREMENT_CORRECTIONS = 5; // 0x5
+    field public static final int MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH = 7; // 0x7
+    field public static final int MEASUREMENT_CORRECTIONS_LOS_SATS = 6; // 0x6
+    field public static final int MEASUREMENT_CORRECTIONS_REFLECTING_PLANE = 8; // 0x8
+    field public static final int NAV_MESSAGES = 4; // 0x4
+    field public static final int SATELLITE_BLACKLIST = 1; // 0x1
+  }
+
   public final class GnssMeasurementCorrections implements android.os.Parcelable {
     method public int describeContents();
     method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
@@ -3373,7 +3394,7 @@
   public class LocationManager {
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize();
-    method public int getGnssCapabilities();
+    method @Nullable public android.location.GnssCapabilities getGnssCapabilities();
     method @Nullable public String getLocationControllerExtraPackage();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
     method public boolean isLocationControllerExtraPackageEnabled();
@@ -3557,13 +3578,6 @@
     field public static final int RADIO_TUNER = 1998; // 0x7ce
   }
 
-  public static final class MediaTimestamp.Builder {
-    ctor public MediaTimestamp.Builder();
-    ctor public MediaTimestamp.Builder(@NonNull android.media.MediaTimestamp);
-    method @NonNull public android.media.MediaTimestamp build();
-    method @NonNull public android.media.MediaTimestamp.Builder setMediaTimestamp(long, long, float);
-  }
-
   public class PlayerProxy {
     method public void pause();
     method public void setPan(float);
@@ -3573,20 +3587,6 @@
     method public void stop();
   }
 
-  public static final class SubtitleData.Builder {
-    ctor public SubtitleData.Builder();
-    ctor public SubtitleData.Builder(@NonNull android.media.SubtitleData);
-    method @NonNull public android.media.SubtitleData build();
-    method @NonNull public android.media.SubtitleData.Builder setSubtitleData(int, long, long, @NonNull byte[]);
-  }
-
-  public static final class TimedMetaData.Builder {
-    ctor public TimedMetaData.Builder();
-    ctor public TimedMetaData.Builder(@NonNull android.media.TimedMetaData);
-    method @NonNull public android.media.TimedMetaData build();
-    method @NonNull public android.media.TimedMetaData.Builder setTimedMetaData(long, @NonNull byte[]);
-  }
-
 }
 
 package android.media.audiopolicy {
@@ -4027,8 +4027,8 @@
 package android.net {
 
   public class CaptivePortal implements android.os.Parcelable {
-    ctor public CaptivePortal(android.os.IBinder);
-    method public void logEvent(int, String);
+    ctor public CaptivePortal(@NonNull android.os.IBinder);
+    method public void logEvent(int, @NonNull String);
     method public void useNetwork();
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
     field public static final int APP_RETURN_UNWANTED = 1; // 0x1
@@ -4235,18 +4235,18 @@
 
   public final class StaticIpConfiguration implements android.os.Parcelable {
     ctor public StaticIpConfiguration();
-    ctor public StaticIpConfiguration(android.net.StaticIpConfiguration);
-    method public void addDnsServer(java.net.InetAddress);
+    ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+    method public void addDnsServer(@NonNull java.net.InetAddress);
     method public void clear();
     method public int describeContents();
-    method public java.util.List<java.net.InetAddress> getDnsServers();
-    method public String getDomains();
-    method public java.net.InetAddress getGateway();
-    method public android.net.LinkAddress getIpAddress();
-    method public java.util.List<android.net.RouteInfo> getRoutes(String);
-    method public void setDomains(String);
-    method public void setGateway(java.net.InetAddress);
-    method public void setIpAddress(android.net.LinkAddress);
+    method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
+    method @Nullable public String getDomains();
+    method @Nullable public java.net.InetAddress getGateway();
+    method @Nullable public android.net.LinkAddress getIpAddress();
+    method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(String);
+    method public void setDomains(@Nullable String);
+    method public void setGateway(@Nullable java.net.InetAddress);
+    method public void setIpAddress(@Nullable android.net.LinkAddress);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
   }
@@ -4300,28 +4300,28 @@
 
   public final class CaptivePortalProbeResult {
     ctor public CaptivePortalProbeResult(int);
-    ctor public CaptivePortalProbeResult(int, String, String);
-    ctor public CaptivePortalProbeResult(int, String, String, android.net.captiveportal.CaptivePortalProbeSpec);
+    ctor public CaptivePortalProbeResult(int, @Nullable String, @Nullable String);
+    ctor public CaptivePortalProbeResult(int, @Nullable String, @Nullable String, @Nullable android.net.captiveportal.CaptivePortalProbeSpec);
     method public boolean isFailed();
     method public boolean isPartialConnectivity();
     method public boolean isPortal();
     method public boolean isSuccessful();
-    field public static final android.net.captiveportal.CaptivePortalProbeResult FAILED;
+    field @NonNull public static final android.net.captiveportal.CaptivePortalProbeResult FAILED;
     field public static final int FAILED_CODE = 599; // 0x257
     field public static final android.net.captiveportal.CaptivePortalProbeResult PARTIAL;
     field public static final int PORTAL_CODE = 302; // 0x12e
-    field public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS;
+    field @NonNull public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS;
     field public static final int SUCCESS_CODE = 204; // 0xcc
-    field public final String detectUrl;
+    field @Nullable public final String detectUrl;
     field @Nullable public final android.net.captiveportal.CaptivePortalProbeSpec probeSpec;
-    field public final String redirectUrl;
+    field @Nullable public final String redirectUrl;
   }
 
   public abstract class CaptivePortalProbeSpec {
-    method public String getEncodedSpec();
-    method public abstract android.net.captiveportal.CaptivePortalProbeResult getResult(int, @Nullable String);
-    method public java.net.URL getUrl();
-    method public static java.util.Collection<android.net.captiveportal.CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(String);
+    method @NonNull public String getEncodedSpec();
+    method @NonNull public abstract android.net.captiveportal.CaptivePortalProbeResult getResult(int, @Nullable String);
+    method @NonNull public java.net.URL getUrl();
+    method @NonNull public static java.util.Collection<android.net.captiveportal.CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(@NonNull String);
     method @Nullable public static android.net.captiveportal.CaptivePortalProbeSpec parseSpecOrNull(@Nullable String);
   }
 
@@ -4332,78 +4332,78 @@
   public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event {
   }
 
-  public static class ApfProgramEvent.Builder {
+  public static final class ApfProgramEvent.Builder {
     ctor public ApfProgramEvent.Builder();
-    method public android.net.metrics.ApfProgramEvent build();
-    method public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long);
-    method public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int);
-    method public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int);
-    method public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean);
-    method public android.net.metrics.ApfProgramEvent.Builder setLifetime(long);
-    method public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int);
+    method @NonNull public android.net.metrics.ApfProgramEvent build();
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setLifetime(long);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int);
   }
 
   public final class ApfStats implements android.net.metrics.IpConnectivityLog.Event {
   }
 
-  public static class ApfStats.Builder {
+  public static final class ApfStats.Builder {
     ctor public ApfStats.Builder();
-    method public android.net.metrics.ApfStats build();
-    method public android.net.metrics.ApfStats.Builder setDroppedRas(int);
-    method public android.net.metrics.ApfStats.Builder setDurationMs(long);
-    method public android.net.metrics.ApfStats.Builder setMatchingRas(int);
-    method public android.net.metrics.ApfStats.Builder setMaxProgramSize(int);
-    method public android.net.metrics.ApfStats.Builder setParseErrors(int);
-    method public android.net.metrics.ApfStats.Builder setProgramUpdates(int);
-    method public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int);
-    method public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int);
-    method public android.net.metrics.ApfStats.Builder setReceivedRas(int);
-    method public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int);
+    method @NonNull public android.net.metrics.ApfStats build();
+    method @NonNull public android.net.metrics.ApfStats.Builder setDroppedRas(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setDurationMs(long);
+    method @NonNull public android.net.metrics.ApfStats.Builder setMatchingRas(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setMaxProgramSize(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setParseErrors(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdates(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setReceivedRas(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int);
   }
 
   public final class DhcpClientEvent implements android.net.metrics.IpConnectivityLog.Event {
   }
 
-  public static class DhcpClientEvent.Builder {
+  public static final class DhcpClientEvent.Builder {
     ctor public DhcpClientEvent.Builder();
-    method public android.net.metrics.DhcpClientEvent build();
-    method public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int);
-    method public android.net.metrics.DhcpClientEvent.Builder setMsg(String);
+    method @NonNull public android.net.metrics.DhcpClientEvent build();
+    method @NonNull public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int);
+    method @NonNull public android.net.metrics.DhcpClientEvent.Builder setMsg(String);
   }
 
   public final class DhcpErrorEvent implements android.net.metrics.IpConnectivityLog.Event {
     ctor public DhcpErrorEvent(int);
     method public static int errorCodeWithOption(int, int);
-    field public static final int BOOTP_TOO_SHORT;
-    field public static final int BUFFER_UNDERFLOW;
-    field public static final int DHCP_BAD_MAGIC_COOKIE;
+    field public static final int BOOTP_TOO_SHORT = 67174400; // 0x4010000
+    field public static final int BUFFER_UNDERFLOW = 83951616; // 0x5010000
+    field public static final int DHCP_BAD_MAGIC_COOKIE = 67239936; // 0x4020000
     field public static final int DHCP_ERROR = 4; // 0x4
-    field public static final int DHCP_INVALID_OPTION_LENGTH;
-    field public static final int DHCP_NO_COOKIE;
-    field public static final int DHCP_NO_MSG_TYPE;
-    field public static final int DHCP_UNKNOWN_MSG_TYPE;
+    field public static final int DHCP_INVALID_OPTION_LENGTH = 67305472; // 0x4030000
+    field public static final int DHCP_NO_COOKIE = 67502080; // 0x4060000
+    field public static final int DHCP_NO_MSG_TYPE = 67371008; // 0x4040000
+    field public static final int DHCP_UNKNOWN_MSG_TYPE = 67436544; // 0x4050000
     field public static final int L2_ERROR = 1; // 0x1
-    field public static final int L2_TOO_SHORT;
-    field public static final int L2_WRONG_ETH_TYPE;
+    field public static final int L2_TOO_SHORT = 16842752; // 0x1010000
+    field public static final int L2_WRONG_ETH_TYPE = 16908288; // 0x1020000
     field public static final int L3_ERROR = 2; // 0x2
-    field public static final int L3_INVALID_IP;
-    field public static final int L3_NOT_IPV4;
-    field public static final int L3_TOO_SHORT;
+    field public static final int L3_INVALID_IP = 33751040; // 0x2030000
+    field public static final int L3_NOT_IPV4 = 33685504; // 0x2020000
+    field public static final int L3_TOO_SHORT = 33619968; // 0x2010000
     field public static final int L4_ERROR = 3; // 0x3
-    field public static final int L4_NOT_UDP;
-    field public static final int L4_WRONG_PORT;
+    field public static final int L4_NOT_UDP = 50397184; // 0x3010000
+    field public static final int L4_WRONG_PORT = 50462720; // 0x3020000
     field public static final int MISC_ERROR = 5; // 0x5
-    field public static final int PARSING_ERROR;
-    field public static final int RECEIVE_ERROR;
+    field public static final int PARSING_ERROR = 84082688; // 0x5030000
+    field public static final int RECEIVE_ERROR = 84017152; // 0x5020000
   }
 
   public class IpConnectivityLog {
     ctor public IpConnectivityLog();
-    method public boolean log(long, android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(String, android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(android.net.Network, int[], android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(int, int[], android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(long, @NonNull android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(@NonNull String, @NonNull android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(@NonNull android.net.Network, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(int, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(@NonNull android.net.metrics.IpConnectivityLog.Event);
   }
 
   public static interface IpConnectivityLog.Event extends android.os.Parcelable {
@@ -4474,12 +4474,12 @@
     field public static final int PROBE_PRIVDNS = 5; // 0x5
   }
 
-  public static class ValidationProbeEvent.Builder {
+  public static final class ValidationProbeEvent.Builder {
     ctor public ValidationProbeEvent.Builder();
-    method public android.net.metrics.ValidationProbeEvent build();
-    method public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long);
-    method public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean);
-    method public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int);
+    method @NonNull public android.net.metrics.ValidationProbeEvent build();
+    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long);
+    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean);
+    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int);
   }
 
 }
@@ -5492,7 +5492,7 @@
   }
 
   public class ServiceSpecificException extends java.lang.RuntimeException {
-    ctor public ServiceSpecificException(int, String);
+    ctor public ServiceSpecificException(int, @Nullable String);
     ctor public ServiceSpecificException(int);
     field public final int errorCode;
   }
@@ -5884,7 +5884,9 @@
     field public static final String NAMESPACE_RUNTIME_NATIVE = "runtime_native";
     field public static final String NAMESPACE_RUNTIME_NATIVE_BOOT = "runtime_native_boot";
     field public static final String NAMESPACE_SCHEDULER = "scheduler";
+    field public static final String NAMESPACE_STORAGE = "storage";
     field public static final String NAMESPACE_SYSTEMUI = "systemui";
+    field public static final String NAMESPACE_TELEPHONY = "telephony";
     field public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier";
   }
 
@@ -5912,18 +5914,6 @@
     method @Nullable public String getString(@NonNull String, @Nullable String);
   }
 
-  public static interface DeviceConfig.Storage {
-    field public static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
-    field public static final String NAMESPACE = "storage";
-  }
-
-  public static interface DeviceConfig.Telephony {
-    field public static final String NAMESPACE = "telephony";
-    field public static final String RAMPING_RINGER_DURATION = "ramping_ringer_duration";
-    field public static final String RAMPING_RINGER_ENABLED = "ramping_ringer_enabled";
-    field public static final String RAMPING_RINGER_VIBRATION_DURATION = "ramping_ringer_vibration_duration";
-  }
-
   public final class DocumentsContract {
     method public static boolean isManageMode(@NonNull android.net.Uri);
     method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri);
@@ -6118,6 +6108,8 @@
     field public static final String LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE = "location_permissions_upgrade_to_q_mode";
     field public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications";
     field public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
+    field public static final String ODI_CAPTIONS_ENABLED = "odi_captions_enabled";
+    field public static final String ODI_CAPTIONS_OPTED_OUT = "odi_captions_opted_out";
     field public static final String THEME_CUSTOMIZATION_OVERLAY_PACKAGES = "theme_customization_overlay_packages";
     field public static final String USER_SETUP_COMPLETE = "user_setup_complete";
     field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa
@@ -6428,6 +6420,7 @@
     method public int getEventType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.ActivityEvent> CREATOR;
+    field public static final int TYPE_ACTIVITY_DESTROYED = 24; // 0x18
     field public static final int TYPE_ACTIVITY_PAUSED = 2; // 0x2
     field public static final int TYPE_ACTIVITY_RESUMED = 1; // 0x1
     field public static final int TYPE_ACTIVITY_STOPPED = 23; // 0x17
@@ -6446,6 +6439,7 @@
     method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
     method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
     field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
+    field public static final String SERVICE_META_DATA = "android.content_capture";
   }
 
   public final class SnapshotData implements android.os.Parcelable {
@@ -6646,6 +6640,7 @@
     method public final void adjustNotifications(@NonNull java.util.List<android.service.notification.Adjustment>);
     method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int);
     method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
+    method public void onCapabilitiesChanged();
     method public void onNotificationDirectReplied(@NonNull String);
     method @Nullable public abstract android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification);
     method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel);
@@ -8067,7 +8062,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultisimCarrierRestriction(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
@@ -8355,6 +8350,7 @@
     field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
     field public static final String EXTRA_ENABLE_SUBSCRIPTION = "android.telephony.euicc.extra.ENABLE_SUBSCRIPTION";
     field public static final String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION";
+    field public static final String EXTRA_FROM_SUBSCRIPTION_ID = "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID";
     field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.euicc.extra.SUBSCRIPTION_ID";
     field public static final String EXTRA_SUBSCRIPTION_NICKNAME = "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME";
   }
@@ -8574,7 +8570,7 @@
     field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants;
   }
 
-  public class ImsException extends java.lang.Exception {
+  public final class ImsException extends java.lang.Exception {
     ctor public ImsException(@Nullable String);
     ctor public ImsException(@Nullable String, int);
     ctor public ImsException(@Nullable String, int, @Nullable Throwable);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 18d0ec0..7e04469 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -60,14 +60,6 @@
 
 }
 
-package android.content.pm {
-
-  public static class PackageInstaller.SessionParams implements android.os.Parcelable {
-    method @Deprecated public void setEnableRollback();
-  }
-
-}
-
 package android.location {
 
   public class LocationManager {
diff --git a/api/test-current.txt b/api/test-current.txt
index f309528..5e9b405 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -14,6 +14,7 @@
     field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
     field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
     field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
+    field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
     field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
     field public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
     field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
@@ -133,16 +134,19 @@
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void addHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOps);
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void clearHistory();
     method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
-    method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
+    method @RequiresPermission("android.permission.MANAGE_APPOPS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
     method public static int getNumOps();
     method public static String[] getOpStrs();
     method public boolean isOperationActive(int, int, String);
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void offsetHistory(long);
+    method public static int opToDefaultMode(@NonNull String);
     method public static String opToPermission(int);
     method public static int permissionToOpCode(String);
+    method @RequiresPermission("android.permission.MANAGE_APPOPS") public void reloadNonHistoricalState();
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters();
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
     method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int);
+    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int);
     method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(String, int, int);
     method public void startWatchingActive(@NonNull int[], @NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
     method public void stopWatchingActive(@NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
@@ -168,6 +172,7 @@
     field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
     field public static final String OPSTR_GPS = "android:gps";
     field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
+    field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
     field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
     field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
     field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
@@ -415,7 +420,8 @@
   public class BackupManager {
     method @RequiresPermission("android.permission.BACKUP") public android.content.Intent getConfigurationIntent(String);
     method @RequiresPermission("android.permission.BACKUP") public android.content.Intent getDataManagementIntent(String);
-    method @RequiresPermission("android.permission.BACKUP") public String getDataManagementLabel(String);
+    method @Nullable @RequiresPermission("android.permission.BACKUP") public CharSequence getDataManagementIntentLabel(@NonNull String);
+    method @Deprecated @Nullable @RequiresPermission("android.permission.BACKUP") public String getDataManagementLabel(@NonNull String);
     method @RequiresPermission("android.permission.BACKUP") public String getDestinationString(String);
   }
 
@@ -655,6 +661,7 @@
     method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS"}) public abstract void updatePermissionFlags(String, String, int, int, @NonNull android.os.UserHandle);
     field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
     field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
+    field public static final int FLAG_PERMISSION_HIDDEN = 1024; // 0x400
     field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
     field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
     field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
@@ -720,11 +727,11 @@
   }
 
   public final class RollbackManager {
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void reloadPersistedData();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
+    method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
+    method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void reloadPersistedData();
     field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS";
     field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE";
     field public static final String PROPERTY_ROLLBACK_LIFETIME_MILLIS = "rollback_lifetime_in_millis";
@@ -1071,6 +1078,14 @@
     method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int);
   }
 
+  public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
+    ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size);
+    ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size);
+    method public int getMaxFrameRate();
+    method public long getMaxMacroBlockRate();
+    method public int getMaxMacroBlocks();
+  }
+
   public class MediaPlayer2 implements android.media.AudioRouting java.lang.AutoCloseable {
     method public android.media.MediaPlayer2.DrmInfo getDrmInfo(@NonNull android.media.DataSourceDesc);
     method public android.media.MediaDrm.KeyRequest getDrmKeyRequest(@NonNull android.media.DataSourceDesc, @Nullable byte[], @Nullable byte[], @Nullable String, int, @Nullable java.util.Map<java.lang.String,java.lang.String>) throws android.media.MediaPlayer2.NoDrmSchemeException;
@@ -1175,8 +1190,8 @@
 package android.net {
 
   public class CaptivePortal implements android.os.Parcelable {
-    ctor public CaptivePortal(android.os.IBinder);
-    method public void logEvent(int, String);
+    ctor public CaptivePortal(@NonNull android.os.IBinder);
+    method public void logEvent(int, @NonNull String);
     method public void useNetwork();
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
     field public static final int APP_RETURN_UNWANTED = 1; // 0x1
@@ -1261,18 +1276,18 @@
 
   public final class StaticIpConfiguration implements android.os.Parcelable {
     ctor public StaticIpConfiguration();
-    ctor public StaticIpConfiguration(android.net.StaticIpConfiguration);
-    method public void addDnsServer(java.net.InetAddress);
+    ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+    method public void addDnsServer(@NonNull java.net.InetAddress);
     method public void clear();
     method public int describeContents();
-    method public java.util.List<java.net.InetAddress> getDnsServers();
-    method public String getDomains();
-    method public java.net.InetAddress getGateway();
-    method public android.net.LinkAddress getIpAddress();
-    method public java.util.List<android.net.RouteInfo> getRoutes(String);
-    method public void setDomains(String);
-    method public void setGateway(java.net.InetAddress);
-    method public void setIpAddress(android.net.LinkAddress);
+    method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
+    method @Nullable public String getDomains();
+    method @Nullable public java.net.InetAddress getGateway();
+    method @Nullable public android.net.LinkAddress getIpAddress();
+    method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(String);
+    method public void setDomains(@Nullable String);
+    method public void setGateway(@Nullable java.net.InetAddress);
+    method public void setIpAddress(@Nullable android.net.LinkAddress);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
   }
@@ -1325,28 +1340,28 @@
 
   public final class CaptivePortalProbeResult {
     ctor public CaptivePortalProbeResult(int);
-    ctor public CaptivePortalProbeResult(int, String, String);
-    ctor public CaptivePortalProbeResult(int, String, String, android.net.captiveportal.CaptivePortalProbeSpec);
+    ctor public CaptivePortalProbeResult(int, @Nullable String, @Nullable String);
+    ctor public CaptivePortalProbeResult(int, @Nullable String, @Nullable String, @Nullable android.net.captiveportal.CaptivePortalProbeSpec);
     method public boolean isFailed();
     method public boolean isPartialConnectivity();
     method public boolean isPortal();
     method public boolean isSuccessful();
-    field public static final android.net.captiveportal.CaptivePortalProbeResult FAILED;
+    field @NonNull public static final android.net.captiveportal.CaptivePortalProbeResult FAILED;
     field public static final int FAILED_CODE = 599; // 0x257
     field public static final android.net.captiveportal.CaptivePortalProbeResult PARTIAL;
     field public static final int PORTAL_CODE = 302; // 0x12e
-    field public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS;
+    field @NonNull public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS;
     field public static final int SUCCESS_CODE = 204; // 0xcc
-    field public final String detectUrl;
+    field @Nullable public final String detectUrl;
     field @Nullable public final android.net.captiveportal.CaptivePortalProbeSpec probeSpec;
-    field public final String redirectUrl;
+    field @Nullable public final String redirectUrl;
   }
 
   public abstract class CaptivePortalProbeSpec {
-    method public String getEncodedSpec();
-    method public abstract android.net.captiveportal.CaptivePortalProbeResult getResult(int, @Nullable String);
-    method public java.net.URL getUrl();
-    method public static java.util.Collection<android.net.captiveportal.CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(String);
+    method @NonNull public String getEncodedSpec();
+    method @NonNull public abstract android.net.captiveportal.CaptivePortalProbeResult getResult(int, @Nullable String);
+    method @NonNull public java.net.URL getUrl();
+    method @NonNull public static java.util.Collection<android.net.captiveportal.CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(@NonNull String);
     method @Nullable public static android.net.captiveportal.CaptivePortalProbeSpec parseSpecOrNull(@Nullable String);
   }
 
@@ -1357,78 +1372,78 @@
   public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event {
   }
 
-  public static class ApfProgramEvent.Builder {
+  public static final class ApfProgramEvent.Builder {
     ctor public ApfProgramEvent.Builder();
-    method public android.net.metrics.ApfProgramEvent build();
-    method public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long);
-    method public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int);
-    method public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int);
-    method public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean);
-    method public android.net.metrics.ApfProgramEvent.Builder setLifetime(long);
-    method public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int);
+    method @NonNull public android.net.metrics.ApfProgramEvent build();
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setLifetime(long);
+    method @NonNull public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int);
   }
 
   public final class ApfStats implements android.net.metrics.IpConnectivityLog.Event {
   }
 
-  public static class ApfStats.Builder {
+  public static final class ApfStats.Builder {
     ctor public ApfStats.Builder();
-    method public android.net.metrics.ApfStats build();
-    method public android.net.metrics.ApfStats.Builder setDroppedRas(int);
-    method public android.net.metrics.ApfStats.Builder setDurationMs(long);
-    method public android.net.metrics.ApfStats.Builder setMatchingRas(int);
-    method public android.net.metrics.ApfStats.Builder setMaxProgramSize(int);
-    method public android.net.metrics.ApfStats.Builder setParseErrors(int);
-    method public android.net.metrics.ApfStats.Builder setProgramUpdates(int);
-    method public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int);
-    method public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int);
-    method public android.net.metrics.ApfStats.Builder setReceivedRas(int);
-    method public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int);
+    method @NonNull public android.net.metrics.ApfStats build();
+    method @NonNull public android.net.metrics.ApfStats.Builder setDroppedRas(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setDurationMs(long);
+    method @NonNull public android.net.metrics.ApfStats.Builder setMatchingRas(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setMaxProgramSize(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setParseErrors(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdates(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setReceivedRas(int);
+    method @NonNull public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int);
   }
 
   public final class DhcpClientEvent implements android.net.metrics.IpConnectivityLog.Event {
   }
 
-  public static class DhcpClientEvent.Builder {
+  public static final class DhcpClientEvent.Builder {
     ctor public DhcpClientEvent.Builder();
-    method public android.net.metrics.DhcpClientEvent build();
-    method public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int);
-    method public android.net.metrics.DhcpClientEvent.Builder setMsg(String);
+    method @NonNull public android.net.metrics.DhcpClientEvent build();
+    method @NonNull public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int);
+    method @NonNull public android.net.metrics.DhcpClientEvent.Builder setMsg(String);
   }
 
   public final class DhcpErrorEvent implements android.net.metrics.IpConnectivityLog.Event {
     ctor public DhcpErrorEvent(int);
     method public static int errorCodeWithOption(int, int);
-    field public static final int BOOTP_TOO_SHORT;
-    field public static final int BUFFER_UNDERFLOW;
-    field public static final int DHCP_BAD_MAGIC_COOKIE;
+    field public static final int BOOTP_TOO_SHORT = 67174400; // 0x4010000
+    field public static final int BUFFER_UNDERFLOW = 83951616; // 0x5010000
+    field public static final int DHCP_BAD_MAGIC_COOKIE = 67239936; // 0x4020000
     field public static final int DHCP_ERROR = 4; // 0x4
-    field public static final int DHCP_INVALID_OPTION_LENGTH;
-    field public static final int DHCP_NO_COOKIE;
-    field public static final int DHCP_NO_MSG_TYPE;
-    field public static final int DHCP_UNKNOWN_MSG_TYPE;
+    field public static final int DHCP_INVALID_OPTION_LENGTH = 67305472; // 0x4030000
+    field public static final int DHCP_NO_COOKIE = 67502080; // 0x4060000
+    field public static final int DHCP_NO_MSG_TYPE = 67371008; // 0x4040000
+    field public static final int DHCP_UNKNOWN_MSG_TYPE = 67436544; // 0x4050000
     field public static final int L2_ERROR = 1; // 0x1
-    field public static final int L2_TOO_SHORT;
-    field public static final int L2_WRONG_ETH_TYPE;
+    field public static final int L2_TOO_SHORT = 16842752; // 0x1010000
+    field public static final int L2_WRONG_ETH_TYPE = 16908288; // 0x1020000
     field public static final int L3_ERROR = 2; // 0x2
-    field public static final int L3_INVALID_IP;
-    field public static final int L3_NOT_IPV4;
-    field public static final int L3_TOO_SHORT;
+    field public static final int L3_INVALID_IP = 33751040; // 0x2030000
+    field public static final int L3_NOT_IPV4 = 33685504; // 0x2020000
+    field public static final int L3_TOO_SHORT = 33619968; // 0x2010000
     field public static final int L4_ERROR = 3; // 0x3
-    field public static final int L4_NOT_UDP;
-    field public static final int L4_WRONG_PORT;
+    field public static final int L4_NOT_UDP = 50397184; // 0x3010000
+    field public static final int L4_WRONG_PORT = 50462720; // 0x3020000
     field public static final int MISC_ERROR = 5; // 0x5
-    field public static final int PARSING_ERROR;
-    field public static final int RECEIVE_ERROR;
+    field public static final int PARSING_ERROR = 84082688; // 0x5030000
+    field public static final int RECEIVE_ERROR = 84017152; // 0x5020000
   }
 
   public class IpConnectivityLog {
     ctor public IpConnectivityLog();
-    method public boolean log(long, android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(String, android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(android.net.Network, int[], android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(int, int[], android.net.metrics.IpConnectivityLog.Event);
-    method public boolean log(android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(long, @NonNull android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(@NonNull String, @NonNull android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(@NonNull android.net.Network, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(int, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event);
+    method public boolean log(@NonNull android.net.metrics.IpConnectivityLog.Event);
   }
 
   public static interface IpConnectivityLog.Event extends android.os.Parcelable {
@@ -1499,12 +1514,12 @@
     field public static final int PROBE_PRIVDNS = 5; // 0x5
   }
 
-  public static class ValidationProbeEvent.Builder {
+  public static final class ValidationProbeEvent.Builder {
     ctor public ValidationProbeEvent.Builder();
-    method public android.net.metrics.ValidationProbeEvent build();
-    method public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long);
-    method public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean);
-    method public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int);
+    method @NonNull public android.net.metrics.ValidationProbeEvent build();
+    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long);
+    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean);
+    method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int);
   }
 
 }
@@ -2393,6 +2408,7 @@
     method public int getEventType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.ActivityEvent> CREATOR;
+    field public static final int TYPE_ACTIVITY_DESTROYED = 24; // 0x18
     field public static final int TYPE_ACTIVITY_PAUSED = 2; // 0x2
     field public static final int TYPE_ACTIVITY_RESUMED = 1; // 0x1
     field public static final int TYPE_ACTIVITY_STOPPED = 23; // 0x17
@@ -2411,6 +2427,7 @@
     method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
     method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
     field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
+    field public static final String SERVICE_META_DATA = "android.content_capture";
   }
 
   public final class SnapshotData implements android.os.Parcelable {
@@ -3169,10 +3186,6 @@
 
 package android.view.inspector {
 
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public @interface InspectableNodeName {
-    method public abstract String value();
-  }
-
   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD}) public @interface InspectableProperty {
     method public abstract int attributeId() default android.content.res.Resources.ID_NULL;
     method public abstract android.view.inspector.InspectableProperty.EnumEntry[] enumMapping() default {};
diff --git a/cmds/idmap2/idmap2/Commands.h b/cmds/idmap2/idmap2/Commands.h
index dcc69b3..718e361 100644
--- a/cmds/idmap2/idmap2/Commands.h
+++ b/cmds/idmap2/idmap2/Commands.h
@@ -20,10 +20,12 @@
 #include <string>
 #include <vector>
 
-bool Create(const std::vector<std::string>& args, std::ostream& out_error);
-bool Dump(const std::vector<std::string>& args, std::ostream& out_error);
-bool Lookup(const std::vector<std::string>& args, std::ostream& out_error);
-bool Scan(const std::vector<std::string>& args, std::ostream& out_error);
-bool Verify(const std::vector<std::string>& args, std::ostream& out_error);
+#include "idmap2/Result.h"
+
+android::idmap2::Result<android::idmap2::Unit> Create(const std::vector<std::string>& args);
+android::idmap2::Result<android::idmap2::Unit> Dump(const std::vector<std::string>& args);
+android::idmap2::Result<android::idmap2::Unit> Lookup(const std::vector<std::string>& args);
+android::idmap2::Result<android::idmap2::Unit> Scan(const std::vector<std::string>& args);
+android::idmap2::Result<android::idmap2::Unit> Verify(const std::vector<std::string>& args);
 
 #endif  // IDMAP2_IDMAP2_COMMANDS_H_
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index c416fa1..fdbb210 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -33,14 +33,17 @@
 using android::ApkAssets;
 using android::idmap2::BinaryStreamVisitor;
 using android::idmap2::CommandLineOptions;
+using android::idmap2::Error;
 using android::idmap2::Idmap;
 using android::idmap2::PoliciesToBitmask;
 using android::idmap2::PolicyBitmask;
 using android::idmap2::PolicyFlags;
+using android::idmap2::Result;
+using android::idmap2::Unit;
 using android::idmap2::utils::kIdmapFilePermissionMask;
 using android::idmap2::utils::UidHasWriteAccessToPath;
 
-bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
+Result<Unit> Create(const std::vector<std::string>& args) {
   SYSTRACE << "Create " << args;
   std::string target_apk_path;
   std::string overlay_apk_path;
@@ -63,15 +66,14 @@
                           &policies)
           .OptionalFlag("--ignore-overlayable", "disables overlayable and policy checks",
                         &ignore_overlayable);
-  if (!opts.Parse(args, out_error)) {
-    return false;
+  const auto opts_ok = opts.Parse(args);
+  if (!opts_ok) {
+    return opts_ok.GetError();
   }
 
   const uid_t uid = getuid();
   if (!UidHasWriteAccessToPath(uid, idmap_path)) {
-    out_error << "error: uid " << uid << " does not have write access to " << idmap_path
-              << std::endl;
-    return false;
+    return Error("uid %d does not have write access to %s", uid, idmap_path.c_str());
   }
 
   PolicyBitmask fulfilled_policies = 0;
@@ -79,8 +81,7 @@
   if (conv_result) {
     fulfilled_policies |= *conv_result;
   } else {
-    out_error << "error: " << conv_result.GetErrorMessage() << std::endl;
-    return false;
+    return conv_result.GetError();
   }
 
   if (fulfilled_policies == 0) {
@@ -89,36 +90,33 @@
 
   const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
   if (!target_apk) {
-    out_error << "error: failed to load apk " << target_apk_path << std::endl;
-    return false;
+    return Error("failed to load apk %s", target_apk_path.c_str());
   }
 
   const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
   if (!overlay_apk) {
-    out_error << "error: failed to load apk " << overlay_apk_path << std::endl;
-    return false;
+    return Error("failed to load apk %s", overlay_apk_path.c_str());
   }
 
+  std::stringstream stream;
   const std::unique_ptr<const Idmap> idmap =
       Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           fulfilled_policies, !ignore_overlayable, out_error);
+                           fulfilled_policies, !ignore_overlayable, stream);
   if (!idmap) {
-    return false;
+    return Error("failed to create idmap: %s", stream.str().c_str());
   }
 
   umask(kIdmapFilePermissionMask);
   std::ofstream fout(idmap_path);
   if (fout.fail()) {
-    out_error << "failed to open idmap path " << idmap_path << std::endl;
-    return false;
+    return Error("failed to open idmap path %s", idmap_path.c_str());
   }
   BinaryStreamVisitor visitor(fout);
   idmap->accept(&visitor);
   fout.close();
   if (fout.fail()) {
-    out_error << "failed to write to idmap path " << idmap_path << std::endl;
-    return false;
+    return Error("failed to write to idmap path %s", idmap_path.c_str());
   }
 
-  return true;
+  return Unit{};
 }
diff --git a/cmds/idmap2/idmap2/Dump.cpp b/cmds/idmap2/idmap2/Dump.cpp
index 3947703..fd58222 100644
--- a/cmds/idmap2/idmap2/Dump.cpp
+++ b/cmds/idmap2/idmap2/Dump.cpp
@@ -17,6 +17,7 @@
 #include <fstream>
 #include <iostream>
 #include <memory>
+#include <sstream>
 #include <string>
 #include <vector>
 
@@ -24,14 +25,18 @@
 #include "idmap2/Idmap.h"
 #include "idmap2/PrettyPrintVisitor.h"
 #include "idmap2/RawPrintVisitor.h"
+#include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 
 using android::idmap2::CommandLineOptions;
+using android::idmap2::Error;
 using android::idmap2::Idmap;
 using android::idmap2::PrettyPrintVisitor;
 using android::idmap2::RawPrintVisitor;
+using android::idmap2::Result;
+using android::idmap2::Unit;
 
-bool Dump(const std::vector<std::string>& args, std::ostream& out_error) {
+Result<Unit> Dump(const std::vector<std::string>& args) {
   SYSTRACE << "Dump " << args;
   std::string idmap_path;
   bool verbose;
@@ -40,14 +45,16 @@
       CommandLineOptions("idmap2 dump")
           .MandatoryOption("--idmap-path", "input: path to idmap file to pretty-print", &idmap_path)
           .OptionalFlag("--verbose", "annotate every byte of the idmap", &verbose);
-  if (!opts.Parse(args, out_error)) {
-    return false;
+  const auto opts_ok = opts.Parse(args);
+  if (!opts_ok) {
+    return opts_ok.GetError();
   }
+  std::stringstream stream;
   std::ifstream fin(idmap_path);
-  const std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, out_error);
+  const std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, stream);
   fin.close();
   if (!idmap) {
-    return false;
+    return Error("failed to load idmap: %s", stream.str().c_str());
   }
 
   if (verbose) {
@@ -58,5 +65,5 @@
     idmap->accept(&visitor);
   }
 
-  return true;
+  return Unit{};
 }
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index 83a40ef..677c6fa 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -57,6 +57,7 @@
 using android::idmap2::IdmapHeader;
 using android::idmap2::ResourceId;
 using android::idmap2::Result;
+using android::idmap2::Unit;
 using android::idmap2::Xml;
 using android::idmap2::ZipFile;
 using android::util::Utf16ToUtf8;
@@ -157,7 +158,7 @@
 }
 }  // namespace
 
-bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) {
+Result<Unit> Lookup(const std::vector<std::string>& args) {
   SYSTRACE << "Lookup " << args;
   std::vector<std::string> idmap_paths;
   std::string config_str;
@@ -172,14 +173,14 @@
                            "'[package:]type/name') to look up",
                            &resid_str);
 
-  if (!opts.Parse(args, out_error)) {
-    return false;
+  const auto opts_ok = opts.Parse(args);
+  if (!opts_ok) {
+    return opts_ok.GetError();
   }
 
   ConfigDescription config;
   if (!ConfigDescription::Parse(config_str, &config)) {
-    out_error << "error: failed to parse config" << std::endl;
-    return false;
+    return Error("failed to parse config");
   }
 
   std::vector<std::unique_ptr<const ApkAssets>> apk_assets;
@@ -191,39 +192,33 @@
     auto idmap_header = IdmapHeader::FromBinaryStream(fin);
     fin.close();
     if (!idmap_header) {
-      out_error << "error: failed to read idmap from " << idmap_path << std::endl;
-      return false;
+      return Error("failed to read idmap from %s", idmap_path.c_str());
     }
 
     if (i == 0) {
       target_path = idmap_header->GetTargetPath().to_string();
       auto target_apk = ApkAssets::Load(target_path);
       if (!target_apk) {
-        out_error << "error: failed to read target apk from " << target_path << std::endl;
-        return false;
+        return Error("failed to read target apk from %s", target_path.c_str());
       }
       apk_assets.push_back(std::move(target_apk));
 
       const Result<std::string> package_name =
           GetTargetPackageNameFromManifest(idmap_header->GetOverlayPath().to_string());
       if (!package_name) {
-        out_error << "error: failed to parse android:targetPackage from overlay manifest"
-                  << std::endl;
-        return false;
+        return Error("failed to parse android:targetPackage from overlay manifest");
       }
       target_package_name = *package_name;
     } else if (target_path != idmap_header->GetTargetPath()) {
-      out_error << "error: different target APKs (expected target APK " << target_path << " but "
-                << idmap_path << " has target APK " << idmap_header->GetTargetPath() << ")"
-                << std::endl;
-      return false;
+      return Error("different target APKs (expected target APK %s but %s has target APK %s)",
+                   target_path.c_str(), idmap_path.c_str(),
+                   idmap_header->GetTargetPath().to_string().c_str());
     }
 
     auto overlay_apk = ApkAssets::LoadOverlay(idmap_path);
     if (!overlay_apk) {
-      out_error << "error: failed to read overlay apk from " << idmap_header->GetOverlayPath()
-                << std::endl;
-      return false;
+      return Error("failed to read overlay apk from %s",
+                   idmap_header->GetOverlayPath().to_string().c_str());
     }
     apk_assets.push_back(std::move(overlay_apk));
   }
@@ -238,16 +233,14 @@
 
   const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name);
   if (!resid) {
-    out_error << "error: failed to parse resource ID" << std::endl;
-    return false;
+    return Error(resid.GetError(), "failed to parse resource ID");
   }
 
   const Result<std::string> value = GetValue(am, *resid);
   if (!value) {
-    out_error << StringPrintf("error: resource 0x%08x not found", *resid) << std::endl;
-    return false;
+    return Error(value.GetError(), "resource 0x%08x not found", *resid);
   }
   std::cout << *value << std::endl;
 
-  return true;
+  return Unit{};
 }
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index a0ffccb..d8867fe 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -24,14 +24,17 @@
 #include <vector>
 
 #include "idmap2/CommandLineOptions.h"
+#include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 
 #include "Commands.h"
 
 using android::idmap2::CommandLineOptions;
+using android::idmap2::Result;
+using android::idmap2::Unit;
 
 using NameToFunctionMap =
-    std::map<std::string, std::function<bool(const std::vector<std::string>&, std::ostream&)>>;
+    std::map<std::string, std::function<Result<Unit>(const std::vector<std::string>&)>>;
 
 namespace {
 
@@ -69,5 +72,10 @@
     PrintUsage(commands, std::cerr);
     return EXIT_FAILURE;
   }
-  return iter->second(*args, std::cerr) ? EXIT_SUCCESS : EXIT_FAILURE;
+  const auto result = iter->second(*args);
+  if (!result) {
+    std::cerr << "error: " << result.GetErrorMessage() << std::endl;
+    return EXIT_FAILURE;
+  }
+  return EXIT_SUCCESS;
 }
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index e85f132..24331af 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -30,6 +30,7 @@
 #include "idmap2/FileUtils.h"
 #include "idmap2/Idmap.h"
 #include "idmap2/ResourceUtils.h"
+#include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 #include "idmap2/Xml.h"
 #include "idmap2/ZipFile.h"
@@ -37,6 +38,7 @@
 #include "Commands.h"
 
 using android::idmap2::CommandLineOptions;
+using android::idmap2::Error;
 using android::idmap2::Idmap;
 using android::idmap2::kPolicyProduct;
 using android::idmap2::kPolicyPublic;
@@ -45,6 +47,7 @@
 using android::idmap2::PolicyBitmask;
 using android::idmap2::PolicyFlags;
 using android::idmap2::Result;
+using android::idmap2::Unit;
 using android::idmap2::utils::ExtractOverlayManifestInfo;
 using android::idmap2::utils::FindFiles;
 using android::idmap2::utils::OverlayManifestInfo;
@@ -69,8 +72,8 @@
   return version == "Q" || version == "q";
 }
 
-std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::string>& dirs,
-                                                       bool recursive, std::ostream& out_error) {
+Result<std::unique_ptr<std::vector<std::string>>> FindApkFiles(const std::vector<std::string>& dirs,
+                                                               bool recursive) {
   SYSTRACE << "FindApkFiles " << dirs << " " << recursive;
   const auto predicate = [](unsigned char type, const std::string& path) -> bool {
     static constexpr size_t kExtLen = 4;  // strlen(".apk")
@@ -82,8 +85,7 @@
   for (const auto& dir : dirs) {
     const auto apk_paths = FindFiles(dir, recursive, predicate);
     if (!apk_paths) {
-      out_error << "error: failed to open directory " << dir << std::endl;
-      return nullptr;
+      return Error("failed to open directory %s", dir.c_str());
     }
     paths.insert(apk_paths->cbegin(), apk_paths->cend());
   }
@@ -110,7 +112,7 @@
 
 }  // namespace
 
-bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
+Result<Unit> Scan(const std::vector<std::string>& args) {
   SYSTRACE << "Scan " << args;
   std::vector<std::string> input_directories;
   std::string target_package_name;
@@ -135,22 +137,22 @@
               "input: an overlayable policy this overlay fulfills "
               "(if none or supplied, the overlays will not have their policies overriden",
               &override_policies);
-  if (!opts.Parse(args, out_error)) {
-    return false;
+  const auto opts_ok = opts.Parse(args);
+  if (!opts_ok) {
+    return opts_ok.GetError();
   }
 
-  const auto apk_paths = FindApkFiles(input_directories, recursive, out_error);
+  const auto apk_paths = FindApkFiles(input_directories, recursive);
   if (!apk_paths) {
-    return false;
+    return Error(apk_paths.GetError(), "failed to find apk files");
   }
 
   std::vector<InputOverlay> interesting_apks;
-  for (const std::string& path : *apk_paths) {
+  for (const std::string& path : **apk_paths) {
     Result<OverlayManifestInfo> overlay_info =
         ExtractOverlayManifestInfo(path, /* assert_overlay */ false);
     if (!overlay_info) {
-      out_error << "error: " << overlay_info.GetErrorMessage() << std::endl;
-      return false;
+      return overlay_info.GetError();
     }
 
     if (!overlay_info->is_static) {
@@ -194,16 +196,13 @@
 
   std::stringstream stream;
   for (const auto& overlay : interesting_apks) {
-    // Create the idmap for the overlay if it currently does not exist or if it is not up to date.
-    std::stringstream dev_null;
-
     std::vector<std::string> verify_args = {"--idmap-path", overlay.idmap_path};
     for (const std::string& policy : overlay.policies) {
       verify_args.emplace_back("--policy");
       verify_args.emplace_back(policy);
     }
 
-    if (!Verify(std::vector<std::string>(verify_args), dev_null)) {
+    if (!Verify(std::vector<std::string>(verify_args))) {
       std::vector<std::string> create_args = {"--target-apk-path",  target_apk_path,
                                               "--overlay-apk-path", overlay.apk_path,
                                               "--idmap-path",       overlay.idmap_path};
@@ -216,8 +215,9 @@
         create_args.emplace_back(policy);
       }
 
-      if (!Create(create_args, out_error)) {
-        return false;
+      const auto create_ok = Create(create_args);
+      if (!create_ok) {
+        return Error(create_ok.GetError(), "failed to create idmap");
       }
     }
 
@@ -226,5 +226,5 @@
 
   std::cout << stream.str();
 
-  return true;
+  return Unit{};
 }
diff --git a/cmds/idmap2/idmap2/Verify.cpp b/cmds/idmap2/idmap2/Verify.cpp
index d8fe7aa..9cb67b3 100644
--- a/cmds/idmap2/idmap2/Verify.cpp
+++ b/cmds/idmap2/idmap2/Verify.cpp
@@ -21,29 +21,39 @@
 
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/Idmap.h"
+#include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 
 using android::idmap2::CommandLineOptions;
+using android::idmap2::Error;
 using android::idmap2::IdmapHeader;
+using android::idmap2::Result;
+using android::idmap2::Unit;
 
-bool Verify(const std::vector<std::string>& args, std::ostream& out_error) {
+Result<Unit> Verify(const std::vector<std::string>& args) {
   SYSTRACE << "Verify " << args;
   std::string idmap_path;
 
   const CommandLineOptions opts =
       CommandLineOptions("idmap2 verify")
           .MandatoryOption("--idmap-path", "input: path to idmap file to verify", &idmap_path);
-  if (!opts.Parse(args, out_error)) {
-    return false;
+
+  const auto opts_ok = opts.Parse(args);
+  if (!opts_ok) {
+    return opts_ok.GetError();
   }
 
   std::ifstream fin(idmap_path);
   const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin);
   fin.close();
   if (!header) {
-    out_error << "error: failed to parse idmap header" << std::endl;
-    return false;
+    return Error("failed to parse idmap header");
   }
 
-  return header->IsUpToDate(out_error);
+  const auto header_ok = header->IsUpToDate();
+  if (!header_ok) {
+    return Error(header_ok.GetError(), "idmap not up to date");
+  }
+
+  return Unit{};
 }
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index fa94414..e03a9cc 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -104,8 +104,7 @@
   std::ifstream fin(idmap_path);
   const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin);
   fin.close();
-  std::stringstream dev_null;
-  *_aidl_return = header && header->IsUpToDate(dev_null);
+  *_aidl_return = header && header->IsUpToDate();
 
   // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed
 
diff --git a/cmds/idmap2/include/idmap2/CommandLineOptions.h b/cmds/idmap2/include/idmap2/CommandLineOptions.h
index 6db6bf9..52ac818 100644
--- a/cmds/idmap2/include/idmap2/CommandLineOptions.h
+++ b/cmds/idmap2/include/idmap2/CommandLineOptions.h
@@ -23,6 +23,8 @@
 #include <string>
 #include <vector>
 
+#include "idmap2/Result.h"
+
 namespace android::idmap2 {
 
 /*
@@ -46,7 +48,7 @@
                                      std::string* value);
   CommandLineOptions& OptionalOption(const std::string& name, const std::string& description,
                                      std::vector<std::string>* value);
-  bool Parse(const std::vector<std::string>& argv, std::ostream& outError) const;
+  Result<Unit> Parse(const std::vector<std::string>& argv) const;
   void Usage(std::ostream& out) const;
 
  private:
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 1666dc8..673d18d 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -115,7 +115,7 @@
   // Invariant: anytime the idmap data encoding is changed, the idmap version
   // field *must* be incremented. Because of this, we know that if the idmap
   // header is up-to-date the entire file is up-to-date.
-  bool IsUpToDate(std::ostream& out_error) const;
+  Result<Unit> IsUpToDate() const;
 
   void accept(Visitor* v) const;
 
diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
index a49a607..d5fd2ce 100644
--- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp
+++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
@@ -19,12 +19,14 @@
 #include <iostream>
 #include <memory>
 #include <set>
+#include <sstream>
 #include <string>
 #include <vector>
 
 #include "android-base/macros.h"
 
 #include "idmap2/CommandLineOptions.h"
+#include "idmap2/Result.h"
 
 namespace android::idmap2 {
 
@@ -77,7 +79,7 @@
   return *this;
 }
 
-bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostream& outError) const {
+Result<Unit> CommandLineOptions::Parse(const std::vector<std::string>& argv) const {
   const auto pivot = std::partition(options_.begin(), options_.end(), [](const Option& opt) {
     return opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE;
   });
@@ -89,8 +91,9 @@
   for (size_t i = 0; i < argv_size; i++) {
     const std::string arg = argv[i];
     if ("--help" == arg || "-h" == arg) {
-      Usage(outError);
-      return false;
+      std::stringstream stream;
+      Usage(stream);
+      return Error("%s", stream.str().c_str());
     }
     bool match = false;
     for (const Option& opt : options_) {
@@ -100,9 +103,9 @@
         if (opt.argument) {
           i++;
           if (i >= argv_size) {
-            outError << "error: " << opt.name << ": missing argument" << std::endl;
-            Usage(outError);
-            return false;
+            std::stringstream stream;
+            Usage(stream);
+            return Error("%s: missing argument\n%s", opt.name.c_str(), stream.str().c_str());
           }
         }
         opt.action(argv[i]);
@@ -111,20 +114,27 @@
       }
     }
     if (!match) {
-      outError << "error: " << arg << ": unknown option" << std::endl;
-      Usage(outError);
-      return false;
+      std::stringstream stream;
+      Usage(stream);
+      return Error("%s: unknown option\n%s", arg.c_str(), stream.str().c_str());
     }
   }
 
   if (!mandatory_opts.empty()) {
+    std::stringstream stream;
+    bool separator = false;
     for (const auto& opt : mandatory_opts) {
-      outError << "error: " << opt << ": missing mandatory option" << std::endl;
+      if (separator) {
+        stream << ", ";
+      }
+      separator = true;
+      stream << opt << ": missing mandatory option";
     }
-    Usage(outError);
-    return false;
+    stream << std::endl;
+    Usage(stream);
+    return Error("%s", stream.str().c_str());
   }
-  return true;
+  return Unit{};
 }
 
 void CommandLineOptions::Usage(std::ostream& out) const {
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index a7d180c..e8e19d8 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -56,7 +56,7 @@
   }
 
   inline const std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>>& WARN_UNUSED
-      Map() const {
+  Map() const {
     return map_;
   }
 
@@ -142,62 +142,46 @@
   return std::move(idmap_header);
 }
 
-bool IdmapHeader::IsUpToDate(std::ostream& out_error) const {
+Result<Unit> IdmapHeader::IsUpToDate() const {
   if (magic_ != kIdmapMagic) {
-    out_error << base::StringPrintf("error: bad magic: actual 0x%08x, expected 0x%08x", magic_,
-                                    kIdmapMagic)
-              << std::endl;
-    return false;
+    return Error("bad magic: actual 0x%08x, expected 0x%08x", magic_, kIdmapMagic);
   }
 
   if (version_ != kIdmapCurrentVersion) {
-    out_error << base::StringPrintf("error: bad version: actual 0x%08x, expected 0x%08x", version_,
-                                    kIdmapCurrentVersion)
-              << std::endl;
-    return false;
+    return Error("bad version: actual 0x%08x, expected 0x%08x", version_, kIdmapCurrentVersion);
   }
 
   const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_path_);
   if (!target_zip) {
-    out_error << "error: failed to open target " << target_path_ << std::endl;
-    return false;
+    return Error("failed to open target %s", GetTargetPath().to_string().c_str());
   }
 
   Result<uint32_t> target_crc = GetCrc(*target_zip);
   if (!target_crc) {
-    out_error << "error: failed to get target crc" << std::endl;
-    return false;
+    return Error("failed to get target crc");
   }
 
   if (target_crc_ != *target_crc) {
-    out_error << base::StringPrintf(
-                     "error: bad target crc: idmap version 0x%08x, file system version 0x%08x",
-                     target_crc_, *target_crc)
-              << std::endl;
-    return false;
+    return Error("bad target crc: idmap version 0x%08x, file system version 0x%08x", target_crc_,
+                 *target_crc);
   }
 
   const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_path_);
   if (!overlay_zip) {
-    out_error << "error: failed to open overlay " << overlay_path_ << std::endl;
-    return false;
+    return Error("failed to open overlay %s", GetOverlayPath().to_string().c_str());
   }
 
   Result<uint32_t> overlay_crc = GetCrc(*overlay_zip);
   if (!overlay_crc) {
-    out_error << "error: failed to get overlay crc" << std::endl;
-    return false;
+    return Error("failed to get overlay crc");
   }
 
   if (overlay_crc_ != *overlay_crc) {
-    out_error << base::StringPrintf(
-                     "error: bad overlay crc: idmap version 0x%08x, file system version 0x%08x",
-                     overlay_crc_, *overlay_crc)
-              << std::endl;
-    return false;
+    return Error("bad overlay crc: idmap version 0x%08x, file system version 0x%08x", overlay_crc_,
+                 *overlay_crc);
   }
 
-  return true;
+  return Unit{};
 }
 
 std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) {
@@ -452,7 +436,7 @@
       continue;
     }
 
-    if (!enforce_overlayable) {
+    if (enforce_overlayable) {
       Result<Unit> success =
           CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid);
       if (!success) {
diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
index 39f18d3..d567af6 100644
--- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp
+++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
@@ -46,14 +46,13 @@
   CommandLineOptions opts =
       CommandLineOptions("test").OptionalFlag("--foo", "", &foo).OptionalFlag("--bar", "", &bar);
 
-  std::ostream fakeStdErr(nullptr);
-  bool success = opts.Parse({"--foo", "--bar"}, fakeStdErr);
+  auto success = opts.Parse({"--foo", "--bar"});
   ASSERT_TRUE(success);
   ASSERT_TRUE(foo);
   ASSERT_TRUE(bar);
 
   foo = bar = false;
-  success = opts.Parse({"--foo"}, fakeStdErr);
+  success = opts.Parse({"--foo"});
   ASSERT_TRUE(success);
   ASSERT_TRUE(foo);
   ASSERT_FALSE(bar);
@@ -65,21 +64,19 @@
   CommandLineOptions opts = CommandLineOptions("test")
                                 .MandatoryOption("--foo", "", &foo)
                                 .MandatoryOption("--bar", "", &bar);
-  std::ostream fakeStdErr(nullptr);
-  bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr);
+  auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"});
   ASSERT_TRUE(success);
   ASSERT_EQ(foo, "FOO");
   ASSERT_EQ(bar, "BAR");
 
-  success = opts.Parse({"--foo"}, fakeStdErr);
+  success = opts.Parse({"--foo"});
   ASSERT_FALSE(success);
 }
 
 TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsButExpectedOnce) {
   std::string foo;
   CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &foo);
-  std::ostream fakeStdErr(nullptr);
-  bool success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"}, fakeStdErr);
+  auto success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"});
   ASSERT_TRUE(success);
   ASSERT_EQ(foo, "SECOND");
 }
@@ -87,8 +84,7 @@
 TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsAndExpectedOnceOrMore) {
   std::vector<std::string> args;
   CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &args);
-  std::ostream fakeStdErr(nullptr);
-  bool success = opts.Parse({"--foo", "FOO", "--foo", "BAR"}, fakeStdErr);
+  auto success = opts.Parse({"--foo", "FOO", "--foo", "BAR"});
   ASSERT_TRUE(success);
   ASSERT_EQ(args.size(), 2U);
   ASSERT_EQ(args[0], "FOO");
@@ -101,23 +97,22 @@
   CommandLineOptions opts = CommandLineOptions("test")
                                 .OptionalOption("--foo", "", &foo)
                                 .OptionalOption("--bar", "", &bar);
-  std::ostream fakeStdErr(nullptr);
-  bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr);
+  auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"});
   ASSERT_TRUE(success);
   ASSERT_EQ(foo, "FOO");
   ASSERT_EQ(bar, "BAR");
 
-  success = opts.Parse({"--foo", "BAZ"}, fakeStdErr);
+  success = opts.Parse({"--foo", "BAZ"});
   ASSERT_TRUE(success);
   ASSERT_EQ(foo, "BAZ");
 
-  success = opts.Parse({"--foo"}, fakeStdErr);
+  success = opts.Parse({"--foo"});
   ASSERT_FALSE(success);
 
-  success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr);
+  success = opts.Parse({"--foo", "--bar", "BAR"});
   ASSERT_FALSE(success);
 
-  success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr);
+  success = opts.Parse({"--foo", "FOO", "--bar"});
   ASSERT_FALSE(success);
 }
 
@@ -127,8 +122,7 @@
   CommandLineOptions opts = CommandLineOptions("test")
                                 .OptionalOption("--foo", "", &foo)
                                 .OptionalOption("--bar", "", &bar);
-  std::ostream fakeStdErr(nullptr);
-  bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr);
+  auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"});
   ASSERT_TRUE(success);
   ASSERT_EQ(foo.size(), 1U);
   ASSERT_EQ(foo[0], "FOO");
@@ -137,7 +131,7 @@
 
   foo.clear();
   bar.clear();
-  success = opts.Parse({"--foo", "BAZ"}, fakeStdErr);
+  success = opts.Parse({"--foo", "BAZ"});
   ASSERT_TRUE(success);
   ASSERT_EQ(foo.size(), 1U);
   ASSERT_EQ(foo[0], "BAZ");
@@ -145,8 +139,7 @@
 
   foo.clear();
   bar.clear();
-  success =
-      opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}, fakeStdErr);
+  success = opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"});
   ASSERT_TRUE(success);
   ASSERT_EQ(foo.size(), 2U);
   ASSERT_EQ(foo[0], "BAZ");
@@ -157,17 +150,17 @@
 
   foo.clear();
   bar.clear();
-  success = opts.Parse({"--foo"}, fakeStdErr);
+  success = opts.Parse({"--foo"});
   ASSERT_FALSE(success);
 
   foo.clear();
   bar.clear();
-  success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr);
+  success = opts.Parse({"--foo", "--bar", "BAR"});
   ASSERT_FALSE(success);
 
   foo.clear();
   bar.clear();
-  success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr);
+  success = opts.Parse({"--foo", "FOO", "--bar"});
   ASSERT_FALSE(success);
 }
 
@@ -179,14 +172,13 @@
                                 .MandatoryOption("--foo", "", &foo)
                                 .OptionalFlag("--baz", "", &baz)
                                 .OptionalOption("--bar", "", &bar);
-  std::ostream fakeStdErr(nullptr);
-  bool success = opts.Parse({"--unexpected"}, fakeStdErr);
+  auto success = opts.Parse({"--unexpected"});
   ASSERT_FALSE(success);
 
-  success = opts.Parse({"--bar", "BAR"}, fakeStdErr);
+  success = opts.Parse({"--bar", "BAR"});
   ASSERT_FALSE(success);
 
-  success = opts.Parse({"--baz", "--foo", "FOO"}, fakeStdErr);
+  success = opts.Parse({"--baz", "--foo", "FOO"});
   ASSERT_TRUE(success);
   ASSERT_TRUE(baz);
   ASSERT_EQ(foo, "FOO");
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 8d65428..c20ae7b 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -501,7 +501,7 @@
 
   std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
   ASSERT_THAT(header, NotNull());
-  ASSERT_TRUE(header->IsUpToDate(error)) << error.str();
+  ASSERT_TRUE(header->IsUpToDate());
 
   // magic: bytes (0x0, 0x03)
   std::string bad_magic_string(stream.str());
@@ -514,7 +514,7 @@
       IdmapHeader::FromBinaryStream(bad_magic_stream);
   ASSERT_THAT(bad_magic_header, NotNull());
   ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic());
-  ASSERT_FALSE(bad_magic_header->IsUpToDate(error));
+  ASSERT_FALSE(bad_magic_header->IsUpToDate());
 
   // version: bytes (0x4, 0x07)
   std::string bad_version_string(stream.str());
@@ -527,7 +527,7 @@
       IdmapHeader::FromBinaryStream(bad_version_stream);
   ASSERT_THAT(bad_version_header, NotNull());
   ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion());
-  ASSERT_FALSE(bad_version_header->IsUpToDate(error));
+  ASSERT_FALSE(bad_version_header->IsUpToDate());
 
   // target crc: bytes (0x8, 0xb)
   std::string bad_target_crc_string(stream.str());
@@ -540,7 +540,7 @@
       IdmapHeader::FromBinaryStream(bad_target_crc_stream);
   ASSERT_THAT(bad_target_crc_header, NotNull());
   ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
-  ASSERT_FALSE(bad_target_crc_header->IsUpToDate(error));
+  ASSERT_FALSE(bad_target_crc_header->IsUpToDate());
 
   // overlay crc: bytes (0xc, 0xf)
   std::string bad_overlay_crc_string(stream.str());
@@ -553,7 +553,7 @@
       IdmapHeader::FromBinaryStream(bad_overlay_crc_stream);
   ASSERT_THAT(bad_overlay_crc_header, NotNull());
   ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
-  ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate(error));
+  ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate());
 
   // target path: bytes (0x10, 0x10f)
   std::string bad_target_path_string(stream.str());
@@ -563,7 +563,7 @@
       IdmapHeader::FromBinaryStream(bad_target_path_stream);
   ASSERT_THAT(bad_target_path_header, NotNull());
   ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
-  ASSERT_FALSE(bad_target_path_header->IsUpToDate(error));
+  ASSERT_FALSE(bad_target_path_header->IsUpToDate());
 
   // overlay path: bytes (0x110, 0x20f)
   std::string bad_overlay_path_string(stream.str());
@@ -573,7 +573,7 @@
       IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
   ASSERT_THAT(bad_overlay_path_header, NotNull());
   ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath());
-  ASSERT_FALSE(bad_overlay_path_header->IsUpToDate(error));
+  ASSERT_FALSE(bad_overlay_path_header->IsUpToDate());
 }
 
 class TestVisitor : public Visitor {
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
index a7767a6..619bb6c 100644
--- a/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
@@ -16,6 +16,7 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="test.overlay">
+    <application android:hasCode="false"/>
     <overlay
         android:targetPackage="test.target"
         android:targetName="TestResources"/>
diff --git a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
index 5dacebd..9e6a453 100644
--- a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
@@ -16,6 +16,7 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="test.overlay.system">
+    <application android:hasCode="false"/>
     <overlay
         android:targetPackage="test.target"
         android:targetName="TestResources"/>
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml
index ae687d3..c7b652c 100644
--- a/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml
@@ -16,6 +16,7 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="test.overlay.system.invalid">
+    <application android:hasCode="false"/>
     <overlay
         android:targetPackage="test.target"
         android:targetName="TestResources"/>
diff --git a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
index 5dacebd..9e6a453 100644
--- a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
@@ -16,6 +16,7 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="test.overlay.system">
+    <application android:hasCode="false"/>
     <overlay
         android:targetPackage="test.target"
         android:targetName="TestResources"/>
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 1dbbbc5..d331c0f 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -2065,6 +2065,9 @@
     // HCI reason code associated with this event
     // Default: STATUS_UNKNOWN
     optional android.bluetooth.hci.StatusEnum reason_code = 6;
+    // A status value related to this specific event
+    // Default: 0
+    optional int64 event_value = 7;
 }
 
 /**
diff --git a/core/java/android/accessibilityservice/AccessibilityButtonController.java b/core/java/android/accessibilityservice/AccessibilityButtonController.java
index a70085c..af5af9c 100644
--- a/core/java/android/accessibilityservice/AccessibilityButtonController.java
+++ b/core/java/android/accessibilityservice/AccessibilityButtonController.java
@@ -17,7 +17,6 @@
 package android.accessibilityservice;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -76,13 +75,16 @@
      * available to the calling service, {@code false} otherwise
      */
     public boolean isAccessibilityButtonAvailable() {
-        try {
-            return mServiceConnection.isAccessibilityButtonAvailable();
-        } catch (RemoteException re) {
-            Slog.w(LOG_TAG, "Failed to get accessibility button availability.", re);
-            re.rethrowFromSystemServer();
-            return false;
+        if (mServiceConnection != null) {
+            try {
+                return mServiceConnection.isAccessibilityButtonAvailable();
+            } catch (RemoteException re) {
+                Slog.w(LOG_TAG, "Failed to get accessibility button availability.", re);
+                re.rethrowFromSystemServer();
+                return false;
+            }
         }
+        return false;
     }
 
     /**
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index f6cfe48..e8d3293 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -340,4 +340,21 @@
      * like persisting database etc.
      */
     public abstract void prepareForPossibleShutdown();
+
+    /**
+     * Returns {@code true} if {@code uid} is running a foreground service of a specific
+     * {@code foregroundServiceType}.
+     */
+    public abstract boolean hasRunningForegroundService(int uid, int foregroundServiceType);
+
+    /**
+     * Registers the specified {@code processObserver} to be notified of future changes to
+     * process state.
+     */
+    public abstract void registerProcessObserver(IProcessObserver processObserver);
+
+    /**
+     * Unregisters the specified {@code processObserver}.
+     */
+    public abstract void unregisterProcessObserver(IProcessObserver processObserver);
 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1066fc7..5ed4428 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -48,7 +48,6 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
-
 import com.android.internal.annotations.Immutable;
 import com.android.internal.app.IAppOpsActiveCallback;
 import com.android.internal.app.IAppOpsCallback;
@@ -1098,6 +1097,8 @@
     /** @hide Write media of image type. */
     public static final String OPSTR_WRITE_MEDIA_IMAGES = "android:write_media_images";
     /** @hide Has a legacy (non-isolated) view of storage. */
+    @TestApi
+    @SystemApi
     public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
     /** @hide Interact with accessibility. */
     @SystemApi
@@ -2153,6 +2154,7 @@
      *
      * @hide
      */
+    @TestApi
     @SystemApi
     public static int opToDefaultMode(@NonNull String appOp) {
         return opToDefaultMode(strOpToOp(appOp));
@@ -4465,7 +4467,7 @@
      * @hide
      */
     @TestApi
-    @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
+    @RequiresPermission(Manifest.permission.MANAGE_APPOPS)
     public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request,
             @Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) {
         Preconditions.checkNotNull(executor, "executor cannot be null");
@@ -4488,6 +4490,21 @@
     }
 
     /**
+     * Reloads the non historical state to allow testing the read/write path.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.MANAGE_APPOPS)
+    public void reloadNonHistoricalState() {
+        try {
+            mService.reloadNonHistoricalState();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Sets given app op in the specified mode for app ops in the UID.
      * This applies to all apps currently in the UID or installed in
      * this UID in the future.
@@ -4570,6 +4587,7 @@
      * be changed.
      * @hide
      */
+    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setMode(String op, int uid, String packageName, @Mode int mode) {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a226062..7a0639e 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3054,9 +3054,9 @@
     }
 
     @Override
-    public String getContentCaptureServicePackageName() {
+    public String getSystemCaptionsServicePackageName() {
         try {
-            return mPM.getContentCaptureServicePackageName();
+            return mPM.getSystemCaptionsServicePackageName();
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 15084de..7884872 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -70,6 +70,10 @@
     boolean areNotificationsEnabled(String pkg);
     int getPackageImportance(String pkg);
 
+    List<String> getAllowedAssistantCapabilities(String pkg);
+    void allowAssistantCapability(String adjustmentType);
+    void disallowAssistantCapability(String adjustmentType);
+
     boolean shouldHideSilentStatusIcons(String callingPkg);
     void setHideSilentStatusIcons(boolean hide);
 
@@ -86,10 +90,10 @@
     NotificationChannelGroup getPopulatedNotificationChannelGroupForPackage(String pkg, int uid, String groupId, boolean includeDeleted);
     void updateNotificationChannelGroupForPackage(String pkg, int uid, in NotificationChannelGroup group);
     void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
-    NotificationChannel getNotificationChannel(String pkg, String channelId);
+    NotificationChannel getNotificationChannel(String callingPkg, int userId, String pkg, String channelId);
     NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, boolean includeDeleted);
     void deleteNotificationChannel(String pkg, String channelId);
-    ParceledListSlice getNotificationChannels(String pkg);
+    ParceledListSlice getNotificationChannels(String callingPkg, String targetPkg, int userId);
     ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
     int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
     int getDeletedChannelCount(String pkg, int uid);
diff --git a/core/java/android/app/IProcessObserver.aidl b/core/java/android/app/IProcessObserver.aidl
index b436aa2..7be3620 100644
--- a/core/java/android/app/IProcessObserver.aidl
+++ b/core/java/android/app/IProcessObserver.aidl
@@ -19,5 +19,6 @@
 /** {@hide} */
 oneway interface IProcessObserver {
     void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities);
+    void onForegroundServicesChanged(int pid, int uid, int serviceTypes);
     void onProcessDied(int pid, int uid);
 }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 6a301c9..1aacf96 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -42,6 +42,7 @@
 import android.os.StrictMode;
 import android.os.UserHandle;
 import android.provider.Settings.Global;
+import android.service.notification.Adjustment;
 import android.service.notification.Condition;
 import android.service.notification.StatusBarNotification;
 import android.service.notification.ZenModeConfig;
@@ -715,12 +716,16 @@
     /**
      * Returns the notification channel settings for a given channel id.
      *
-     * The channel must belong to your package, or it will not be returned.
+     * <p>The channel must belong to your package, or to a package you are an approved notification
+     * delegate for (see {@link #canNotifyAsPackage(String)}), or it will not be returned. To query
+     * a channel as a notification delegate, call this method from a context created for that
+     * package (see {@link Context#createPackageContext(String, int)}).</p>
      */
     public NotificationChannel getNotificationChannel(String channelId) {
         INotificationManager service = getService();
         try {
-            return service.getNotificationChannel(mContext.getPackageName(), channelId);
+            return service.getNotificationChannel(mContext.getOpPackageName(),
+                    mContext.getUserId(), mContext.getPackageName(), channelId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -728,11 +733,17 @@
 
     /**
      * Returns all notification channels belonging to the calling package.
+     *
+     * <p>Approved notification delegates (see {@link #canNotifyAsPackage(String)}) can query
+     * notification channels belonging to packages they are the delegate for. To do so, call this
+     * method from a context created for that package (see
+     * {@link Context#createPackageContext(String, int)}).</p>
      */
     public List<NotificationChannel> getNotificationChannels() {
         INotificationManager service = getService();
         try {
-            return service.getNotificationChannels(mContext.getPackageName()).getList();
+            return service.getNotificationChannels(mContext.getOpPackageName(),
+                    mContext.getPackageName(), mContext.getUserId()).getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1182,6 +1193,25 @@
         }
     }
 
+    /**
+     * Returns the list of {@link android.service.notification.Adjustment adjustment keys} that can
+     * be modified by the current {@link android.service.notification.NotificationAssistantService}.
+     *
+     * <p>Only callable by the current
+     * {@link android.service.notification.NotificationAssistantService}.
+     * See {@link #isNotificationAssistantAccessGranted(ComponentName)}</p>
+     * @hide
+     */
+    @SystemApi
+    public @NonNull @Adjustment.Keys List<String> getAllowedAssistantCapabilities() {
+        INotificationManager service = getService();
+        try {
+            return service.getAllowedAssistantCapabilities(mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
         INotificationManager service = getService();
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index bcc4974..25caaaa 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -16,6 +16,7 @@
 
 package android.app.backup;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
@@ -502,32 +503,76 @@
      * @param transportComponent The identity of the transport being described.
      * @param name A {@link String} with the new name for the transport. This is NOT for
      *     identification. MUST NOT be {@code null}.
-     * @param configurationIntent An {@link Intent} that can be passed to
-     *     {@link Context#startActivity} in order to launch the transport's configuration UI. It may
-     *     be {@code null} if the transport does not offer any user-facing configuration UI.
+     * @param configurationIntent An {@link Intent} that can be passed to {@link
+     *     Context#startActivity} in order to launch the transport's configuration UI. It may be
+     *     {@code null} if the transport does not offer any user-facing configuration UI.
      * @param currentDestinationString A {@link String} describing the destination to which the
      *     transport is currently sending data. MUST NOT be {@code null}.
-     * @param dataManagementIntent An {@link Intent} that can be passed to
-     *     {@link Context#startActivity} in order to launch the transport's data-management UI. It
-     *     may be {@code null} if the transport does not offer any user-facing data
-     *     management UI.
+     * @param dataManagementIntent An {@link Intent} that can be passed to {@link
+     *     Context#startActivity} in order to launch the transport's data-management UI. It may be
+     *     {@code null} if the transport does not offer any user-facing data management UI.
      * @param dataManagementLabel A {@link String} to be used as the label for the transport's data
-     *     management affordance. This MUST be {@code null} when dataManagementIntent is
-     *     {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
+     *     management affordance. This MUST be {@code null} when dataManagementIntent is {@code
+     *     null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
      * @throws SecurityException If the UID of the calling process differs from the package UID of
      *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
+     * @deprecated Since Android Q, please use the variant {@link
+     *     #updateTransportAttributes(ComponentName, String, Intent, String, Intent, CharSequence)}
+     *     instead.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
+    public void updateTransportAttributes(
+            @NonNull ComponentName transportComponent,
+            @NonNull String name,
+            @Nullable Intent configurationIntent,
+            @NonNull String currentDestinationString,
+            @Nullable Intent dataManagementIntent,
+            @Nullable String dataManagementLabel) {
+        updateTransportAttributes(
+                transportComponent,
+                name,
+                configurationIntent,
+                currentDestinationString,
+                dataManagementIntent,
+                (CharSequence) dataManagementLabel);
+    }
+
+    /**
+     * Update the attributes of the transport identified by {@code transportComponent}. If the
+     * specified transport has not been bound at least once (for registration), this call will be
+     * ignored. Only the host process of the transport can change its description, otherwise a
+     * {@link SecurityException} will be thrown.
      *
+     * @param transportComponent The identity of the transport being described.
+     * @param name A {@link String} with the new name for the transport. This is NOT for
+     *     identification. MUST NOT be {@code null}.
+     * @param configurationIntent An {@link Intent} that can be passed to {@link
+     *     Context#startActivity} in order to launch the transport's configuration UI. It may be
+     *     {@code null} if the transport does not offer any user-facing configuration UI.
+     * @param currentDestinationString A {@link String} describing the destination to which the
+     *     transport is currently sending data. MUST NOT be {@code null}.
+     * @param dataManagementIntent An {@link Intent} that can be passed to {@link
+     *     Context#startActivity} in order to launch the transport's data-management UI. It may be
+     *     {@code null} if the transport does not offer any user-facing data management UI.
+     * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's
+     *     data management affordance. This MUST be {@code null} when dataManagementIntent is {@code
+     *     null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
+     * @throws SecurityException If the UID of the calling process differs from the package UID of
+     *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.BACKUP)
     public void updateTransportAttributes(
-            ComponentName transportComponent,
-            String name,
+            @NonNull ComponentName transportComponent,
+            @NonNull String name,
             @Nullable Intent configurationIntent,
-            String currentDestinationString,
+            @NonNull String currentDestinationString,
             @Nullable Intent dataManagementIntent,
-            @Nullable String dataManagementLabel) {
+            @Nullable CharSequence dataManagementLabel) {
         checkServiceBinder();
         if (sService != null) {
             try {
@@ -796,7 +841,7 @@
     /**
      * Returns an {@link Intent} for the specified transport's configuration UI.
      * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String,
-     * Intent, String)}.
+     * Intent, CharSequence)}.
      * @param transportName The name of the registered transport.
      * @hide
      */
@@ -818,7 +863,7 @@
     /**
      * Returns a {@link String} describing where the specified transport is sending data.
      * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String,
-     * Intent, String)}.
+     * Intent, CharSequence)}.
      * @param transportName The name of the registered transport.
      * @hide
      */
@@ -840,7 +885,7 @@
     /**
      * Returns an {@link Intent} for the specified transport's data management UI.
      * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String,
-     * Intent, String)}.
+     * Intent, CharSequence)}.
      * @param transportName The name of the registered transport.
      * @hide
      */
@@ -861,9 +906,28 @@
 
     /**
      * Returns a {@link String} describing what the specified transport's data management intent is
-     * used for.
-     * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String,
-     * Intent, String)}.
+     * used for. This value is set by {@link #updateTransportAttributes(ComponentName, String,
+     * Intent, String, Intent, CharSequence)}.
+     *
+     * @param transportName The name of the registered transport.
+     * @deprecated Since Android Q, please use the variant {@link
+     *     #getDataManagementIntentLabel(String)} instead.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
+    @Nullable
+    public String getDataManagementLabel(@NonNull String transportName) {
+        CharSequence label = getDataManagementIntentLabel(transportName);
+        return label == null ? null : label.toString();
+    }
+
+    /**
+     * Returns a {@link CharSequence} describing what the specified transport's data management
+     * intent is used for. This value is set by {@link #updateTransportAttributes(ComponentName,
+     * String, Intent, String, Intent, CharSequence)}.
      *
      * @param transportName The name of the registered transport.
      * @hide
@@ -871,13 +935,14 @@
     @SystemApi
     @TestApi
     @RequiresPermission(android.Manifest.permission.BACKUP)
-    public String getDataManagementLabel(String transportName) {
+    @Nullable
+    public CharSequence getDataManagementIntentLabel(@NonNull String transportName) {
         checkServiceBinder();
         if (sService != null) {
             try {
                 return sService.getDataManagementLabelForUser(mContext.getUserId(), transportName);
             } catch (RemoteException e) {
-                Log.e(TAG, "getDataManagementLabel() couldn't connect");
+                Log.e(TAG, "getDataManagementIntentLabel() couldn't connect");
             }
         }
         return null;
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index 0963594..c8f2ff3 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -16,6 +16,7 @@
 
 package android.app.backup;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
@@ -164,19 +165,36 @@
     }
 
     /**
-     * On demand, supply a short string that can be shown to the user as the label
-     * on an overflow menu item used to invoked the data management UI.
+     * On demand, supply a short string that can be shown to the user as the label on an overflow
+     * menu item used to invoke the data management UI.
      *
-     * @return A string to be used as the label for the transport's data management
-     *         affordance.  If the transport supplies a data management intent, this
-     *         method must not return {@code null}.
+     * @return A string to be used as the label for the transport's data management affordance. If
+     *     the transport supplies a data management intent, this method must not return {@code
+     *     null}.
+     * @deprecated Since Android Q, please use the variant {@link #dataManagementIntentLabel()}
+     *     instead.
      */
+    @Deprecated
+    @Nullable
     public String dataManagementLabel() {
         throw new UnsupportedOperationException(
                 "Transport dataManagementLabel() not implemented");
     }
 
     /**
+     * On demand, supply a short CharSequence that can be shown to the user as the label on an
+     * overflow menu item used to invoke the data management UI.
+     *
+     * @return A CharSequence to be used as the label for the transport's data management
+     *     affordance. If the transport supplies a data management intent, this method must not
+     *     return {@code null}.
+     */
+    @Nullable
+    public CharSequence dataManagementIntentLabel() {
+        return dataManagementLabel();
+    }
+
+    /**
      * Ask the transport where, on local device storage, to keep backup state blobs.
      * This is per-transport so that mock transports used for testing can coexist with
      * "live" backup services without interfering with the live bookkeeping.  The
@@ -651,8 +669,8 @@
         }
 
         @Override
-        public String dataManagementLabel() {
-            return BackupTransport.this.dataManagementLabel();
+        public CharSequence dataManagementIntentLabel() {
+            return BackupTransport.this.dataManagementIntentLabel();
         }
 
         @Override
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 70ecdae..2dfaad7 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -353,16 +353,16 @@
      *     {@link Context#startActivity} in order to launch the transport's data-management UI. It
      *     may be {@code null} if the transport does not offer any user-facing data
      *     management UI.
-     * @param dataManagementLabel A {@link String} to be used as the label for the transport's data
-     *     management affordance. This MUST be {@code null} when dataManagementIntent is
-     *     {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
+     * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's
+     *     data management affordance. This MUST be {@code null} when dataManagementIntent is {@code
+     *     null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
      * @throws SecurityException If the UID of the calling process differs from the package UID of
      *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
      */
     void updateTransportAttributesForUser(int userId, in ComponentName transportComponent,
             in String name,
             in Intent configurationIntent, in String currentDestinationString,
-            in Intent dataManagementIntent, in String dataManagementLabel);
+            in Intent dataManagementIntent, in CharSequence dataManagementLabel);
 
     /**
      * Identify the currently selected transport.  Callers must hold the
@@ -525,13 +525,7 @@
      *
      * @param userId User id for which the manage-data menu label should be reported.
      */
-    String getDataManagementLabelForUser(int userId, String transport);
-
-    /**
-     * {@link android.app.backup.IBackupManager.getDataManagementLabelForUser} for the calling user
-     * id.
-     */
-    String getDataManagementLabel(String transport);
+    CharSequence getDataManagementLabelForUser(int userId, String transport);
 
     /**
      * Begin a restore session.  Either or both of packageName and transportID
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index efd9990..93a9dac 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2438,7 +2438,7 @@
      * Broadcast Action: A rollback has been committed.
      *
      * <p class="note">This is a protected intent that can only be sent
-     * by the system.
+     * by the system. The receiver must hold MANAGE_ROLLBACK permission.
      *
      * @hide
      */
diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java
index 8e72fa5..ceea043 100644
--- a/core/java/android/content/om/OverlayManager.java
+++ b/core/java/android/content/om/OverlayManager.java
@@ -16,12 +16,14 @@
 
 package android.content.om;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 
 import java.util.List;
 
@@ -96,6 +98,28 @@
     }
 
     /**
+     * Returns information about the overlay with the given package name for
+     * the specified user.
+     *
+     * @param packageName The name of the package.
+     * @param userHandle The user to get the OverlayInfos for.
+     * @return An OverlayInfo object; if no overlays exist with the
+     *         requested package name, null is returned.
+     *
+     * @hide
+     */
+    @SystemApi
+    @Nullable
+    public OverlayInfo getOverlayInfo(@NonNull final String packageName,
+            @NonNull final UserHandle userHandle) {
+        try {
+            return mService.getOverlayInfo(packageName, userHandle.myUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns information about all overlays for the given target package for
      * the specified user. The returned list is ordered according to the
      * overlay priority with the highest priority at the end of the list.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 706cbbf..068a93a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -671,6 +671,14 @@
      */
     public static final int PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE  = 1 << 27;
 
+    /**
+     * Indicates whether this package is in fact a runtime resource overlay.
+     *
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_IS_RESOURCE_OVERLAY = 1 << 28;
+
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
             PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -683,6 +691,7 @@
             PRIVATE_FLAG_HAS_DOMAIN_URLS,
             PRIVATE_FLAG_HIDDEN,
             PRIVATE_FLAG_INSTANT,
+            PRIVATE_FLAG_IS_RESOURCE_OVERLAY,
             PRIVATE_FLAG_ISOLATED_SPLIT_LOADING,
             PRIVATE_FLAG_OEM,
             PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
@@ -2023,6 +2032,14 @@
     }
 
     /**
+     * Returns true if the package has declared in its manifest that it is a
+     * runtime resource overlay.
+     */
+    public boolean isResourceOverlay() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY) != 0;
+    }
+
+    /**
      * @hide
      */
     @Override protected ApplicationInfo getApplicationInfo() {
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index fd3529b..464e866 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -742,7 +742,7 @@
 
     String getAppPredictionServicePackageName();
 
-    String getContentCaptureServicePackageName();
+    String getSystemCaptionsServicePackageName();
 
     String getIncidentReportApproverPackageName();
 
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 33b9c72..3edd17a 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1448,19 +1448,6 @@
         }
 
         /**
-         * Request that rollbacks be enabled for the given upgrade.
-         *
-         * @removed
-         * @deprecated use {@link #setEnableRollback(boolean)} instead.
-         * @hide
-         */
-        @Deprecated
-        @SystemApi
-        public void setEnableRollback() {
-            installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
-        }
-
-        /**
          * Request that rollbacks be enabled or disabled for the given upgrade.
          *
          * @param enable set to {@code true} to enable, {@code false} to disable
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 99324ba..fa5247c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2589,14 +2589,6 @@
     public static final String FEATURE_PC = "android.hardware.type.pc";
 
     /**
-     * Feature for {@link #getSystemAvailableFeatures} and
-     * {@link #hasSystemFeature}: This is a foldable device. Properties such as
-     * the display size may change in response to being folded.
-     */
-    @SdkConstant(SdkConstantType.FEATURE)
-    public static final String FEATURE_FOLDABLE = "android.hardware.type.foldable";
-
-    /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
      * The device supports printing.
      */
@@ -3073,6 +3065,15 @@
     public static final int FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED =  1 << 9;
 
     /**
+     * Permission flag: The permission should not be shown in the UI.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int FLAG_PERMISSION_HIDDEN =  1 << 10;
+
+    /**
      * Mask for all permission flags present in Android P
      *
      * @deprecated This constant does not contain useful information and should never have been
@@ -3090,7 +3091,7 @@
      *
      * @hide
      */
-    public static final int MASK_PERMISSION_FLAGS_ALL = 0x3FF;
+    public static final int MASK_PERMISSION_FLAGS_ALL = 0x7FF;
 
     /**
      * Injected activity in app that forwards user to setting activity of that app.
@@ -3801,6 +3802,7 @@
             FLAG_PERMISSION_GRANTED_BY_DEFAULT,
             FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED,
             FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED,
+            FLAG_PERMISSION_HIDDEN,
             /*
             FLAG_PERMISSION_REVOKE_WHEN_REQUESED
             */
@@ -6594,6 +6596,7 @@
             case FLAG_PERMISSION_REVOKE_WHEN_REQUESTED: return "REVOKE_WHEN_REQUESTED";
             case FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED: return "USER_SENSITIVE_WHEN_GRANTED";
             case FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED: return "USER_SENSITIVE_WHEN_DENIED";
+            case FLAG_PERMISSION_HIDDEN: return "HIDDEN";
             default: return Integer.toString(flag);
         }
     }
@@ -6863,9 +6866,9 @@
      *
      * @hide
      */
-    public String getContentCaptureServicePackageName() {
+    public String getSystemCaptionsServicePackageName() {
         throw new UnsupportedOperationException(
-                "getContentCaptureServicePackageName not implemented in subclass");
+                "getSystemCaptionsServicePackageName not implemented in subclass");
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 9d0ece0..743a302 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2108,6 +2108,9 @@
                     return null;
                 }
 
+                pkg.applicationInfo.privateFlags |=
+                    ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY;
+
                 XmlUtils.skipCurrentTag(parser);
 
             } else if (tagName.equals(TAG_KEY_SETS)) {
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 13c49a0..3488cc3 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -307,9 +307,9 @@
 
     @Override
     public String toString() {
-        return "SharedLibraryInfo[name:" + mName + ", type:" + typeToString(mType)
+        return "SharedLibraryInfo{name:" + mName + ", type:" + typeToString(mType)
                 + ", version:" + mVersion + (!getDependentPackages().isEmpty()
-                ? " has dependents" : "");
+                ? " has dependents" : "") + "}";
     }
 
     @Override
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 6729242..6b8416d 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -191,9 +191,9 @@
 
     /**
      * Return a global shared Resources object that provides access to only
-     * system resources (no application resources), and is not configured for
-     * the current screen (can not use dimension units, does not change based
-     * on orientation, etc).
+     * system resources (no application resources), is not configured for the
+     * current screen (can not use dimension units, does not change based on
+     * orientation, etc), and is not affected by Runtime Resource Overlay.
      */
     public static Resources getSystem() {
         synchronized (sSync) {
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index 293c1e4..d54a6fe 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -76,10 +76,12 @@
     /**
      * Returns a list of all currently available rollbacks.
      *
-     * @throws SecurityException if the caller does not have the
-     *            MANAGE_ROLLBACKS permission.
+     * @throws SecurityException if the caller does not have appropriate permissions.
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_ROLLBACKS,
+            android.Manifest.permission.TEST_MANAGE_ROLLBACKS
+    })
     @NonNull
     public List<RollbackInfo> getAvailableRollbacks() {
         try {
@@ -104,10 +106,12 @@
      * rolled back from.
      *
      * @return the recently committed rollbacks
-     * @throws SecurityException if the caller does not have the
-     *            MANAGE_ROLLBACKS permission.
+     * @throws SecurityException if the caller does not have appropriate permissions.
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_ROLLBACKS,
+            android.Manifest.permission.TEST_MANAGE_ROLLBACKS
+    })
     public @NonNull List<RollbackInfo> getRecentlyCommittedRollbacks() {
         try {
             return mBinder.getRecentlyExecutedRollbacks().getList();
@@ -190,10 +194,12 @@
      * @param statusReceiver where to deliver the results. Intents sent to
      *                       this receiver contain {@link #EXTRA_STATUS}
      *                       and {@link #EXTRA_STATUS_MESSAGE}.
-     * @throws SecurityException if the caller does not have the
-     *            MANAGE_ROLLBACKS permission.
+     * @throws SecurityException if the caller does not have appropriate permissions.
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_ROLLBACKS,
+            android.Manifest.permission.TEST_MANAGE_ROLLBACKS
+    })
     public void commitRollback(int rollbackId, @NonNull List<VersionedPackage> causePackages,
             @NonNull IntentSender statusReceiver) {
         try {
@@ -210,12 +216,11 @@
      * across device reboot, by simulating what happens on reboot without
      * actually rebooting the device.
      *
-     * @throws SecurityException if the caller does not have the
-     *            MANAGE_ROLLBACKS permission.
+     * @throws SecurityException if the caller does not have appropriate permissions.
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+    @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS)
     @TestApi
     public void reloadPersistedData() {
         try {
@@ -232,12 +237,11 @@
      * recently committed rollbacks that contain the given package.
      *
      * @param packageName the name of the package to expire data for.
-     * @throws SecurityException if the caller does not have the
-     *            MANAGE_ROLLBACKS permission.
+     * @throws SecurityException if the caller does not have appropriate permissions.
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+    @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS)
     @TestApi
     public void expireRollbackForPackage(@NonNull String packageName) {
         try {
diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java
index d796003..5e2875d 100644
--- a/core/java/android/database/sqlite/SQLiteGlobal.java
+++ b/core/java/android/database/sqlite/SQLiteGlobal.java
@@ -176,6 +176,6 @@
 
     /** @hide */
     public static boolean checkDbWipe() {
-        return true;
+        return false;
     }
 }
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index f208724..3e4e35a 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -15,6 +15,7 @@
  */
 package android.net;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.os.IBinder;
@@ -29,15 +30,33 @@
  * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} activity.
  */
 public class CaptivePortal implements Parcelable {
-    /** @hide */
+    /**
+     * Response code from the captive portal application, indicating that the portal was dismissed
+     * and the network should be re-validated.
+     * @see ICaptivePortal#appResponse(int)
+     * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int)
+     * @hide
+     */
     @SystemApi
     @TestApi
     public static final int APP_RETURN_DISMISSED    = 0;
-    /** @hide */
+    /**
+     * Response code from the captive portal application, indicating that the user did not login and
+     * does not want to use the captive portal network.
+     * @see ICaptivePortal#appResponse(int)
+     * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int)
+     * @hide
+     */
     @SystemApi
     @TestApi
     public static final int APP_RETURN_UNWANTED     = 1;
-    /** @hide */
+    /**
+     * Response code from the captive portal application, indicating that the user does not wish to
+     * login but wants to use the captive portal network as-is.
+     * @see ICaptivePortal#appResponse(int)
+     * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int)
+     * @hide
+     */
     @SystemApi
     @TestApi
     public static final int APP_RETURN_WANTED_AS_IS = 2;
@@ -47,7 +66,7 @@
     /** @hide */
     @SystemApi
     @TestApi
-    public CaptivePortal(IBinder binder) {
+    public CaptivePortal(@NonNull IBinder binder) {
         mBinder = binder;
     }
 
@@ -124,7 +143,7 @@
      */
     @SystemApi
     @TestApi
-    public void logEvent(int eventId, String packageName) {
+    public void logEvent(int eventId, @NonNull String packageName) {
         try {
             ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
         } catch (RemoteException e) {
diff --git a/core/java/android/net/INetworkMonitor.aidl b/core/java/android/net/INetworkMonitor.aidl
index 5d1ab98..1b0e1d7 100644
--- a/core/java/android/net/INetworkMonitor.aidl
+++ b/core/java/android/net/INetworkMonitor.aidl
@@ -41,7 +41,7 @@
     void start();
     void launchCaptivePortalApp();
     void notifyCaptivePortalAppFinished(int response);
-    void notifyAcceptPartialConnectivity();
+    void setAcceptPartialConnectivity();
     void forceReevaluation(int uid);
     void notifyPrivateDnsChanged(in PrivateDnsConfigParcel config);
     void notifyDnsResponse(int returnCode);
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 8b264ee..e253105 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -53,22 +55,26 @@
 public final class StaticIpConfiguration implements Parcelable {
     /** @hide */
     @UnsupportedAppUsage
+    @Nullable
     public LinkAddress ipAddress;
     /** @hide */
     @UnsupportedAppUsage
+    @Nullable
     public InetAddress gateway;
     /** @hide */
     @UnsupportedAppUsage
+    @NonNull
     public final ArrayList<InetAddress> dnsServers;
     /** @hide */
     @UnsupportedAppUsage
+    @Nullable
     public String domains;
 
     public StaticIpConfiguration() {
         dnsServers = new ArrayList<InetAddress>();
     }
 
-    public StaticIpConfiguration(StaticIpConfiguration source) {
+    public StaticIpConfiguration(@Nullable StaticIpConfiguration source) {
         this();
         if (source != null) {
             // All of these except dnsServers are immutable, so no need to make copies.
@@ -86,38 +92,38 @@
         domains = null;
     }
 
-    public LinkAddress getIpAddress() {
+    public @Nullable LinkAddress getIpAddress() {
         return ipAddress;
     }
 
-    public void setIpAddress(LinkAddress ipAddress) {
+    public void setIpAddress(@Nullable LinkAddress ipAddress) {
         this.ipAddress = ipAddress;
     }
 
-    public InetAddress getGateway() {
+    public @Nullable InetAddress getGateway() {
         return gateway;
     }
 
-    public void setGateway(InetAddress gateway) {
+    public void setGateway(@Nullable InetAddress gateway) {
         this.gateway = gateway;
     }
 
-    public List<InetAddress> getDnsServers() {
+    public @NonNull List<InetAddress> getDnsServers() {
         return dnsServers;
     }
 
-    public String getDomains() {
+    public @Nullable String getDomains() {
         return domains;
     }
 
-    public void setDomains(String newDomains) {
+    public void setDomains(@Nullable String newDomains) {
         domains = newDomains;
     }
 
     /**
      * Add a DNS server to this configuration.
      */
-    public void addDnsServer(InetAddress server) {
+    public void addDnsServer(@NonNull InetAddress server) {
         dnsServers.add(server);
     }
 
@@ -128,7 +134,7 @@
      * route to the gateway as well. This configuration is arguably invalid, but it used to work
      * in K and earlier, and other OSes appear to accept it.
      */
-    public List<RouteInfo> getRoutes(String iface) {
+    public @NonNull List<RouteInfo> getRoutes(String iface) {
         List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
         if (ipAddress != null) {
             RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
@@ -150,7 +156,7 @@
      * IPv6 configuration) will not be included.
      * @hide
      */
-    public LinkProperties toLinkProperties(String iface) {
+    public @NonNull LinkProperties toLinkProperties(String iface) {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName(iface);
         if (ipAddress != null) {
diff --git a/core/java/android/net/TcpKeepalivePacketDataParcelable.aidl b/core/java/android/net/TcpKeepalivePacketDataParcelable.aidl
index 7329c63..d66b6ae 100644
--- a/core/java/android/net/TcpKeepalivePacketDataParcelable.aidl
+++ b/core/java/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -23,4 +23,6 @@
     int dstPort;
     int seq;
     int ack;
+    int rcvWnd;
+    int rcvWndScale;
 }
diff --git a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java
index 3930344..a1d3de2 100644
--- a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java
+++ b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java
@@ -16,6 +16,7 @@
 
 package android.net.captiveportal;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -39,14 +40,18 @@
      */
     public static final int PARTIAL_CODE = -1;
 
+    @NonNull
     public static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE);
+    @NonNull
     public static final CaptivePortalProbeResult SUCCESS =
             new CaptivePortalProbeResult(SUCCESS_CODE);
     public static final CaptivePortalProbeResult PARTIAL =
             new CaptivePortalProbeResult(PARTIAL_CODE);
 
     private final int mHttpResponseCode;  // HTTP response code returned from Internet probe.
+    @Nullable
     public final String redirectUrl;      // Redirect destination returned from Internet probe.
+    @Nullable
     public final String detectUrl;        // URL where a 204 response code indicates
                                           // captive portal has been appeased.
     @Nullable
@@ -56,12 +61,13 @@
         this(httpResponseCode, null, null);
     }
 
-    public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl, String detectUrl) {
+    public CaptivePortalProbeResult(int httpResponseCode, @Nullable String redirectUrl,
+            @Nullable String detectUrl) {
         this(httpResponseCode, redirectUrl, detectUrl, null);
     }
 
-    public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl, String detectUrl,
-            CaptivePortalProbeSpec probeSpec) {
+    public CaptivePortalProbeResult(int httpResponseCode, @Nullable String redirectUrl,
+            @Nullable String detectUrl, @Nullable CaptivePortalProbeSpec probeSpec) {
         mHttpResponseCode = httpResponseCode;
         this.redirectUrl = redirectUrl;
         this.detectUrl = detectUrl;
diff --git a/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java b/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java
index 7ad4ecf..6c6a16c 100644
--- a/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java
+++ b/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java
@@ -19,6 +19,8 @@
 import static android.net.captiveportal.CaptivePortalProbeResult.PORTAL_CODE;
 import static android.net.captiveportal.CaptivePortalProbeResult.SUCCESS_CODE;
 
+import static com.android.internal.util.Preconditions.checkNotNull;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -48,9 +50,10 @@
     private final String mEncodedSpec;
     private final URL mUrl;
 
-    CaptivePortalProbeSpec(String encodedSpec, URL url) {
-        mEncodedSpec = encodedSpec;
-        mUrl = url;
+    CaptivePortalProbeSpec(@NonNull String encodedSpec, @NonNull URL url)
+            throws NullPointerException {
+        mEncodedSpec = checkNotNull(encodedSpec);
+        mUrl = checkNotNull(url);
     }
 
     /**
@@ -64,7 +67,7 @@
      */
     @VisibleForTesting
     @NonNull
-    public static CaptivePortalProbeSpec parseSpec(String spec) throws ParseException,
+    public static CaptivePortalProbeSpec parseSpec(@NonNull String spec) throws ParseException,
             MalformedURLException {
         if (TextUtils.isEmpty(spec)) {
             throw new ParseException("Empty probe spec", 0 /* errorOffset */);
@@ -84,7 +87,8 @@
     }
 
     @Nullable
-    private static Pattern parsePatternIfNonEmpty(String pattern, int pos) throws ParseException {
+    private static Pattern parsePatternIfNonEmpty(@Nullable String pattern, int pos)
+            throws ParseException {
         if (TextUtils.isEmpty(pattern)) {
             return null;
         }
@@ -120,8 +124,9 @@
      * <p>Each spec is separated by @@,@@ and follows the format for {@link #parseSpec(String)}.
      * <p>This method does not throw but ignores any entry that could not be parsed.
      */
+    @NonNull
     public static Collection<CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(
-            String settingsVal) {
+            @NonNull String settingsVal) {
         List<CaptivePortalProbeSpec> specs = new ArrayList<>();
         if (settingsVal != null) {
             for (String spec : TextUtils.split(settingsVal, SPEC_SEPARATOR)) {
@@ -142,12 +147,15 @@
     /**
      * Get the probe result from HTTP status and location header.
      */
+    @NonNull
     public abstract CaptivePortalProbeResult getResult(int status, @Nullable String locationHeader);
 
+    @NonNull
     public String getEncodedSpec() {
         return mEncodedSpec;
     }
 
+    @NonNull
     public URL getUrl() {
         return mUrl;
     }
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index b30d8cb..2bd4378 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -17,6 +17,7 @@
 package android.net.metrics;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -95,7 +96,7 @@
     /**
      * Utility to create an instance of {@link ApfProgramEvent}.
      */
-    public static class Builder {
+    public static final class Builder {
         private long mLifetime;
         private long mActualLifetime;
         private int mFilteredRas;
@@ -106,6 +107,7 @@
         /**
          * Set the maximum computed lifetime of the program in seconds.
          */
+        @NonNull
         public Builder setLifetime(long lifetime) {
             mLifetime = lifetime;
             return this;
@@ -114,6 +116,7 @@
         /**
          * Set the effective program lifetime in seconds.
          */
+        @NonNull
         public Builder setActualLifetime(long lifetime) {
             mActualLifetime = lifetime;
             return this;
@@ -122,6 +125,7 @@
         /**
          * Set the number of RAs filtered by the APF program.
          */
+        @NonNull
         public Builder setFilteredRas(int filteredRas) {
             mFilteredRas = filteredRas;
             return this;
@@ -130,6 +134,7 @@
         /**
          * Set the total number of current RAs at generation time.
          */
+        @NonNull
         public Builder setCurrentRas(int currentRas) {
             mCurrentRas = currentRas;
             return this;
@@ -138,6 +143,7 @@
         /**
          * Set the length of the APF program in bytes.
          */
+        @NonNull
         public Builder setProgramLength(int programLength) {
             mProgramLength = programLength;
             return this;
@@ -146,6 +152,7 @@
         /**
          * Set the flags describing what an Apf program filters.
          */
+        @NonNull
         public Builder setFlags(boolean hasIPv4, boolean multicastFilterOn) {
             mFlags = flagsFor(hasIPv4, multicastFilterOn);
             return this;
@@ -154,6 +161,7 @@
         /**
          * Build a new {@link ApfProgramEvent}.
          */
+        @NonNull
         public ApfProgramEvent build() {
             return new ApfProgramEvent(mLifetime, mActualLifetime, mFilteredRas, mCurrentRas,
                     mProgramLength, mFlags);
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index e1c8888..6c3b7af 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -125,7 +126,7 @@
      */
     @SystemApi
     @TestApi
-    public static class Builder {
+    public static final class Builder {
         private long mDurationMs;
         private int mReceivedRas;
         private int mMatchingRas;
@@ -140,6 +141,7 @@
         /**
          * Set the time interval in milliseconds these statistics covers.
          */
+        @NonNull
         public Builder setDurationMs(long durationMs) {
             mDurationMs = durationMs;
             return this;
@@ -148,6 +150,7 @@
         /**
          * Set the number of received RAs.
          */
+        @NonNull
         public Builder setReceivedRas(int receivedRas) {
             mReceivedRas = receivedRas;
             return this;
@@ -156,6 +159,7 @@
         /**
          * Set the number of received RAs matching a known RA.
          */
+        @NonNull
         public Builder setMatchingRas(int matchingRas) {
             mMatchingRas = matchingRas;
             return this;
@@ -164,6 +168,7 @@
         /**
          * Set the number of received RAs ignored due to the MAX_RAS limit.
          */
+        @NonNull
         public Builder setDroppedRas(int droppedRas) {
             mDroppedRas = droppedRas;
             return this;
@@ -172,6 +177,7 @@
         /**
          * Set the number of received RAs with a minimum lifetime of 0.
          */
+        @NonNull
         public Builder setZeroLifetimeRas(int zeroLifetimeRas) {
             mZeroLifetimeRas = zeroLifetimeRas;
             return this;
@@ -180,6 +186,7 @@
         /**
          * Set the number of received RAs that could not be parsed.
          */
+        @NonNull
         public Builder setParseErrors(int parseErrors) {
             mParseErrors = parseErrors;
             return this;
@@ -188,6 +195,7 @@
         /**
          * Set the number of APF program updates from receiving RAs.
          */
+        @NonNull
         public Builder setProgramUpdates(int programUpdates) {
             mProgramUpdates = programUpdates;
             return this;
@@ -196,6 +204,7 @@
         /**
          * Set the total number of APF program updates.
          */
+        @NonNull
         public Builder setProgramUpdatesAll(int programUpdatesAll) {
             mProgramUpdatesAll = programUpdatesAll;
             return this;
@@ -204,6 +213,7 @@
         /**
          * Set the number of APF program updates from allowing multicast traffic.
          */
+        @NonNull
         public Builder setProgramUpdatesAllowingMulticast(int programUpdatesAllowingMulticast) {
             mProgramUpdatesAllowingMulticast = programUpdatesAllowingMulticast;
             return this;
@@ -212,6 +222,7 @@
         /**
          * Set the maximum APF program size advertised by hardware.
          */
+        @NonNull
         public Builder setMaxProgramSize(int maxProgramSize) {
             mMaxProgramSize = maxProgramSize;
             return this;
@@ -220,6 +231,7 @@
         /**
          * Create a new {@link ApfStats}.
          */
+        @NonNull
         public ApfStats build() {
             return new ApfStats(mDurationMs, mReceivedRas, mMatchingRas, mDroppedRas,
                     mZeroLifetimeRas, mParseErrors, mProgramUpdates, mProgramUpdatesAll,
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index e4faea9..a3d0a20 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -51,13 +52,14 @@
     /**
      * Utility to create an instance of {@link ApfProgramEvent}.
      */
-    public static class Builder {
+    public static final class Builder {
         private String mMsg;
         private int mDurationMs;
 
         /**
          * Set the message of the event.
          */
+        @NonNull
         public Builder setMsg(String msg) {
             mMsg = msg;
             return this;
@@ -66,6 +68,7 @@
         /**
          * Set the duration of the event in milliseconds.
          */
+        @NonNull
         public Builder setDurationMs(int durationMs) {
             mDurationMs = durationMs;
             return this;
@@ -74,6 +77,7 @@
         /**
          * Create a new {@link DhcpClientEvent}.
          */
+        @NonNull
         public DhcpClientEvent build() {
             return new DhcpClientEvent(mMsg, mDurationMs);
         }
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
index 91318a2..652ce5d 100644
--- a/core/java/android/net/metrics/DhcpErrorEvent.java
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -37,26 +37,26 @@
     public static final int DHCP_ERROR = 4;
     public static final int MISC_ERROR = 5;
 
-    public static final int L2_TOO_SHORT               = makeErrorCode(L2_ERROR, 1);
-    public static final int L2_WRONG_ETH_TYPE          = makeErrorCode(L2_ERROR, 2);
+    public static final int L2_TOO_SHORT               = (L2_ERROR << 24) | (1 << 16);
+    public static final int L2_WRONG_ETH_TYPE          = (L2_ERROR << 24) | (2 << 16);
 
-    public static final int L3_TOO_SHORT               = makeErrorCode(L3_ERROR, 1);
-    public static final int L3_NOT_IPV4                = makeErrorCode(L3_ERROR, 2);
-    public static final int L3_INVALID_IP              = makeErrorCode(L3_ERROR, 3);
+    public static final int L3_TOO_SHORT               = (L3_ERROR << 24) | (1 << 16);
+    public static final int L3_NOT_IPV4                = (L3_ERROR << 24) | (2 << 16);
+    public static final int L3_INVALID_IP              = (L3_ERROR << 24) | (3 << 16);
 
-    public static final int L4_NOT_UDP                 = makeErrorCode(L4_ERROR, 1);
-    public static final int L4_WRONG_PORT              = makeErrorCode(L4_ERROR, 2);
+    public static final int L4_NOT_UDP                 = (L4_ERROR << 24) | (1 << 16);
+    public static final int L4_WRONG_PORT              = (L4_ERROR << 24) | (2 << 16);
 
-    public static final int BOOTP_TOO_SHORT            = makeErrorCode(DHCP_ERROR, 1);
-    public static final int DHCP_BAD_MAGIC_COOKIE      = makeErrorCode(DHCP_ERROR, 2);
-    public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3);
-    public static final int DHCP_NO_MSG_TYPE           = makeErrorCode(DHCP_ERROR, 4);
-    public static final int DHCP_UNKNOWN_MSG_TYPE      = makeErrorCode(DHCP_ERROR, 5);
-    public static final int DHCP_NO_COOKIE             = makeErrorCode(DHCP_ERROR, 6);
+    public static final int BOOTP_TOO_SHORT            = (DHCP_ERROR << 24) | (1 << 16);
+    public static final int DHCP_BAD_MAGIC_COOKIE      = (DHCP_ERROR << 24) | (2 << 16);
+    public static final int DHCP_INVALID_OPTION_LENGTH = (DHCP_ERROR << 24) | (3 << 16);
+    public static final int DHCP_NO_MSG_TYPE           = (DHCP_ERROR << 24) | (4 << 16);
+    public static final int DHCP_UNKNOWN_MSG_TYPE      = (DHCP_ERROR << 24) | (5 << 16);
+    public static final int DHCP_NO_COOKIE             = (DHCP_ERROR << 24) | (6 << 16);
 
-    public static final int BUFFER_UNDERFLOW           = makeErrorCode(MISC_ERROR, 1);
-    public static final int RECEIVE_ERROR              = makeErrorCode(MISC_ERROR, 2);
-    public static final int PARSING_ERROR              = makeErrorCode(MISC_ERROR, 3);
+    public static final int BUFFER_UNDERFLOW           = (MISC_ERROR << 24) | (1 << 16);
+    public static final int RECEIVE_ERROR              = (MISC_ERROR << 24) | (2 << 16);
+    public static final int PARSING_ERROR              = (MISC_ERROR << 24) | (3 << 16);
 
     // error code byte format (MSB to LSB):
     // byte 0: error type
@@ -102,10 +102,6 @@
         return (0xFFFF0000 & errorCode) | (0xFF & option);
     }
 
-    private static int makeErrorCode(int type, int subtype) {
-        return (type << 24) | ((0xFF & subtype) << 16);
-    }
-
     @Override
     public String toString() {
         return String.format("DhcpErrorEvent(%s)", Decoder.constants.get(errorCode));
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index 5b5a235..680c015 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.net.ConnectivityMetricsEvent;
@@ -41,7 +42,7 @@
 
     /** @hide */
     public static final String SERVICE_NAME = "connmetrics";
-
+    @NonNull
     private IIpConnectivityMetrics mService;
 
     /**
@@ -57,7 +58,7 @@
 
     /** @hide */
     @VisibleForTesting
-    public IpConnectivityLog(IIpConnectivityMetrics service) {
+    public IpConnectivityLog(@NonNull IIpConnectivityMetrics service) {
         mService = service;
     }
 
@@ -83,7 +84,7 @@
      * @return true if the event was successfully logged.
      * @hide
      */
-    public boolean log(ConnectivityMetricsEvent ev) {
+    public boolean log(@NonNull ConnectivityMetricsEvent ev) {
         if (!checkLoggerService()) {
             if (DBG) {
                 Log.d(TAG, SERVICE_NAME + " service was not ready");
@@ -109,7 +110,7 @@
      * @param data is a Parcelable instance representing the event.
      * @return true if the event was successfully logged.
      */
-    public boolean log(long timestamp, Event data) {
+    public boolean log(long timestamp, @NonNull Event data) {
         ConnectivityMetricsEvent ev = makeEv(data);
         ev.timestamp = timestamp;
         return log(ev);
@@ -121,7 +122,7 @@
      * @param data is a Parcelable instance representing the event.
      * @return true if the event was successfully logged.
      */
-    public boolean log(String ifname, Event data) {
+    public boolean log(@NonNull String ifname, @NonNull Event data) {
         ConnectivityMetricsEvent ev = makeEv(data);
         ev.ifname = ifname;
         return log(ev);
@@ -135,7 +136,7 @@
      * @param data is a Parcelable instance representing the event.
      * @return true if the event was successfully logged.
      */
-    public boolean log(Network network, int[] transports, Event data) {
+    public boolean log(@NonNull Network network, @NonNull int[] transports, @NonNull Event data) {
         return log(network.netId, transports, data);
     }
 
@@ -147,7 +148,7 @@
      * @param data is a Parcelable instance representing the event.
      * @return true if the event was successfully logged.
      */
-    public boolean log(int netid, int[] transports, Event data) {
+    public boolean log(int netid, @NonNull int[] transports, @NonNull Event data) {
         ConnectivityMetricsEvent ev = makeEv(data);
         ev.netId = netid;
         ev.transports = BitUtils.packBits(transports);
@@ -159,7 +160,7 @@
      * @param data is a Parcelable instance representing the event.
      * @return true if the event was successfully logged.
      */
-    public boolean log(Event data) {
+    public boolean log(@NonNull Event data) {
         return log(makeEv(data));
     }
 
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 052758d..45b665d 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -17,6 +17,7 @@
 package android.net.metrics;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.os.Parcel;
@@ -81,7 +82,7 @@
     /**
      * Utility to create an instance of {@link ValidationProbeEvent}.
      */
-    public static class Builder {
+    public static final class Builder {
         private long mDurationMs;
         private int mProbeType;
         private int mReturnCode;
@@ -89,6 +90,7 @@
         /**
          * Set the duration of the probe in milliseconds.
          */
+        @NonNull
         public Builder setDurationMs(long durationMs) {
             mDurationMs = durationMs;
             return this;
@@ -97,6 +99,7 @@
         /**
          * Set the probe type based on whether it was the first validation.
          */
+        @NonNull
         public Builder setProbeType(int probeType, boolean firstValidation) {
             mProbeType = makeProbeType(probeType, firstValidation);
             return this;
@@ -105,6 +108,7 @@
         /**
          * Set the return code of the probe.
          */
+        @NonNull
         public Builder setReturnCode(int returnCode) {
             mReturnCode = returnCode;
             return this;
@@ -113,6 +117,7 @@
         /**
          * Create a new {@link ValidationProbeEvent}.
          */
+        @NonNull
         public ValidationProbeEvent build() {
             return new ValidationProbeEvent(mDurationMs, mProbeType, mReturnCode);
         }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4fae3a8..b64fe00 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -200,13 +200,21 @@
 
     /**
      * Include only the current run in the stats.
+     *
+     * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, only {@link #STATS_SINCE_CHARGED}
+     * is supported.
      */
     @UnsupportedAppUsage
+    @Deprecated
     public static final int STATS_CURRENT = 1;
 
     /**
      * Include only the run since the last time the device was unplugged in the stats.
+     *
+     * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, only {@link #STATS_SINCE_CHARGED}
+     * is supported.
      */
+    @Deprecated
     public static final int STATS_SINCE_UNPLUGGED = 2;
 
     // NOTE: Update this list if you add/change any stats above.
@@ -255,8 +263,10 @@
      *   - Ambient display properly output in data dump.
      * New in version 33:
      *   - Fixed bug in min learned capacity updating process.
+     * New in version 34:
+     *   - Deprecated STATS_SINCE_UNPLUGGED and STATS_CURRENT.
      */
-    static final int CHECKIN_VERSION = 33;
+    static final int CHECKIN_VERSION = 34;
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -3651,6 +3661,14 @@
      */
     public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid,
             boolean wifiOnly) {
+
+        if (which != BatteryStats.STATS_SINCE_CHARGED) {
+            dumpLine(pw, 0, STAT_NAMES[which], "err",
+                    "ERROR: BatteryStats.dumpCheckin called for which type " + which
+                    + " but only STATS_SINCE_CHARGED is supported.");
+            return;
+        }
+
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtimeMs = SystemClock.elapsedRealtime();
         final long rawRealtime = rawRealtimeMs * 1000;
@@ -3848,28 +3866,13 @@
                 multicastWakeLockTimeTotalMicros / 1000,
                 multicastWakeLockCountTotal);
 
-        if (which == STATS_SINCE_UNPLUGGED) {
-            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
-                    getDischargeCurrentLevel());
-        }
-
-        if (which == STATS_SINCE_UNPLUGGED) {
-            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
-                    getDischargeStartLevel()-getDischargeCurrentLevel(),
-                    getDischargeStartLevel()-getDischargeCurrentLevel(),
-                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff(),
-                    dischargeCount / 1000, dischargeScreenOffCount / 1000,
-                    getDischargeAmountScreenDoze(), dischargeScreenDozeCount / 1000,
-                    dischargeLightDozeCount / 1000, dischargeDeepDozeCount / 1000);
-        } else {
-            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
-                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
-                    getDischargeAmountScreenOnSinceCharge(),
-                    getDischargeAmountScreenOffSinceCharge(),
-                    dischargeCount / 1000, dischargeScreenOffCount / 1000,
-                    getDischargeAmountScreenDozeSinceCharge(), dischargeScreenDozeCount / 1000,
-                    dischargeLightDozeCount / 1000, dischargeDeepDozeCount / 1000);
-        }
+        dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
+                getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
+                getDischargeAmountScreenOnSinceCharge(),
+                getDischargeAmountScreenOffSinceCharge(),
+                dischargeCount / 1000, dischargeScreenOffCount / 1000,
+                getDischargeAmountScreenDozeSinceCharge(), dischargeScreenDozeCount / 1000,
+                dischargeLightDozeCount / 1000, dischargeDeepDozeCount / 1000);
 
         if (reqUid < 0) {
             final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
@@ -4432,6 +4435,13 @@
     @SuppressWarnings("unused")
     public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
             int reqUid, boolean wifiOnly) {
+
+        if (which != BatteryStats.STATS_SINCE_CHARGED) {
+            pw.println("ERROR: BatteryStats.dump called for which type " + which
+                    + " but only STATS_SINCE_CHARGED is supported");
+            return;
+        }
+
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
         final long rawRealtimeMs = (rawRealtime + 500) / 1000;
@@ -5044,41 +5054,18 @@
 
         pw.println();
 
-        if (which == STATS_SINCE_UNPLUGGED) {
-            if (getIsOnBattery()) {
-                pw.print(prefix); pw.println("  Device is currently unplugged");
-                pw.print(prefix); pw.print("    Discharge cycle start level: ");
-                        pw.println(getDischargeStartLevel());
-                pw.print(prefix); pw.print("    Discharge cycle current level: ");
-                        pw.println(getDischargeCurrentLevel());
-            } else {
-                pw.print(prefix); pw.println("  Device is currently plugged into power");
-                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
-                        pw.println(getDischargeStartLevel());
-                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
-                        pw.println(getDischargeCurrentLevel());
-            }
-            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
-            pw.println(getDischargeAmountScreenOn());
-            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
-            pw.println(getDischargeAmountScreenOff());
-            pw.print(prefix); pw.print("    Amount discharged while screen doze: ");
-            pw.println(getDischargeAmountScreenDoze());
-            pw.println(" ");
-        } else {
-            pw.print(prefix); pw.println("  Device battery use since last full charge");
-            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
-            pw.println(getLowDischargeAmountSinceCharge());
-            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
-            pw.println(getHighDischargeAmountSinceCharge());
-            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
-            pw.println(getDischargeAmountScreenOnSinceCharge());
-            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
-            pw.println(getDischargeAmountScreenOffSinceCharge());
-            pw.print(prefix); pw.print("    Amount discharged while screen doze: ");
-            pw.println(getDischargeAmountScreenDozeSinceCharge());
-            pw.println();
-        }
+        pw.print(prefix); pw.println("  Device battery use since last full charge");
+        pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
+        pw.println(getLowDischargeAmountSinceCharge());
+        pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
+        pw.println(getHighDischargeAmountSinceCharge());
+        pw.print(prefix); pw.print("    Amount discharged while screen on: ");
+        pw.println(getDischargeAmountScreenOnSinceCharge());
+        pw.print(prefix); pw.print("    Amount discharged while screen off: ");
+        pw.println(getDischargeAmountScreenOffSinceCharge());
+        pw.print(prefix); pw.print("    Amount discharged while screen doze: ");
+        pw.println(getDischargeAmountScreenDozeSinceCharge());
+        pw.println();
 
         final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
         helper.create(this);
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index f62a999..6536fc9 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -242,27 +242,6 @@
     void tetherLimitReached(ITetheringStatsProvider provider);
 
     /**
-     ** PPPD
-     **/
-
-    /**
-     * Returns the list of currently known TTY devices on the system
-     */
-    String[] listTtys();
-
-    /**
-     * Attaches a PPP server daemon to the specified TTY with the specified
-     * local/remote addresses.
-     */
-    void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr,
-            String dns2Addr);
-
-    /**
-     * Detaches a PPP server daemon from the specified TTY.
-     */
-    void detachPppd(String tty);
-
-    /**
      ** DATA USAGE RELATED
      **/
 
diff --git a/core/java/android/os/ServiceSpecificException.java b/core/java/android/os/ServiceSpecificException.java
index 3b0f26ae..03d5d3e 100644
--- a/core/java/android/os/ServiceSpecificException.java
+++ b/core/java/android/os/ServiceSpecificException.java
@@ -15,6 +15,7 @@
  */
 package android.os;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 
 /**
@@ -34,7 +35,7 @@
 public class ServiceSpecificException extends RuntimeException {
     public final int errorCode;
 
-    public ServiceSpecificException(int errorCode, String message) {
+    public ServiceSpecificException(int errorCode, @Nullable String message) {
         super(message);
         this.errorCode = errorCode;
     }
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index e695a1b..64effb8 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -20,6 +20,8 @@
 import android.annotation.UnsupportedAppUsage;
 import android.app.IAlarmManager;
 import android.content.Context;
+import android.location.ILocationManager;
+import android.location.LocationTime;
 import android.util.Slog;
 
 import dalvik.annotation.optimization.CriticalNative;
@@ -317,4 +319,33 @@
             }
         };
     }
+
+    /**
+     * Returns a {@link Clock} that starts at January 1, 1970 00:00:00.0 UTC,
+     * synchronized using the device's location provider.
+     *
+     * @throws DateTimeException when the location provider has not had a location fix since boot.
+     */
+    public static @NonNull Clock currentGnssTimeClock() {
+        return new SimpleClock(ZoneOffset.UTC) {
+            private final ILocationManager mMgr = ILocationManager.Stub
+                    .asInterface(ServiceManager.getService(Context.LOCATION_SERVICE));
+            @Override
+            public long millis() {
+                LocationTime time;
+                try {
+                    time = mMgr.getGnssTimeMillis();
+                } catch (RemoteException e) {
+                    e.rethrowFromSystemServer();
+                    return 0;
+                }
+                if (time == null) {
+                    throw new DateTimeException("Gnss based time is not available.");
+                }
+                long currentNanos = elapsedRealtimeNanos();
+                long deltaMs = (currentNanos - time.getElapsedRealtimeNanos()) / 1000000L;
+                return time.getTime() + deltaMs;
+            }
+        };
+    }
 }
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index 71eda19..a92e28a 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -37,11 +37,13 @@
  * by the logging itself.  It can be substantial.
  * <p>
  * <b>Battery Usage</b><br>
- * The statistics related to power (battery) usage are recorded since the device
- * was last unplugged. It is expected that applications schedule more work to do
- * while the device is plugged in (e.g. using {@link android.app.job.JobScheduler
- * JobScheduler}), and while that can affect charging rates, it is still preferable
- * to actually draining the battery.
+ * Since Android version {@link android.os.Build.VERSION_CODES#Q}, the statistics related to power
+ * (battery) usage are recorded since the device was last considered fully charged (for previous
+ * versions, it is instead since the device was last unplugged).
+ * It is expected that applications schedule more work to do while the device is
+ * plugged in (e.g. using {@link android.app.job.JobScheduler JobScheduler}), and
+ * while that can affect charging rates, it is still preferable to actually draining
+ * the battery.
  */
 @SystemService(Context.SYSTEM_HEALTH_SERVICE)
 public class SystemHealthManager {
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 7bd0fe2..4322a59 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -225,6 +225,14 @@
     public static final String NAMESPACE_SCHEDULER = "scheduler";
 
     /**
+     * Namespace for storage-related features.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_STORAGE = "storage";
+
+    /**
      * Namespace for System UI related features.
      *
      * @hide
@@ -233,6 +241,14 @@
     public static final String NAMESPACE_SYSTEMUI = "systemui";
 
     /**
+     * Telephony related properties.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_TELEPHONY = "telephony";
+
+    /**
      * Namespace for TextClassifier related features.
      *
      * @hide
@@ -277,7 +293,6 @@
      *
      * @hide
      */
-    @SystemApi
     public interface Telephony {
         String NAMESPACE = "telephony";
         /**
@@ -294,23 +309,6 @@
         String RAMPING_RINGER_VIBRATION_DURATION = "ramping_ringer_vibration_duration";
     }
 
-    /**
-     * Namespace for storage-related features.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface Storage {
-        String NAMESPACE = "storage";
-
-        /**
-         * If {@code 1}, enables the isolated storage feature. If {@code -1},
-         * disables the isolated storage feature. If {@code 0}, uses the default
-         * value from the build system.
-         */
-        String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
-    }
-
     private static final Object sLock = new Object();
     @GuardedBy("sLock")
     private static ArrayMap<OnPropertyChangedListener, Pair<String, Executor>> sSingleListeners =
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index e931826..8f772d4 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -34,7 +34,6 @@
 import android.graphics.fonts.FontStyle;
 import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
-import android.os.Build.VERSION_CODES;
 import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -652,17 +651,12 @@
                 if (familyBuilder == null) {
                     familyBuilder = new FontFamily.Builder(font);
                 } else {
-                    try {
-                        familyBuilder.addFont(font);
-                    } catch (IllegalArgumentException e) {
-                        if (context.getApplicationInfo().targetSdkVersion <= VERSION_CODES.P) {
-                            // Surpress the IllegalArgumentException for keeping the backward
-                            // compatibility.
-                            continue;
-                        }
-                        throw e;
-                    }
+                    familyBuilder.addFont(font);
                 }
+            } catch (IllegalArgumentException e) {
+                // To be a compatible behavior with API28 or before, catch IllegalArgumentExcetpion
+                // thrown by native code and returns null.
+                return null;
             } catch (IOException e) {
                 continue;
             }
diff --git a/core/java/android/provider/SearchIndexablesProvider.java b/core/java/android/provider/SearchIndexablesProvider.java
index 1549c45..d505f02 100644
--- a/core/java/android/provider/SearchIndexablesProvider.java
+++ b/core/java/android/provider/SearchIndexablesProvider.java
@@ -25,6 +25,7 @@
 import android.content.pm.ProviderInfo;
 import android.database.Cursor;
 import android.net.Uri;
+import android.util.Log;
 
 /**
  * Base class for a search indexable provider. Such provider offers data to be indexed either
@@ -112,19 +113,26 @@
     @Override
     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                         String sortOrder) {
-        switch (mMatcher.match(uri)) {
-            case MATCH_RES_CODE:
-                return queryXmlResources(null);
-            case MATCH_RAW_CODE:
-                return queryRawData(null);
-            case MATCH_NON_INDEXABLE_KEYS_CODE:
-                return queryNonIndexableKeys(null);
-            case MATCH_SITE_MAP_PAIRS_CODE:
-                return querySiteMapPairs();
-            case MATCH_SLICE_URI_PAIRS_CODE:
-                return querySliceUriPairs();
-            default:
-                throw new UnsupportedOperationException("Unknown Uri " + uri);
+        try {
+            switch (mMatcher.match(uri)) {
+                case MATCH_RES_CODE:
+                    return queryXmlResources(null);
+                case MATCH_RAW_CODE:
+                    return queryRawData(null);
+                case MATCH_NON_INDEXABLE_KEYS_CODE:
+                    return queryNonIndexableKeys(null);
+                case MATCH_SITE_MAP_PAIRS_CODE:
+                    return querySiteMapPairs();
+                case MATCH_SLICE_URI_PAIRS_CODE:
+                    return querySliceUriPairs();
+                default:
+                    throw new UnsupportedOperationException("Unknown Uri " + uri);
+            }
+        } catch (UnsupportedOperationException e) {
+            throw e;
+        } catch (Exception e) {
+            Log.e(TAG, "Provider querying exception:", e);
+            return null;
         }
     }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b8174e6..7c80a0b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5607,11 +5607,23 @@
          *
          * @hide
          */
+        @SystemApi
         public static final String ODI_CAPTIONS_ENABLED = "odi_captions_enabled";
 
         private static final Validator ODI_CAPTIONS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
+         * Setting to indicate that on device captions cannot be shown because the app
+         * which is currently playing media had opted out.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final String ODI_CAPTIONS_OPTED_OUT = "odi_captions_opted_out";
+
+        private static final Validator ODI_CAPTIONS_OPTED_OUT_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
          * On Android 8.0 (API level 26) and higher versions of the platform,
          * a 64-bit number (expressed as a hexadecimal string), unique to
          * each combination of app-signing key, user, and device.
@@ -8978,6 +8990,7 @@
             VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
             VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
             VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR);
+            VALIDATORS.put(ODI_CAPTIONS_OPTED_OUT, ODI_CAPTIONS_OPTED_OUT_VALIDATOR);
         }
 
         /**
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 34ced17..96b861b 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -427,7 +427,7 @@
                 mFocusedValue = focusedValue;
                 if (mCallback != null) {
                     try {
-                        if (mCallback.isCompleted()) {
+                        if (!mCallback.isCompleted()) {
                             mCallback.cancel();
                         }
                     } catch (RemoteException e) {
diff --git a/core/java/android/service/contentcapture/ActivityEvent.java b/core/java/android/service/contentcapture/ActivityEvent.java
index 5407c1d..fc781c2 100644
--- a/core/java/android/service/contentcapture/ActivityEvent.java
+++ b/core/java/android/service/contentcapture/ActivityEvent.java
@@ -52,11 +52,17 @@
      */
     public static final int TYPE_ACTIVITY_STOPPED = Event.ACTIVITY_STOPPED;
 
+    /**
+     * The activity was destroyed.
+     */
+    public static final int TYPE_ACTIVITY_DESTROYED = Event.ACTIVITY_DESTROYED;
+
     /** @hide */
     @IntDef(prefix = { "TYPE_" }, value = {
             TYPE_ACTIVITY_RESUMED,
             TYPE_ACTIVITY_PAUSED,
-            TYPE_ACTIVITY_STOPPED
+            TYPE_ACTIVITY_STOPPED,
+            TYPE_ACTIVITY_DESTROYED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ActivityEventType{}
@@ -81,7 +87,8 @@
     /**
      * Gets the event type.
      *
-     * @return either {@link #TYPE_ACTIVITY_RESUMED} or {@value #TYPE_ACTIVITY_PAUSED}.
+     * @return either {@link #TYPE_ACTIVITY_RESUMED}, {@value #TYPE_ACTIVITY_PAUSED},
+     * {@value #TYPE_ACTIVITY_STOPPED}, or {@value #TYPE_ACTIVITY_DESTROYED}.
      */
     @ActivityEventType
     public int getEventType() {
@@ -97,6 +104,8 @@
                 return "ACTIVITY_PAUSED";
             case TYPE_ACTIVITY_STOPPED:
                 return "ACTIVITY_STOPPED";
+            case TYPE_ACTIVITY_DESTROYED:
+                return "ACTIVITY_DESTROYED";
             default:
                 return "UKNOWN_TYPE: " + type;
         }
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 6f4114d..df11397 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -78,6 +78,21 @@
     public static final String SERVICE_INTERFACE =
             "android.service.contentcapture.ContentCaptureService";
 
+    /**
+     * Name under which a ContentCaptureService component publishes information about itself.
+     *
+     * <p>This meta-data should reference an XML resource containing a
+     * <code>&lt;{@link
+     * android.R.styleable#ContentCaptureService content-capture-service}&gt;</code> tag.
+     *
+     * <p>This is a a sample XML file configuring a ContentCaptureService:
+     * <pre> &lt;content-capture-service
+     *     android:settingsActivity="foo.bar.SettingsActivity"
+     *     . . .
+     * /&gt;</pre>
+     */
+    public static final String SERVICE_META_DATA = "android.content_capture";
+
     private Handler mHandler;
     private IContentCaptureServiceCallback mCallback;
 
diff --git a/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java b/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java
new file mode 100644
index 0000000..6ecd82f
--- /dev/null
+++ b/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java
@@ -0,0 +1,171 @@
+/*
+ * 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.service.contentcapture;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * {@link ServiceInfo} and meta-data about an {@link ContentCaptureService}.
+ *
+ * @hide
+ */
+public final class ContentCaptureServiceInfo {
+
+    private static final String TAG = ContentCaptureServiceInfo.class.getSimpleName();
+    private static final String XML_TAG_SERVICE = "content-capture-service";
+
+    private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, boolean isTemp,
+            @UserIdInt int userId) throws PackageManager.NameNotFoundException {
+        int flags = PackageManager.GET_META_DATA;
+        if (!isTemp) {
+            flags |= PackageManager.MATCH_SYSTEM_ONLY;
+        }
+
+        ServiceInfo si = null;
+        try {
+            si = AppGlobals.getPackageManager().getServiceInfo(comp, flags, userId);
+        } catch (RemoteException e) {
+        }
+        if (si == null) {
+            throw new NameNotFoundException("Could not get serviceInfo for "
+                    + (isTemp ? " (temp)" : "(default system)")
+                    + " " + comp.flattenToShortString());
+        }
+        return si;
+    }
+
+    @NonNull
+    private final ServiceInfo mServiceInfo;
+
+    @Nullable
+    private final String mSettingsActivity;
+
+    public ContentCaptureServiceInfo(@NonNull Context context, @NonNull ComponentName comp,
+            boolean isTemporaryService, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException {
+        this(context, getServiceInfoOrThrow(comp, isTemporaryService, userId));
+    }
+
+    private ContentCaptureServiceInfo(@NonNull Context context, @NonNull ServiceInfo si) {
+        // Check for permissions.
+        if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) {
+            Slog.w(TAG, "ContentCaptureService from '" + si.packageName
+                    + "' does not require permission "
+                    + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
+            throw new SecurityException("Service does not require permission "
+                    + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
+        }
+
+        mServiceInfo = si;
+
+        // Get the metadata, if declared.
+        final XmlResourceParser parser = si.loadXmlMetaData(context.getPackageManager(),
+                ContentCaptureService.SERVICE_META_DATA);
+        if (parser == null) {
+            mSettingsActivity = null;
+            return;
+        }
+
+        String settingsActivity = null;
+
+        try {
+            final Resources resources = context.getPackageManager().getResourcesForApplication(
+                    si.applicationInfo);
+
+            int type = 0;
+            while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
+                type = parser.next();
+            }
+
+            if (XML_TAG_SERVICE.equals(parser.getName())) {
+                final AttributeSet allAttributes = Xml.asAttributeSet(parser);
+                TypedArray afsAttributes = null;
+                try {
+                    afsAttributes = resources.obtainAttributes(allAttributes,
+                            com.android.internal.R.styleable.ContentCaptureService);
+                    settingsActivity = afsAttributes.getString(
+                            R.styleable.ContentCaptureService_settingsActivity);
+                } finally {
+                    if (afsAttributes != null) {
+                        afsAttributes.recycle();
+                    }
+                }
+            } else {
+                Log.e(TAG, "Meta-data does not start with content-capture-service tag");
+            }
+        } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) {
+            Log.e(TAG, "Error parsing auto fill service meta-data", e);
+        }
+
+        mSettingsActivity = settingsActivity;
+    }
+
+    public ServiceInfo getServiceInfo() {
+        return mServiceInfo;
+    }
+
+    @Nullable
+    public String getSettingsActivity() {
+        return mSettingsActivity;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder();
+        builder.append(getClass().getSimpleName());
+        builder.append("[").append(mServiceInfo);
+        builder.append(", settings:").append(mSettingsActivity);
+        return builder.toString();
+    }
+
+    /**
+     * Dumps it!
+     */
+    public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+        pw.print(prefix);
+        pw.print("Component: ");
+        pw.println(getServiceInfo().getComponentName());
+        pw.print(prefix);
+        pw.print("Settings: ");
+        pw.println(mSettingsActivity);
+    }
+}
diff --git a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java
index 7a9d8a0..9add38e 100644
--- a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java
+++ b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java
@@ -97,9 +97,10 @@
         if (this.result == EuiccService.RESULT_OK) {
             this.mProfiles = profiles;
         } else {
-            if (profiles != null) {
+            // For error case, profiles is either null or 0 size.
+            if (profiles != null && profiles.length > 0) {
                 throw new IllegalArgumentException(
-                        "Error result with non-null profiles: " + result);
+                        "Error result with non-empty profiles: " + result);
             }
             this.mProfiles = null;
         }
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 1cdb62f..8ba9a83 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -16,6 +16,7 @@
 package android.service.notification;
 
 import android.annotation.NonNull;
+import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.app.Notification;
 import android.os.Bundle;
@@ -23,6 +24,9 @@
 import android.os.Parcelable;
 import android.os.UserHandle;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Ranking updates from the Assistant.
  *
@@ -43,6 +47,14 @@
     private final Bundle mSignals;
     private final int mUser;
 
+    /** @hide */
+    @StringDef (prefix = { "KEY_" }, value = {
+            KEY_CONTEXTUAL_ACTIONS, KEY_GROUP_KEY, KEY_IMPORTANCE, KEY_PEOPLE, KEY_SNOOZE_CRITERIA,
+            KEY_TEXT_REPLIES, KEY_USER_SENTIMENT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Keys {}
+
     /**
      * Data type: ArrayList of {@code String}, where each is a representation of a
      * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 780b576..a1932b8 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -25,6 +25,7 @@
 import android.annotation.SystemApi;
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -141,7 +142,6 @@
         return onNotificationEnqueued(sbn);
     }
 
-
     /**
      * Implement this method to learn when notifications are removed, how they were interacted with
      * before removal, and why they were removed.
@@ -216,6 +216,15 @@
     }
 
     /**
+     * Implement this to know when a user has changed which features of
+     * their notifications the assistant can modify.
+     * <p> Query {@link NotificationManager#getAllowedAssistantCapabilities()} to see what
+     * {@link Adjustment adjustments} you are currently allowed to make.</p>
+     */
+    public void onCapabilitiesChanged() {
+    }
+
+    /**
      * Updates a notification.  N.B. this won’t cause
      * an existing notification to alert, but might allow a future update to
      * this notification to alert.
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index cc74e1a..8512a0b 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -292,9 +292,9 @@
         return uid;
     }
 
-    /** The package that posted the notification.
-     *<p>
-     * Might be different from {@link #getPackageName()} if the app owning the notification has
+    /**
+     * The package that posted the notification.
+     * <p> Might be different from {@link #getPackageName()} if the app owning the notification has
      * a {@link NotificationManager#setNotificationDelegate(String) notification delegate}.
      */
     public @NonNull String getOpPkg() {
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
index 7fb0f95..610cf2c 100644
--- a/core/java/android/text/style/LineHeightSpan.java
+++ b/core/java/android/text/style/LineHeightSpan.java
@@ -70,7 +70,15 @@
      * Default implementation of the {@link LineHeightSpan}, which changes the line height of the
      * attached paragraph.
      * <p>
-     * LineHeightSpan will change the line height of the entire paragraph, even though it
+     * For example, a paragraph with its line height equal to 100px can be set like this:
+     * <pre>
+     * SpannableString string = new SpannableString("This is a multiline paragraph. This is a multiline paragraph.");
+     * string.setSpan(new LineHeightSpan.Standard(100), 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+     * </pre>
+     * <img src="{@docRoot}reference/android/images/text/style/lineheightspan.png" />
+     * <figcaption>Text with line height set to 100 pixels.</figcaption>
+     * <p>
+     * Notice that LineHeightSpan will change the line height of the entire paragraph, even though it
      * covers only part of the paragraph.
      * </p>
      */
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index c1504ae..de10ffb 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -51,7 +51,7 @@
         DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
         DEFAULT_FLAGS.put("settings_slice_injection", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
-        DEFAULT_FLAGS.put("settings_mainline_module", "false");
+        DEFAULT_FLAGS.put("settings_mainline_module", "true");
         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/GestureDetector.java b/core/java/android/view/GestureDetector.java
index c1d122a..c794a69 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -16,20 +16,11 @@
 
 package android.view;
 
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
-
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
-import android.os.SystemClock;
-import android.util.StatsLog;
 
 /**
  * Detects various gestures and events using the supplied {@link MotionEvent}s.
@@ -260,12 +251,8 @@
     private boolean mAlwaysInTapRegion;
     private boolean mAlwaysInBiggerTapRegion;
     private boolean mIgnoreNextUpEvent;
-    // Whether a classification has been recorded by statsd for the current event stream. Reset on
-    // ACTION_DOWN.
-    private boolean mHasRecordedClassification;
 
     private MotionEvent mCurrentDownEvent;
-    private MotionEvent mCurrentMotionEvent;
     private MotionEvent mPreviousUpEvent;
 
     /**
@@ -310,7 +297,6 @@
                     break;
 
                 case LONG_PRESS:
-                    recordGestureClassification(msg.arg1);
                     dispatchLongPress();
                     break;
 
@@ -318,8 +304,6 @@
                     // If the user's finger is still down, do not count it as a tap
                     if (mDoubleTapListener != null) {
                         if (!mStillDown) {
-                            recordGestureClassification(
-                                    TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
                             mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
                         } else {
                             mDeferConfirmSingleTap = true;
@@ -517,11 +501,6 @@
 
         final int action = ev.getAction();
 
-        if (mCurrentMotionEvent != null) {
-            mCurrentMotionEvent.recycle();
-        }
-        mCurrentMotionEvent = MotionEvent.obtain(ev);
-
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
@@ -590,8 +569,6 @@
                             && isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
                         // This is a second tap
                         mIsDoubleTapping = true;
-                        recordGestureClassification(
-                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP);
                         // Give a callback with the first tap of the double-tap
                         handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
                         // Give a callback with down event of the double-tap
@@ -613,17 +590,11 @@
                 mStillDown = true;
                 mInLongPress = false;
                 mDeferConfirmSingleTap = false;
-                mHasRecordedClassification = false;
 
                 if (mIsLongpressEnabled) {
                     mHandler.removeMessages(LONG_PRESS);
-                    mHandler.sendMessageAtTime(
-                            mHandler.obtainMessage(
-                                    LONG_PRESS,
-                                    TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS,
-                                    0 /* arg2 */),
-                            mCurrentDownEvent.getDownTime()
-                                    + ViewConfiguration.getLongPressTimeout());
+                    mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime()
+                            + ViewConfiguration.getLongPressTimeout());
                 }
                 mHandler.sendEmptyMessageAtTime(SHOW_PRESS,
                         mCurrentDownEvent.getDownTime() + TAP_TIMEOUT);
@@ -642,8 +613,6 @@
                 final float scrollY = mLastFocusY - focusY;
                 if (mIsDoubleTapping) {
                     // Give the move events of the double-tap
-                    recordGestureClassification(
-                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP);
                     handled |= mDoubleTapListener.onDoubleTapEvent(ev);
                 } else if (mAlwaysInTapRegion) {
                     final int deltaX = (int) (focusX - mDownFocusX);
@@ -666,12 +635,8 @@
                             // reschedule long press with a modified timeout.
                             mHandler.removeMessages(LONG_PRESS);
                             final long longPressTimeout = ViewConfiguration.getLongPressTimeout();
-                            mHandler.sendMessageAtTime(
-                                    mHandler.obtainMessage(
-                                            LONG_PRESS,
-                                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS,
-                                            0 /* arg2 */),
-                                    ev.getDownTime() + (long) (longPressTimeout * multiplier));
+                            mHandler.sendEmptyMessageAtTime(LONG_PRESS, ev.getDownTime()
+                                    + (long) (longPressTimeout * multiplier));
                         }
                         // Inhibit default scroll. If a gesture is ambiguous, we prevent scroll
                         // until the gesture is resolved.
@@ -681,8 +646,6 @@
                     }
 
                     if (distance > slopSquare) {
-                        recordGestureClassification(
-                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL);
                         handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
                         mLastFocusX = focusX;
                         mLastFocusY = focusY;
@@ -696,7 +659,6 @@
                         mAlwaysInBiggerTapRegion = false;
                     }
                 } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
-                    recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL);
                     handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
                     mLastFocusX = focusX;
                     mLastFocusY = focusY;
@@ -705,11 +667,7 @@
                         motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
                 if (deepPress && hasPendingLongPress) {
                     mHandler.removeMessages(LONG_PRESS);
-                    mHandler.sendMessage(
-                            mHandler.obtainMessage(
-                                  LONG_PRESS,
-                                  TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS,
-                                  0 /* arg2 */));
+                    mHandler.sendEmptyMessage(LONG_PRESS);
                 }
                 break;
 
@@ -718,15 +676,11 @@
                 MotionEvent currentUpEvent = MotionEvent.obtain(ev);
                 if (mIsDoubleTapping) {
                     // Finally, give the up event of the double-tap
-                    recordGestureClassification(
-                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP);
                     handled |= mDoubleTapListener.onDoubleTapEvent(ev);
                 } else if (mInLongPress) {
                     mHandler.removeMessages(TAP);
                     mInLongPress = false;
                 } else if (mAlwaysInTapRegion && !mIgnoreNextUpEvent) {
-                    recordGestureClassification(
-                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
                     handled = mListener.onSingleTapUp(ev);
                     if (mDeferConfirmSingleTap && mDoubleTapListener != null) {
                         mDoubleTapListener.onSingleTapConfirmed(ev);
@@ -867,21 +821,4 @@
         mInLongPress = true;
         mListener.onLongPress(mCurrentDownEvent);
     }
-
-    private void recordGestureClassification(int classification) {
-        if (mHasRecordedClassification
-                || classification
-                    == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
-            // Only record the first classification for an event stream.
-            return;
-        }
-        StatsLog.write(
-                StatsLog.TOUCH_GESTURE_CLASSIFIED,
-                getClass().getName(),
-                classification,
-                (int) (SystemClock.uptimeMillis() - mCurrentMotionEvent.getDownTime()),
-                (float) Math.hypot(mCurrentMotionEvent.getRawX() - mCurrentDownEvent.getRawX(),
-                                   mCurrentMotionEvent.getRawY() - mCurrentDownEvent.getRawY()));
-        mHasRecordedClassification = true;
-    }
 }
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index b1f934a..597b34bf 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -73,4 +73,33 @@
      * Hides the current input method if one is showing.
      */
     void hideCurrentInputMethod();
+
+    /**
+     * Set a state for controller whether would like to cancel recents animations with deferred
+     * task screenshot presentation.
+     *
+     * When we cancel the recents animation due to a stack order change, we can't just cancel it
+     * immediately as it would lead to a flicker in Launcher if we just remove the task from the
+     * leash. Instead we screenshot the previous task and replace the child of the leash with the
+     * screenshot, so that Launcher can still control the leash lifecycle & make the next app
+     * transition animate smoothly without flickering.
+     *
+     * @param screenshot When set {@code true}, means recents animation will be canceled when the
+     *                   next app launch. System will take previous task's screenshot when the next
+     *                   app transition starting, and skip previous task's animation.
+     *                   Set {@code false} means will not take screenshot & skip animation
+     *                   for previous task.
+     *
+     * @see #cleanupScreenshot()
+     * @see IRecentsAnimationRunner#onCancelled
+     */
+    void setCancelWithDeferredScreenshot(boolean screenshot);
+
+    /**
+     * Clean up the screenshot of previous task which was created during recents animation that
+     * was cancelled by a stack order change.
+     *
+     * @see {@link IRecentsAnimationRunner#onAnimationCanceled}
+     */
+    void cleanupScreenshot();
 }
diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl
index 6e382f4..9c652a8 100644
--- a/core/java/android/view/IRecentsAnimationRunner.aidl
+++ b/core/java/android/view/IRecentsAnimationRunner.aidl
@@ -32,9 +32,17 @@
      * Called when the system needs to cancel the current animation. This can be due to the
      * wallpaper not drawing in time, or the handler not finishing the animation within a predefined
      * amount of time.
+     *
+     * @param deferredWithScreenshot If set to {@code true}, the contents of the task will be
+     *                               replaced with a screenshot, such that the runner's leash is
+     *                               still active. As soon as the runner doesn't need the leash
+     *                               anymore, it can call
+     *                               {@link IRecentsAnimationController#cleanupScreenshot).
+     *
+     * @see {@link RecentsAnimationController#cleanupScreenshot}
      */
     @UnsupportedAppUsage
-    void onAnimationCanceled() = 1;
+    void onAnimationCanceled(boolean deferredWithScreenshot) = 1;
 
     /**
      * Called when the system is ready for the handler to start animating all the visible tasks.
diff --git a/core/java/android/view/ISystemGestureExclusionListener.aidl b/core/java/android/view/ISystemGestureExclusionListener.aidl
new file mode 100644
index 0000000..a032625
--- /dev/null
+++ b/core/java/android/view/ISystemGestureExclusionListener.aidl
@@ -0,0 +1,34 @@
+/**
+ * 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.view;
+
+import android.graphics.Region;
+
+/**
+ * Listener for changes to the system gesture exclusion region
+ *
+ * {@hide}
+ */
+oneway interface ISystemGestureExclusionListener {
+    /**
+     * Called when the system gesture exclusion for the given display changed.
+     * @param displayId the display whose system gesture exclusion changed
+     * @param systemGestureExclusion a {@code Region} where the app would like priority over the
+     *                               system gestures, in display coordinates.
+     */
+    void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion);
+}
\ No newline at end of file
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 9ee6585..b91b93f 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -40,6 +40,7 @@
 import android.view.IPinnedStackListener;
 import android.view.RemoteAnimationAdapter;
 import android.view.IRotationWatcher;
+import android.view.ISystemGestureExclusionListener;
 import android.view.IWallpaperVisibilityListener;
 import android.view.IWindowSession;
 import android.view.IWindowSessionCallback;
@@ -281,6 +282,18 @@
         int displayId);
 
     /**
+     * Registers a system gesture exclusion listener for a given display.
+     */
+    void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener,
+        int displayId);
+
+    /**
+     * Unregisters a system gesture exclusion listener for a given display.
+     */
+    void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener,
+        int displayId);
+
+    /**
      * Used only for assist -- request a screenshot of the current application.
      */
     boolean requestAssistScreenshot(IAssistDataReceiver receiver);
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 1fcd432..87efb3f 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -32,6 +32,8 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 
+import java.util.List;
+
 /**
  * System private per-application interface to the window manager.
  *
@@ -265,4 +267,10 @@
      * that new state.
      */
     void insetsModified(IWindow window, in InsetsState state);
+
+
+    /**
+     * Called when the system gesture exclusion has changed.
+     */
+    void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ab2cc66..75067d3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,10 +17,6 @@
 package android.view;
 
 import static android.content.res.Resources.ID_NULL;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
-import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
 
@@ -100,7 +96,6 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.StateSet;
-import android.util.StatsLog;
 import android.util.SuperNotCalledException;
 import android.util.TypedValue;
 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
@@ -11095,11 +11090,10 @@
      * <p>Computes the coordinates of this view in its surface. The argument
      * must be an array of two integers. After the method returns, the array
      * contains the x and y location in that order.</p>
-     * @hide
+     *
      * @param location an array of two integers in which to hold the coordinates
      */
-    @UnsupportedAppUsage
-    public void getLocationInSurface(@Size(2) int[] location) {
+    public void getLocationInSurface(@NonNull @Size(2) int[] location) {
         getLocationInWindow(location);
         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
@@ -14547,12 +14541,7 @@
                     if (clickable) {
                         setPressed(true, x, y);
                     }
-                    checkForLongClick(
-                            ViewConfiguration.getLongPressTimeout(),
-                            x,
-                            y,
-                            // This is not a touch gesture -- do not classify it as one.
-                            TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
+                    checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y);
                     return true;
                 }
             }
@@ -15293,11 +15282,7 @@
                     mHasPerformedLongPress = false;
 
                     if (!clickable) {
-                        checkForLongClick(
-                                ViewConfiguration.getLongPressTimeout(),
-                                x,
-                                y,
-                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
+                        checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y);
                         break;
                     }
 
@@ -15321,11 +15306,7 @@
                     } else {
                         // Not inside a scrolling container, so show the feedback right away
                         setPressed(true, x, y);
-                        checkForLongClick(
-                                ViewConfiguration.getLongPressTimeout(),
-                                x,
-                                y,
-                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
+                        checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y);
                     }
                     break;
 
@@ -15362,11 +15343,7 @@
                                     * ambiguousMultiplier);
                             // Subtract the time already spent
                             delay -= event.getEventTime() - event.getDownTime();
-                            checkForLongClick(
-                                    delay,
-                                    x,
-                                    y,
-                                    TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
+                            checkForLongClick(delay, x, y);
                         }
                         touchSlop *= ambiguousMultiplier;
                     }
@@ -15388,11 +15365,7 @@
                     if (deepPress && hasPendingLongPressCallback()) {
                         // process the long click action immediately
                         removeLongPressCallback();
-                        checkForLongClick(
-                                0 /* send immediately */,
-                                x,
-                                y,
-                                TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
+                        checkForLongClick(0 /* send immediately */, x, y);
                     }
 
                     break;
@@ -26057,7 +26030,7 @@
         }
     }
 
-    private void checkForLongClick(long delay, float x, float y, int classification) {
+    private void checkForLongClick(long delay, float x, float y) {
         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
             mHasPerformedLongPress = false;
 
@@ -26067,7 +26040,6 @@
             mPendingCheckForLongPress.setAnchor(x, y);
             mPendingCheckForLongPress.rememberWindowAttachCount();
             mPendingCheckForLongPress.rememberPressedState();
-            mPendingCheckForLongPress.setClassification(classification);
             postDelayed(mPendingCheckForLongPress, delay);
         }
     }
@@ -27625,17 +27597,11 @@
         private float mX;
         private float mY;
         private boolean mOriginalPressedState;
-        /**
-         * The classification of the long click being checked: one of the
-         * StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
-         */
-        private int mClassification;
 
         @Override
         public void run() {
             if ((mOriginalPressedState == isPressed()) && (mParent != null)
                     && mOriginalWindowAttachCount == mWindowAttachCount) {
-                recordGestureClassification(mClassification);
                 if (performLongClick(mX, mY)) {
                     mHasPerformedLongPress = true;
                 }
@@ -27654,10 +27620,6 @@
         public void rememberPressedState() {
             mOriginalPressedState = isPressed();
         }
-
-        public void setClassification(int classification) {
-            mClassification = classification;
-        }
     }
 
     private final class CheckForTap implements Runnable {
@@ -27670,28 +27632,17 @@
             setPressed(true, x, y);
             final long delay =
                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
-            checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
+            checkForLongClick(delay, x, y);
         }
     }
 
     private final class PerformClick implements Runnable {
         @Override
         public void run() {
-            recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
             performClickInternal();
         }
     }
 
-    /** Records a classification for the current event stream. */
-    private void recordGestureClassification(int classification) {
-        if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
-            return;
-        }
-        // To avoid negatively impacting View performance, the latency and displacement metrics
-        // are omitted.
-        StatsLog.write(StatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(), classification);
-    }
-
     /**
      * This method returns a ViewPropertyAnimator object, which can be used to animate
      * specific properties on this View.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a28d662..6d04cd31 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3987,7 +3987,11 @@
     void systemGestureExclusionChanged() {
         final List<Rect> rectsForWindowManager = mGestureExclusionTracker.computeChangedRects();
         if (rectsForWindowManager != null) {
-            // TODO Send to WM
+            try {
+                mWindowSession.reportSystemGestureExclusionChanged(mWindow, rectsForWindowManager);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
             mAttachInfo.mTreeObserver
                     .dispatchOnSystemGestureExclusionRectsChanged(rectsForWindowManager);
         }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 8f1896d..8cb04cb 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -228,6 +228,9 @@
     /** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED = 0x1;
     /** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2;
     /** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4;
+
+    /** @hide */ public static final int FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1;
+
     /** @hide */
     public static final int DEFAULT_LOGGING_LEVEL = Build.IS_DEBUGGABLE
             ? AutofillManager.FLAG_ADD_CLIENT_DEBUG
@@ -307,8 +310,8 @@
 
     /**
      * Same as {@link #STATE_UNKNOWN}, but used on
-     * {@link AutofillManagerClient#setSessionFinished(int)} when the session was finished because
-     * the URL bar changed on client mode
+     * {@link AutofillManagerClient#setSessionFinished(int, List)} when the session was finished
+     * because the URL bar changed on client mode
      *
      * @hide
      */
@@ -316,8 +319,8 @@
 
     /**
      * Same as {@link #STATE_UNKNOWN}, but used on
-     * {@link AutofillManagerClient#setSessionFinished(int)} when the session was finished because
-     * the service failed to fullfil a request.
+     * {@link AutofillManagerClient#setSessionFinished(int, List)} when the session was finished
+     * because the service failed to fullfil a request.
      *
      * @hide
      */
@@ -436,7 +439,7 @@
      * There is currently no session running.
      * {@hide}
      */
-    public static final int NO_SESSION = Integer.MIN_VALUE;
+    public static final int NO_SESSION = Integer.MAX_VALUE;
 
     private final IAutoFillManager mService;
 
@@ -513,6 +516,10 @@
     @Nullable
     private final AutofillOptions mOptions;
 
+    /** When set, session is only used for augmented autofill requests. */
+    @GuardedBy("mLock")
+    private boolean mForAugmentedAutofillOnly;
+
     /** @hide */
     public interface AutofillClient {
         /**
@@ -940,9 +947,8 @@
         ensureServiceClientAddedIfNeededLocked();
 
         if (!mEnabled) {
-            if (sVerbose) {
-                Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled");
-            }
+            if (sVerbose) Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled");
+
             if (mCallback != null) {
                 callback = mCallback;
             }
@@ -1025,6 +1031,12 @@
     private void notifyViewVisibilityChangedInternal(@NonNull View view, int virtualId,
             boolean isVisible, boolean virtual) {
         synchronized (mLock) {
+            if (mForAugmentedAutofillOnly) {
+                if (sVerbose) {
+                    Log.v(TAG,  "notifyViewVisibilityChanged(): ignoring on augmented only mode");
+                }
+                return;
+            }
             if (mEnabled && isActiveLocked()) {
                 final AutofillId id = virtual ? getAutofillId(view, virtualId)
                         : view.getAutofillId();
@@ -1168,6 +1180,10 @@
         AutofillValue value = null;
 
         synchronized (mLock) {
+            if (mForAugmentedAutofillOnly) {
+                if (sVerbose) Log.v(TAG,  "notifyValueChanged(): ignoring on augmented only mode");
+                return;
+            }
             // If the session is gone some fields might still be highlighted, hence we have to
             // remove the isAutofilled property even if no sessions are active.
             if (mLastAutofilledData == null) {
@@ -1221,6 +1237,10 @@
             return;
         }
         synchronized (mLock) {
+            if (mForAugmentedAutofillOnly) {
+                if (sVerbose) Log.v(TAG,  "notifyValueChanged(): ignoring on augmented only mode");
+                return;
+            }
             if (!mEnabled || !isActiveLocked()) {
                 if (sVerbose) {
                     Log.v(TAG, "notifyValueChanged(" + view.getAutofillId() + ":" + virtualId
@@ -1676,14 +1696,20 @@
             if (client == null) return; // NOTE: getClient() already logged it..
 
             final SyncResultReceiver receiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
+            final ComponentName componentName = client.autofillClientGetComponentName();
             mService.startSession(client.autofillClientGetActivityToken(),
                     mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
-                    mCallback != null, flags, client.autofillClientGetComponentName(),
+                    mCallback != null, flags, componentName,
                     isCompatibilityModeEnabledLocked(), receiver);
             mSessionId = receiver.getIntResult();
             if (mSessionId != NO_SESSION) {
                 mState = STATE_ACTIVE;
             }
+            final int extraFlags = receiver.getOptionalExtraIntResult(0);
+            if ((extraFlags & FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) != 0) {
+                if (sDebug) Log.d(TAG, "startSession(" + componentName + "): for augmented only");
+                mForAugmentedAutofillOnly = true;
+            }
             client.autofillClientResetableStateAvailable();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -2400,6 +2426,9 @@
             pw.print(pfx); pw.print("entered ids for augmented autofill: ");
             pw.println(mEnteredForAugmentedAutofillIds);
         }
+        if (mForAugmentedAutofillOnly) {
+            pw.print(pfx); pw.println("For Augmented Autofill Only");
+        }
         pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId);
         pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish);
         if (mOptions != null) {
diff --git a/core/java/android/view/inspector/InspectableNodeName.java b/core/java/android/view/inspector/InspectableNodeName.java
deleted file mode 100644
index 7b9a507..0000000
--- a/core/java/android/view/inspector/InspectableNodeName.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.view.inspector;
-
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.annotation.TestApi;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Marks the node name to display to a developer in the inspection tree.
- *
- * This annotation is optional to marking a class as inspectable. If it is omitted, the node name
- * will be inferred using the semantics of {@link Class#getSimpleName()}. The fully qualified class
- * name is always available in the tree, this is for display purposes only. If a class is inflated
- * from XML and the tag it inflates from does not match its simple name, this annotation should be
- * used to inform the inspector to display the XML tag name in the inspection tree view.
- *
- * This annotation does not inherit. If a class extends an annotated parent class, but does not
- * annotate itself, its node name will be inferred from its Java name.
- *
- * @see InspectionCompanion#getNodeName()
- * @hide
- */
-@Target({TYPE})
-@Retention(SOURCE)
-@TestApi
-public @interface InspectableNodeName {
-    /**
-     * The display name for nodes of this type.
-     *
-     * @return The name for nodes of this type
-     */
-    String value();
-}
diff --git a/core/java/android/view/inspector/InspectionCompanion.java b/core/java/android/view/inspector/InspectionCompanion.java
index 62d769b..a633a580 100644
--- a/core/java/android/view/inspector/InspectionCompanion.java
+++ b/core/java/android/view/inspector/InspectionCompanion.java
@@ -17,7 +17,6 @@
 package android.view.inspector;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 
 /**
  * An interface for companion objects used to inspect views.
@@ -33,11 +32,6 @@
  * parent class via the parent's inspection companion, and the child companion will only read
  * properties added or changed since the parent was defined.
  *
- * Only one child traversal is considered for each class. If a descendant class defines a
- * different child traversal than its parent, only the bottom traversal is used. If a class does
- * not define its own child traversal, but one of its ancestors does, the bottom-most ancestor's
- * traversal will be used.
- *
  * @param <T> The type of inspectable this is the companion to
  */
 public interface InspectionCompanion<T> {
@@ -68,22 +62,6 @@
     void readProperties(@NonNull T inspectable, @NonNull PropertyReader propertyReader);
 
     /**
-     * Get an optional name to display to developers for inspection nodes of this companion's type.
-     *
-     * The default implementation returns null, which will cause the runtime to use the class's
-     * simple name as defined by {@link Class#getSimpleName()} as the node name.
-     *
-     * If the type of this companion is inflated from XML, this method should be overridden to
-     * return the string used as the tag name for this type in XML.
-     *
-     * @return A string to use as the node name, or null to use the simple class name fallback.
-     */
-    @Nullable
-    default String getNodeName() {
-        return null;
-    }
-
-    /**
      * Thrown by {@link #readProperties(Object, PropertyReader)} if called before
      * {@link #mapProperties(PropertyMapper)}.
      */
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 494eb03..a46580d 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -245,10 +245,11 @@
     /**
      * Used with {@link #setForceDark}
      *
-     * Enable force dark, dependent on the state of the WebView parent. If the WebView parent view
-     * is being automatically rendered in dark mode, then WebView content will be rendered so as to
-     * emulate a dark theme. WebViews that are not attached to the view hierarchy will not be
-     * inverted.
+     * Enable force dark dependent on the state of the WebView parent view. If the WebView parent
+     * view is being automatically force darkened
+     * (see: {@link android.view.View#setForceDarkAllowed}), then WebView content will be rendered
+     * so as to emulate a dark theme. WebViews that are not attached to the view hierarchy will not
+     * be inverted.
      */
     public static final int FORCE_DARK_AUTO = 1;
 
@@ -1466,6 +1467,8 @@
 
     /**
      * Set the force dark mode for this WebView.
+     *
+     * @param forceDark the force dark mode to set.
      */
     public void setForceDark(@ForceDark int forceDark) {
         // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
@@ -1474,6 +1477,8 @@
     /**
      * Get the force dark mode for this WebView.
      *
+     * The default force dark mode is {@link #FORCE_DARK_AUTO}
+     *
      * @return the currently set force dark mode.
      */
     public @ForceDark int getForceDark() {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index b6ec5f9..c9ef038 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -4984,9 +4984,6 @@
             if (magnifierTopLeft == null) {
                 return;
             }
-            final Rect surfaceInsets =
-                    mTextView.getViewRootImpl().mWindowAttributes.surfaceInsets;
-            magnifierTopLeft.offset(-surfaceInsets.left, -surfaceInsets.top);
             final Rect magnifierRect = new Rect(magnifierTopLeft.x, magnifierTopLeft.y,
                     magnifierTopLeft.x + mMagnifierAnimator.mMagnifier.getWidth(),
                     magnifierTopLeft.y + mMagnifierAnimator.mMagnifier.getHeight());
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 50e8836..08799cf 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -471,13 +471,13 @@
     }
 
     /**
-     * Returns the top left coordinates of the magnifier, relative to the surface of the
-     * main application window. They will be determined by the coordinates of the last
-     * {@link #show(float, float)} or {@link #show(float, float, float, float)} call, adjusted
-     * to take into account any potential clamping behavior. The method can be used immediately
-     * after a #show call to find out where the magnifier will be positioned. However, the
-     * position of the magnifier will not be updated in the same frame due to the async
-     * copying of the content copying and of the magnifier rendering.
+     * Returns the top left coordinates of the magnifier, relative to the main application
+     * window. They will be determined by the coordinates of the last {@link #show(float, float)}
+     * or {@link #show(float, float, float, float)} call, adjusted to take into account any
+     * potential clamping behavior. The method can be used immediately after a #show
+     * call to find out where the magnifier will be positioned. However, the position of the
+     * magnifier will not be updated visually in the same frame, due to the async nature of
+     * the content copying and of the magnifier rendering.
      * The method will return {@code null} if #show has not yet been called, or if the last
      * operation performed was a #dismiss.
      *
@@ -488,15 +488,18 @@
         if (mWindow == null) {
             return null;
         }
-        return new Point(getCurrentClampedWindowCoordinates());
+        final Point position = getCurrentClampedWindowCoordinates();
+        position.offset(-mParentSurface.mInsets.left, -mParentSurface.mInsets.top);
+        return new Point(position);
     }
 
     /**
      * Returns the top left coordinates of the magnifier source (i.e. the view region going to
-     * be magnified and copied to the magnifier), relative to the surface the content is copied
-     * from. The content will be copied:
+     * be magnified and copied to the magnifier), relative to the window or surface the content
+     * is copied from. The content will be copied:
      * - if the magnified view is a {@link SurfaceView}, from the surface backing it
-     * - otherwise, from the surface of the main application window
+     * - otherwise, from the surface backing the main application window, and the coordinates
+     *   returned will be relative to the main application window
      * The method will return {@code null} if #show has not yet been called, or if the last
      * operation performed was a #dismiss.
      *
@@ -507,7 +510,9 @@
         if (mWindow == null) {
             return null;
         }
-        return new Point(mPixelCopyRequestRect.left, mPixelCopyRequestRect.top);
+        final Point position = new Point(mPixelCopyRequestRect.left, mPixelCopyRequestRect.top);
+        position.offset(-mContentCopySurface.mInsets.left, -mContentCopySurface.mInsets.top);
+        return new Point(position);
     }
 
     /**
@@ -531,7 +536,7 @@
                         viewRootImpl.getHeight() + surfaceInsets.top + surfaceInsets.bottom;
                 validMainWindowSurface =
                         new SurfaceInfo(viewRootImpl.getSurfaceControl(), mainWindowSurface,
-                                surfaceWidth, surfaceHeight, true);
+                                surfaceWidth, surfaceHeight, surfaceInsets, true);
             }
         }
         // Get the surface backing the magnified view, if it is a SurfaceView.
@@ -544,7 +549,7 @@
             if (sc != null && sc.isValid()) {
                 final Rect surfaceFrame = surfaceHolder.getSurfaceFrame();
                 validSurfaceViewSurface = new SurfaceInfo(sc, surfaceViewSurface,
-                        surfaceFrame.right, surfaceFrame.bottom, false);
+                        surfaceFrame.right, surfaceFrame.bottom, new Rect(), false);
             }
         }
 
@@ -708,9 +713,13 @@
         final Rect windowBounds;
         if (mParentSurface.mIsMainWindowSurface) {
             final Insets systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
-            windowBounds = new Rect(systemInsets.left, systemInsets.top,
-                    mParentSurface.mWidth - systemInsets.right,
-                    mParentSurface.mHeight - systemInsets.bottom);
+            windowBounds = new Rect(
+                    systemInsets.left + mParentSurface.mInsets.left,
+                    systemInsets.top + mParentSurface.mInsets.top,
+                    mParentSurface.mWidth - systemInsets.right - mParentSurface.mInsets.right,
+                    mParentSurface.mHeight - systemInsets.bottom
+                            - mParentSurface.mInsets.bottom
+            );
         } else {
             windowBounds = new Rect(0, 0, mParentSurface.mWidth, mParentSurface.mHeight);
         }
@@ -725,21 +734,23 @@
      * Contains a surface and metadata corresponding to it.
      */
     private static class SurfaceInfo {
-        public static final SurfaceInfo NULL = new SurfaceInfo(null, null, 0, 0, false);
+        public static final SurfaceInfo NULL = new SurfaceInfo(null, null, 0, 0, null, false);
 
         private Surface mSurface;
         private SurfaceControl mSurfaceControl;
         private int mWidth;
         private int mHeight;
+        private Rect mInsets;
         private boolean mIsMainWindowSurface;
 
         SurfaceInfo(final SurfaceControl surfaceControl, final Surface surface,
-                final int width, final int height,
+                final int width, final int height, final Rect insets,
                 final boolean isMainWindowSurface) {
             mSurfaceControl = surfaceControl;
             mSurface = surface;
             mWidth = width;
             mHeight = height;
+            mInsets = insets;
             mIsMainWindowSurface = isMainWindowSurface;
         }
     }
diff --git a/core/java/android/widget/TEST_MAPPING b/core/java/android/widget/TEST_MAPPING
new file mode 100644
index 0000000..ee378ff
--- /dev/null
+++ b/core/java/android/widget/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsWidgetTestCases",
+      "options": [
+        {
+          "instrumentation-arg": "size:=small"
+        }
+      ]
+    }
+  ]
+}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index c4af4c7..1c90182 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -79,4 +79,6 @@
     void stopWatchingNoted(IAppOpsNotedCallback callback);
 
     int checkOperationRaw(int code, int uid, String packageName);
+
+    void reloadNonHistoricalState();
 }
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index f8117a7..c9baf00 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -79,14 +79,14 @@
     Intent dataManagementIntent();
 
     /**
-     * On demand, supply a short string that can be shown to the user as the label
-     * on an overflow menu item used to invoked the data management UI.
+     * On demand, supply a short {@link CharSequence} that can be shown to the user as the label on
+     * an overflow menu item used to invoke the data management UI.
      *
-     * @return A string to be used as the label for the transport's data management
+     * @return A {@link CharSequence} to be used as the label for the transport's data management
      *         affordance.  If the transport supplies a data management intent, this
      *         method must not return {@code null}.
      */
-    String dataManagementLabel();
+    CharSequence dataManagementIntentLabel();
 
     /**
      * Ask the transport where, on local device storage, to keep backup state blobs.
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index ead98e7..e85508e 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -368,6 +368,11 @@
 
     public void refreshStats(int statsType, SparseArray<UserHandle> asUsers, long rawRealtimeUs,
             long rawUptimeUs) {
+        if (statsType != BatteryStats.STATS_SINCE_CHARGED) {
+            Log.w(TAG, "refreshStats called for statsType " + statsType + " but only "
+                    + "STATS_SINCE_CHARGED is supported. Using STATS_SINCE_CHARGED instead.");
+        }
+
         // Initialize mStats if necessary.
         getStats();
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8679dcb..1fc7635 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -145,7 +145,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    static final int VERSION = 185 + (USE_OLD_HISTORY ? 1000 : 0);
+    static final int VERSION = 186 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // The maximum number of names wakelocks we will keep track of
     // per uid; once the limit is reached, we batch the remaining wakelocks
@@ -991,8 +991,6 @@
     private int mPhoneSimStateRaw = -1;
 
     private int mNumConnectivityChange;
-    private int mLoadedNumConnectivityChange;
-    private int mUnpluggedNumConnectivityChange;
 
     private int mEstimatedBatteryCapacity = -1;
 
@@ -1225,27 +1223,11 @@
         }
 
         public long computeUptime(long curTime, int which) {
-            switch (which) {
-                case STATS_SINCE_CHARGED:
-                    return mUptime + getUptime(curTime);
-                case STATS_CURRENT:
-                    return getUptime(curTime);
-                case STATS_SINCE_UNPLUGGED:
-                    return getUptime(curTime) - mUnpluggedUptime;
-            }
-            return 0;
+            return mUptime + getUptime(curTime);
         }
 
         public long computeRealtime(long curTime, int which) {
-            switch (which) {
-                case STATS_SINCE_CHARGED:
-                    return mRealtime + getRealtime(curTime);
-                case STATS_CURRENT:
-                    return getRealtime(curTime);
-                case STATS_SINCE_UNPLUGGED:
-                    return getRealtime(curTime) - mUnpluggedRealtime;
-            }
-            return 0;
+            return mRealtime + getRealtime(curTime);
         }
 
         public long getUptime(long curTime) {
@@ -1352,16 +1334,10 @@
         @UnsupportedAppUsage
         final AtomicInteger mCount = new AtomicInteger();
         final TimeBase mTimeBase;
-        int mLoadedCount;
-        int mUnpluggedCount;
-        int mPluggedCount;
 
         public Counter(TimeBase timeBase, Parcel in) {
             mTimeBase = timeBase;
-            mPluggedCount = in.readInt();
-            mCount.set(mPluggedCount);
-            mLoadedCount = in.readInt();
-            mUnpluggedCount = in.readInt();
+            mCount.set(in.readInt());
             timeBase.add(this);
         }
 
@@ -1372,18 +1348,14 @@
 
         public void writeToParcel(Parcel out) {
             out.writeInt(mCount.get());
-            out.writeInt(mLoadedCount);
-            out.writeInt(mUnpluggedCount);
         }
 
         @Override
         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
-            mUnpluggedCount = mPluggedCount;
         }
 
         @Override
         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
-            mPluggedCount = mCount.get();
         }
 
         /**
@@ -1417,21 +1389,11 @@
 
         @Override
         public int getCountLocked(int which) {
-            int val = mCount.get();
-            if (which == STATS_SINCE_UNPLUGGED) {
-                val -= mUnpluggedCount;
-            } else if (which != STATS_SINCE_CHARGED) {
-                val -= mLoadedCount;
-            }
-
-            return val;
+            return mCount.get();
         }
 
         public void logState(Printer pw, String prefix) {
-            pw.println(prefix + "mCount=" + mCount.get()
-                    + " mLoadedCount=" + mLoadedCount
-                    + " mUnpluggedCount=" + mUnpluggedCount
-                    + " mPluggedCount=" + mPluggedCount);
+            pw.println(prefix + "mCount=" + mCount.get());
         }
 
         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -1453,7 +1415,6 @@
         @Override
         public boolean reset(boolean detachIfReset) {
             mCount.set(0);
-            mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
             if (detachIfReset) {
                 detach();
             }
@@ -1467,15 +1428,12 @@
 
         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
         public void writeSummaryFromParcelLocked(Parcel out) {
-            int count = mCount.get();
-            out.writeInt(count);
+            out.writeInt(mCount.get());
         }
 
         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
         public void readSummaryFromParcelLocked(Parcel in) {
-            mLoadedCount = in.readInt();
-            mCount.set(mLoadedCount);
-            mUnpluggedCount = mPluggedCount = mLoadedCount;
+            mCount.set(in.readInt());
         }
     }
 
@@ -1483,14 +1441,10 @@
     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
         final TimeBase mTimeBase;
         public long[] mCounts;
-        public long[] mLoadedCounts;
-        public long[] mUnpluggedCounts;
 
         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
             mTimeBase = timeBase;
             mCounts = in.createLongArray();
-            mLoadedCounts = in.createLongArray();
-            mUnpluggedCounts = in.createLongArray();
             timeBase.add(this);
         }
 
@@ -1501,13 +1455,10 @@
 
         private void writeToParcel(Parcel out) {
             out.writeLongArray(mCounts);
-            out.writeLongArray(mLoadedCounts);
-            out.writeLongArray(mUnpluggedCounts);
         }
 
         @Override
         public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
-            mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
         }
 
         @Override
@@ -1516,20 +1467,12 @@
 
         @Override
         public long[] getCountsLocked(int which) {
-            long[] val = copyArray(mCounts, null);
-            if (which == STATS_SINCE_UNPLUGGED) {
-                subtract(val, mUnpluggedCounts);
-            } else if (which != STATS_SINCE_CHARGED) {
-                subtract(val, mLoadedCounts);
-            }
-            return val;
+            return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
         }
 
         @Override
         public void logState(Printer pw, String prefix) {
-            pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
-                    + " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
-                    + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts));
+            pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
         }
 
         public void addCountLocked(long[] counts) {
@@ -1559,9 +1502,9 @@
          */
         @Override
         public boolean reset(boolean detachIfReset) {
-            fillArray(mCounts, 0);
-            fillArray(mLoadedCounts, 0);
-            fillArray(mUnpluggedCounts, 0);
+            if (mCounts != null) {
+                Arrays.fill(mCounts, 0);
+            }
             if (detachIfReset) {
                 detach();
             }
@@ -1579,8 +1522,6 @@
 
         private void readSummaryFromParcelLocked(Parcel in) {
             mCounts = in.createLongArray();
-            mLoadedCounts = copyArray(mCounts, mLoadedCounts);
-            mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
         }
 
         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
@@ -1621,49 +1562,16 @@
                 return null;
             }
         }
-
-        private static void fillArray(long[] a, long val) {
-            if (a != null) {
-                Arrays.fill(a, val);
-            }
-        }
-
-        private static void subtract(@NonNull long[] val, long[] toSubtract) {
-            if (toSubtract == null) {
-                return;
-            }
-            for (int i = 0; i < val.length; i++) {
-                val[i] -= toSubtract[i];
-            }
-        }
-
-        private static long[] copyArray(long[] src, long[] dest) {
-            if (src == null) {
-                return null;
-            } else {
-                if (dest == null) {
-                    dest = new long[src.length];
-                }
-                System.arraycopy(src, 0, dest, 0, src.length);
-                return dest;
-            }
-        }
     }
 
     @VisibleForTesting
     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
         final TimeBase mTimeBase;
-        public long mCount;
-        public long mCurrentCount;
-        public long mLoadedCount;
-        public long mUnpluggedCount;
+        private long mCount;
 
         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
             mTimeBase = timeBase;
             mCount = in.readLong();
-            mCurrentCount = in.readLong();
-            mLoadedCount = in.readLong();
-            mUnpluggedCount = in.readLong();
             timeBase.add(this);
         }
 
@@ -1674,14 +1582,10 @@
 
         public void writeToParcel(Parcel out) {
             out.writeLong(mCount);
-            out.writeLong(mCurrentCount);
-            out.writeLong(mLoadedCount);
-            out.writeLong(mUnpluggedCount);
         }
 
         @Override
         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
-            mUnpluggedCount = mCount;
         }
 
         @Override
@@ -1689,43 +1593,22 @@
         }
 
         public long getCountLocked(int which) {
-            long val = mCount;
-            if (which == STATS_SINCE_UNPLUGGED) {
-                val -= mUnpluggedCount;
-            } else if (which != STATS_SINCE_CHARGED) {
-                val -= mLoadedCount;
-            }
-            return val;
+            return mCount;
         }
 
         @Override
         public void logState(Printer pw, String prefix) {
-            pw.println(prefix + "mCount=" + mCount
-                    + " mCurrentCount=" + mCurrentCount
-                    + " mLoadedCount=" + mLoadedCount
-                    + " mUnpluggedCount=" + mUnpluggedCount);
+            pw.println(prefix + "mCount=" + mCount);
         }
 
         public void addCountLocked(long count) {
-            update(mCurrentCount + count, mTimeBase.isRunning());
+            addCountLocked(count, mTimeBase.isRunning());
         }
 
         public void addCountLocked(long count, boolean isRunning) {
-            update(mCurrentCount + count, isRunning);
-        }
-
-        public void update(long count) {
-            update(count, mTimeBase.isRunning());
-        }
-
-        public void update(long count, boolean isRunning) {
-            if (count < mCurrentCount) {
-                mCurrentCount = 0;
-            }
             if (isRunning) {
-                mCount += count - mCurrentCount;
+                mCount += count;
             }
-            mCurrentCount = count;
         }
 
         /**
@@ -1734,7 +1617,6 @@
         @Override
         public boolean reset(boolean detachIfReset) {
             mCount = 0;
-            mLoadedCount = mUnpluggedCount = 0;
             if (detachIfReset) {
                 detach();
             }
@@ -1751,7 +1633,7 @@
         }
 
         public void readSummaryFromParcelLocked(Parcel in) {
-            mCount = mUnpluggedCount= mLoadedCount = in.readLong();
+            mCount = in.readLong();
         }
     }
 
@@ -1764,9 +1646,6 @@
         protected final TimeBase mTimeBase;
 
         protected int mCount;
-        protected int mLoadedCount;
-        protected int mLastCount;
-        protected int mUnpluggedCount;
 
         // Times are in microseconds for better accuracy when dividing by the
         // lock count, and are in "battery realtime" units.
@@ -1779,25 +1658,6 @@
         protected long mTotalTime;
 
         /**
-         * The total time we loaded for the previous runs.  Subtract this from
-         * mTotalTime to find the time for the current run of the system.
-         */
-        protected long mLoadedTime;
-
-        /**
-         * The run time of the last run of the system, as loaded from the
-         * saved data.
-         */
-        protected long mLastTime;
-
-        /**
-         * The value of mTotalTime when unplug() was last called.  Subtract
-         * this from mTotalTime to find the time since the last unplug from
-         * power.
-         */
-        protected long mUnpluggedTime;
-
-        /**
          * The total time this timer has been running until the latest mark has been set.
          * Subtract this from mTotalTime to get the time spent running since the mark was set.
          */
@@ -1815,13 +1675,7 @@
             mTimeBase = timeBase;
 
             mCount = in.readInt();
-            mLoadedCount = in.readInt();
-            mLastCount = 0;
-            mUnpluggedCount = in.readInt();
             mTotalTime = in.readLong();
-            mLoadedTime = in.readLong();
-            mLastTime = 0;
-            mUnpluggedTime = in.readLong();
             mTimeBeforeMark = in.readLong();
             timeBase.add(this);
             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
@@ -1834,6 +1688,16 @@
             timeBase.add(this);
         }
 
+        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
+            if (DEBUG) {
+                Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
+                        + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
+            }
+            out.writeInt(computeCurrentCountLocked());
+            out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
+            out.writeLong(mTimeBeforeMark);
+        }
+
         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
 
         protected abstract int computeCurrentCountLocked();
@@ -1844,8 +1708,8 @@
          */
         @Override
         public boolean reset(boolean detachIfReset) {
-            mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
-            mCount = mLoadedCount = mLastCount = 0;
+            mTotalTime = mTimeBeforeMark = 0;
+            mCount = 0;
             if (detachIfReset) {
                 detach();
             }
@@ -1857,32 +1721,8 @@
             mTimeBase.remove(this);
         }
 
-        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
-            if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
-                    + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
-            out.writeInt(computeCurrentCountLocked());
-            out.writeInt(mLoadedCount);
-            out.writeInt(mUnpluggedCount);
-            out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
-            out.writeLong(mLoadedTime);
-            out.writeLong(mUnpluggedTime);
-            out.writeLong(mTimeBeforeMark);
-        }
-
         @Override
         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
-            if (DEBUG && mType < 0) {
-                Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
-                        + " old mUnpluggedTime=" + mUnpluggedTime
-                        + " old mUnpluggedCount=" + mUnpluggedCount);
-            }
-            mUnpluggedTime = computeRunTimeLocked(baseRealtime);
-            mUnpluggedCount = computeCurrentCountLocked();
-            if (DEBUG && mType < 0) {
-                Log.v(TAG, "unplug #" + mType
-                        + ": new mUnpluggedTime=" + mUnpluggedTime
-                        + " new mUnpluggedCount=" + mUnpluggedCount);
-            }
         }
 
         @Override
@@ -1894,8 +1734,7 @@
             mTotalTime = computeRunTimeLocked(baseRealtime);
             mCount = computeCurrentCountLocked();
             if (DEBUG && mType < 0) {
-                Log.v(TAG, "plug #" + mType
-                        + ": new mTotalTime=" + mTotalTime);
+                Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTime);
             }
         }
 
@@ -1912,34 +1751,19 @@
                 return;
             }
             out.writeInt(1); // indicates non-null
-
             timer.writeToParcel(out, elapsedRealtimeUs);
         }
 
         @Override
         @UnsupportedAppUsage
         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
-            long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
-            if (which == STATS_SINCE_UNPLUGGED) {
-                val -= mUnpluggedTime;
-            } else if (which != STATS_SINCE_CHARGED) {
-                val -= mLoadedTime;
-            }
-
-            return val;
+            return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
         }
 
         @Override
         @UnsupportedAppUsage
         public int getCountLocked(int which) {
-            int val = computeCurrentCountLocked();
-            if (which == STATS_SINCE_UNPLUGGED) {
-                val -= mUnpluggedCount;
-            } else if (which != STATS_SINCE_CHARGED) {
-                val -= mLoadedCount;
-            }
-
-            return val;
+            return computeCurrentCountLocked();
         }
 
         @Override
@@ -1950,13 +1774,8 @@
 
         @Override
         public void logState(Printer pw, String prefix) {
-            pw.println(prefix + "mCount=" + mCount
-                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
-                    + " mUnpluggedCount=" + mUnpluggedCount);
-            pw.println(prefix + "mTotalTime=" + mTotalTime
-                    + " mLoadedTime=" + mLoadedTime);
-            pw.println(prefix + "mLastTime=" + mLastTime
-                    + " mUnpluggedTime=" + mUnpluggedTime);
+            pw.println(prefix + "mCount=" + mCount);
+            pw.println(prefix + "mTotalTime=" + mTotalTime);
         }
 
 
@@ -1968,13 +1787,8 @@
 
         public void readSummaryFromParcelLocked(Parcel in) {
             // Multiply by 1000 for backwards compatibility
-            mTotalTime = mLoadedTime = in.readLong();
-            mLastTime = 0;
-            mUnpluggedTime = mTotalTime;
-            mCount = mLoadedCount = in.readInt();
-            mLastCount = 0;
-            mUnpluggedCount = mCount;
-
+            mTotalTime = in.readLong();
+            mCount = in.readInt();
             // When reading the summary, we set the mark to be the latest information.
             mTimeBeforeMark = mTotalTime;
         }
@@ -2233,7 +2047,7 @@
 
         private long computeOverage(long curTime) {
             if (mLastAddedTime > 0) {
-                return mLastTime + mLastAddedDuration - curTime;
+                return mLastAddedDuration - curTime;
             }
             return 0;
         }
@@ -2452,7 +2266,7 @@
             mTotalDurationMs = 0;
             mCurrentDurationMs = 0;
             if (mNesting > 0) {
-                mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
+                mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000) / 1000;
             } else {
                 mStartTimeMs = -1;
             }
@@ -2491,7 +2305,7 @@
         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
             long durationMs = mCurrentDurationMs;
             if (mNesting > 0 && mTimeBase.isRunning()) {
-                durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
+                durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
                         - mStartTimeMs;
             }
             return durationMs;
@@ -6401,13 +6215,7 @@
     }
 
     @Override public int getNumConnectivityChange(int which) {
-        int val = mNumConnectivityChange;
-        if (which == STATS_CURRENT) {
-            val -= mLoadedNumConnectivityChange;
-        } else if (which == STATS_SINCE_UNPLUGGED) {
-            val -= mUnpluggedNumConnectivityChange;
-        }
-        return val;
+        return mNumConnectivityChange;
     }
 
     @Override public long getGpsSignalQualityTime(int strengthBin,
@@ -9122,66 +8930,6 @@
              */
             int mNumAnrs;
 
-            /**
-             * The amount of user time loaded from a previous save.
-             */
-            long mLoadedUserTime;
-
-            /**
-             * The amount of system time loaded from a previous save.
-             */
-            long mLoadedSystemTime;
-
-            /**
-             * The amount of foreground time loaded from a previous save.
-             */
-            long mLoadedForegroundTime;
-
-            /**
-             * The number of times the process has started from a previous save.
-             */
-            int mLoadedStarts;
-
-            /**
-             * Number of times the process has crashed from a previous save.
-             */
-            int mLoadedNumCrashes;
-
-            /**
-             * Number of times the process has had an ANR from a previous save.
-             */
-            int mLoadedNumAnrs;
-
-            /**
-             * The amount of user time when last unplugged.
-             */
-            long mUnpluggedUserTime;
-
-            /**
-             * The amount of system time when last unplugged.
-             */
-            long mUnpluggedSystemTime;
-
-            /**
-             * The amount of foreground time since unplugged.
-             */
-            long mUnpluggedForegroundTime;
-
-            /**
-             * The number of times the process has started before unplugged.
-             */
-            int mUnpluggedStarts;
-
-            /**
-             * Number of times the process has crashed before unplugged.
-             */
-            int mUnpluggedNumCrashes;
-
-            /**
-             * Number of times the process has had an ANR before unplugged.
-             */
-            int mUnpluggedNumAnrs;
-
             ArrayList<ExcessivePower> mExcessivePower;
 
             public Proc(BatteryStatsImpl bsi, String name) {
@@ -9191,12 +8939,6 @@
             }
 
             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
-                mUnpluggedUserTime = mUserTime;
-                mUnpluggedSystemTime = mSystemTime;
-                mUnpluggedForegroundTime = mForegroundTime;
-                mUnpluggedStarts = mStarts;
-                mUnpluggedNumCrashes = mNumCrashes;
-                mUnpluggedNumAnrs = mNumAnrs;
             }
 
             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
@@ -9283,18 +9025,6 @@
                 out.writeInt(mStarts);
                 out.writeInt(mNumCrashes);
                 out.writeInt(mNumAnrs);
-                out.writeLong(mLoadedUserTime);
-                out.writeLong(mLoadedSystemTime);
-                out.writeLong(mLoadedForegroundTime);
-                out.writeInt(mLoadedStarts);
-                out.writeInt(mLoadedNumCrashes);
-                out.writeInt(mLoadedNumAnrs);
-                out.writeLong(mUnpluggedUserTime);
-                out.writeLong(mUnpluggedSystemTime);
-                out.writeLong(mUnpluggedForegroundTime);
-                out.writeInt(mUnpluggedStarts);
-                out.writeInt(mUnpluggedNumCrashes);
-                out.writeInt(mUnpluggedNumAnrs);
                 writeExcessivePowerToParcelLocked(out);
             }
 
@@ -9305,18 +9035,6 @@
                 mStarts = in.readInt();
                 mNumCrashes = in.readInt();
                 mNumAnrs = in.readInt();
-                mLoadedUserTime = in.readLong();
-                mLoadedSystemTime = in.readLong();
-                mLoadedForegroundTime = in.readLong();
-                mLoadedStarts = in.readInt();
-                mLoadedNumCrashes = in.readInt();
-                mLoadedNumAnrs = in.readInt();
-                mUnpluggedUserTime = in.readLong();
-                mUnpluggedSystemTime = in.readLong();
-                mUnpluggedForegroundTime = in.readLong();
-                mUnpluggedStarts = in.readInt();
-                mUnpluggedNumCrashes = in.readInt();
-                mUnpluggedNumAnrs = in.readInt();
                 readExcessivePowerFromParcelLocked(in);
             }
 
@@ -9358,71 +9076,35 @@
             @Override
             @UnsupportedAppUsage
             public long getUserTime(int which) {
-                long val = mUserTime;
-                if (which == STATS_CURRENT) {
-                    val -= mLoadedUserTime;
-                } else if (which == STATS_SINCE_UNPLUGGED) {
-                    val -= mUnpluggedUserTime;
-                }
-                return val;
+                return mUserTime;
             }
 
             @Override
             @UnsupportedAppUsage
             public long getSystemTime(int which) {
-                long val = mSystemTime;
-                if (which == STATS_CURRENT) {
-                    val -= mLoadedSystemTime;
-                } else if (which == STATS_SINCE_UNPLUGGED) {
-                    val -= mUnpluggedSystemTime;
-                }
-                return val;
+                return mSystemTime;
             }
 
             @Override
             @UnsupportedAppUsage
             public long getForegroundTime(int which) {
-                long val = mForegroundTime;
-                if (which == STATS_CURRENT) {
-                    val -= mLoadedForegroundTime;
-                } else if (which == STATS_SINCE_UNPLUGGED) {
-                    val -= mUnpluggedForegroundTime;
-                }
-                return val;
+                return mForegroundTime;
             }
 
             @Override
             @UnsupportedAppUsage
             public int getStarts(int which) {
-                int val = mStarts;
-                if (which == STATS_CURRENT) {
-                    val -= mLoadedStarts;
-                } else if (which == STATS_SINCE_UNPLUGGED) {
-                    val -= mUnpluggedStarts;
-                }
-                return val;
+                return mStarts;
             }
 
             @Override
             public int getNumCrashes(int which) {
-                int val = mNumCrashes;
-                if (which == STATS_CURRENT) {
-                    val -= mLoadedNumCrashes;
-                } else if (which == STATS_SINCE_UNPLUGGED) {
-                    val -= mUnpluggedNumCrashes;
-                }
-                return val;
+                return mNumCrashes;
             }
 
             @Override
             public int getNumAnrs(int which) {
-                int val = mNumAnrs;
-                if (which == STATS_CURRENT) {
-                    val -= mLoadedNumAnrs;
-                } else if (which == STATS_SINCE_UNPLUGGED) {
-                    val -= mUnpluggedNumAnrs;
-                }
-                return val;
+                return mNumAnrs;
             }
         }
 
@@ -9588,54 +9270,6 @@
                 protected int mLaunches;
 
                 /**
-                 * The amount of time spent started loaded from a previous save
-                 * (ms in battery uptime).
-                 */
-                protected long mLoadedStartTime;
-
-                /**
-                 * The number of starts loaded from a previous save.
-                 */
-                protected int mLoadedStarts;
-
-                /**
-                 * The number of launches loaded from a previous save.
-                 */
-                protected int mLoadedLaunches;
-
-                /**
-                 * The amount of time spent started as of the last run (ms
-                 * in battery uptime).
-                 */
-                protected long mLastStartTime;
-
-                /**
-                 * The number of starts as of the last run.
-                 */
-                protected int mLastStarts;
-
-                /**
-                 * The number of launches as of the last run.
-                 */
-                protected int mLastLaunches;
-
-                /**
-                 * The amount of time spent started when last unplugged (ms
-                 * in battery uptime).
-                 */
-                protected long mUnpluggedStartTime;
-
-                /**
-                 * The number of starts when last unplugged.
-                 */
-                protected int mUnpluggedStarts;
-
-                /**
-                 * The number of launches when last unplugged.
-                 */
-                protected int mUnpluggedLaunches;
-
-                /**
                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
                  */
                 public Serv(BatteryStatsImpl bsi) {
@@ -9645,9 +9279,6 @@
 
                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
                         long baseRealtime) {
-                    mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
-                    mUnpluggedStarts = mStarts;
-                    mUnpluggedLaunches = mLaunches;
                 }
 
                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
@@ -9679,15 +9310,6 @@
                     mLaunchedSince = in.readLong();
                     mLaunched = in.readInt() != 0;
                     mLaunches = in.readInt();
-                    mLoadedStartTime = in.readLong();
-                    mLoadedStarts = in.readInt();
-                    mLoadedLaunches = in.readInt();
-                    mLastStartTime = 0;
-                    mLastStarts = 0;
-                    mLastLaunches = 0;
-                    mUnpluggedStartTime = in.readLong();
-                    mUnpluggedStarts = in.readInt();
-                    mUnpluggedLaunches = in.readInt();
                 }
 
                 public void writeToParcelLocked(Parcel out) {
@@ -9699,12 +9321,6 @@
                     out.writeLong(mLaunchedSince);
                     out.writeInt(mLaunched ? 1 : 0);
                     out.writeInt(mLaunches);
-                    out.writeLong(mLoadedStartTime);
-                    out.writeInt(mLoadedStarts);
-                    out.writeInt(mLoadedLaunches);
-                    out.writeLong(mUnpluggedStartTime);
-                    out.writeInt(mUnpluggedStarts);
-                    out.writeInt(mUnpluggedLaunches);
                 }
 
                 public long getLaunchTimeToNowLocked(long batteryUptime) {
@@ -9768,36 +9384,17 @@
 
                 @Override
                 public int getLaunches(int which) {
-                    int val = mLaunches;
-                    if (which == STATS_CURRENT) {
-                        val -= mLoadedLaunches;
-                    } else if (which == STATS_SINCE_UNPLUGGED) {
-                        val -= mUnpluggedLaunches;
-                    }
-                    return val;
+                    return mLaunches;
                 }
 
                 @Override
                 public long getStartTime(long now, int which) {
-                    long val = getStartTimeToNowLocked(now);
-                    if (which == STATS_CURRENT) {
-                        val -= mLoadedStartTime;
-                    } else if (which == STATS_SINCE_UNPLUGGED) {
-                        val -= mUnpluggedStartTime;
-                    }
-                    return val;
+                    return getStartTimeToNowLocked(now);
                 }
 
                 @Override
                 public int getStarts(int which) {
-                    int val = mStarts;
-                    if (which == STATS_CURRENT) {
-                        val -= mLoadedStarts;
-                    } else if (which == STATS_SINCE_UNPLUGGED) {
-                        val -= mUnpluggedStarts;
-                    }
-
-                    return val;
+                    return mStarts;
                 }
             }
 
@@ -10932,7 +10529,7 @@
         }
         mBluetoothActivity.reset(false);
         mModemActivity.reset(false);
-        mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
+        mNumConnectivityChange = 0;
 
         for (int i=0; i<mUidStats.size(); i++) {
             if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
@@ -12668,7 +12265,7 @@
                 startRecordingHistory(elapsedRealtime, uptime, true);
             }
         } else if (level < 96 &&
-            status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
+                status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
             if (!mRecordingHistory) {
                 mRecordingHistory = true;
                 startRecordingHistory(elapsedRealtime, uptime, true);
@@ -12817,8 +12414,8 @@
             }
         }
         if (!onBattery &&
-            (status == BatteryManager.BATTERY_STATUS_FULL ||
-             status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
+                (status == BatteryManager.BATTERY_STATUS_FULL ||
+                        status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
             // We don't record history while we are plugged in and fully charged
             // (or when battery is not present).  The next time we are
             // unplugged, history will be cleared.
@@ -12855,7 +12452,9 @@
 
     @UnsupportedAppUsage
     public long getAwakeTimeBattery() {
-        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
+        // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
+        // for over a decade, but surely that was a mistake.
+        return getBatteryUptimeLocked();
     }
 
     @UnsupportedAppUsage
@@ -12865,22 +12464,12 @@
 
     @Override
     public long computeUptime(long curTime, int which) {
-        switch (which) {
-            case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
-            case STATS_CURRENT: return (curTime-mUptimeStart);
-            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
-        }
-        return 0;
+        return mUptime + (curTime - mUptimeStart);
     }
 
     @Override
     public long computeRealtime(long curTime, int which) {
-        switch (which) {
-            case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
-            case STATS_CURRENT: return (curTime-mRealtimeStart);
-            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
-        }
-        return 0;
+        return mRealtime + (curTime - mRealtimeStart);
     }
 
     @Override
@@ -14074,7 +13663,7 @@
         mHasBluetoothReporting = in.readInt() != 0;
         mHasModemReporting = in.readInt() != 0;
 
-        mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
+        mNumConnectivityChange = in.readInt();
         mFlashlightOnNesting = 0;
         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
         mCameraOnNesting = 0;
@@ -14383,12 +13972,12 @@
             for (int ip = 0; ip < NP; ip++) {
                 String procName = in.readString();
                 Uid.Proc p = u.getProcessStatsLocked(procName);
-                p.mUserTime = p.mLoadedUserTime = in.readLong();
-                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
-                p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
-                p.mStarts = p.mLoadedStarts = in.readInt();
-                p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
-                p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
+                p.mUserTime = in.readLong();
+                p.mSystemTime = in.readLong();
+                p.mForegroundTime = in.readLong();
+                p.mStarts = in.readInt();
+                p.mNumCrashes = in.readInt();
+                p.mNumAnrs = in.readInt();
                 p.readExcessivePowerFromParcelLocked(in);
             }
 
@@ -14405,7 +13994,7 @@
                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
                 }
                 p.mWakeupAlarms.clear();
-                for (int iwa=0; iwa<NWA; iwa++) {
+                for (int iwa = 0; iwa < NWA; iwa++) {
                     String tag = in.readString();
                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
                     c.readSummaryFromParcelLocked(in);
@@ -14418,9 +14007,9 @@
                 for (int is = 0; is < NS; is++) {
                     String servName = in.readString();
                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
-                    s.mStartTime = s.mLoadedStartTime = in.readLong();
-                    s.mStarts = s.mLoadedStarts = in.readInt();
-                    s.mLaunches = s.mLoadedLaunches = in.readInt();
+                    s.mStartTime = in.readLong();
+                    s.mStarts = in.readInt();
+                    s.mLaunches = in.readInt();
                 }
             }
         }
@@ -15054,9 +14643,8 @@
         mHasModemReporting = in.readInt() != 0;
 
         mNumConnectivityChange = in.readInt();
-        mLoadedNumConnectivityChange = in.readInt();
-        mUnpluggedNumConnectivityChange = in.readInt();
         mAudioOnNesting = 0;
+        // TODO: It's likely a mistake that mAudioOnTimer/mVideoOnTimer don't write/read to parcel!
         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
         mVideoOnNesting = 0;
         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
@@ -15256,8 +14844,6 @@
         out.writeInt(mHasModemReporting ? 1 : 0);
 
         out.writeInt(mNumConnectivityChange);
-        out.writeInt(mLoadedNumConnectivityChange);
-        out.writeInt(mUnpluggedNumConnectivityChange);
         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
         mCameraOnTimer.writeToParcel(out, uSecRealtime);
         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java
index cd69d68..e31c9de 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -27,9 +27,10 @@
      * @param u The recorded stats for the app.
      * @param rawRealtimeUs The raw system realtime in microseconds.
      * @param rawUptimeUs The raw system uptime in microseconds.
-     * @param statsType The type of stats. Can be {@link BatteryStats#STATS_CURRENT},
-     *                  {@link BatteryStats#STATS_SINCE_CHARGED}, or
-     *                  {@link BatteryStats#STATS_SINCE_UNPLUGGED}.
+     * @param statsType The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this can
+     *                  only be {@link BatteryStats#STATS_SINCE_CHARGED}, since
+     *                  {@link BatteryStats#STATS_CURRENT} and
+     *                  {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated.
      */
     public abstract void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
                                       long rawUptimeUs, int statsType);
@@ -40,9 +41,10 @@
      * @param stats The BatteryStats object from which to retrieve data.
      * @param rawRealtimeUs The raw system realtime in microseconds.
      * @param rawUptimeUs The raw system uptime in microseconds.
-     * @param statsType The type of stats. Can be {@link BatteryStats#STATS_CURRENT},
-     *                  {@link BatteryStats#STATS_SINCE_CHARGED}, or
-     *                  {@link BatteryStats#STATS_SINCE_UNPLUGGED}.
+     * @param statsType The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this can
+     *                  only be {@link BatteryStats#STATS_SINCE_CHARGED}, since
+     *                  {@link BatteryStats#STATS_CURRENT} and
+     *                  {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated.
      */
     public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
                                    long rawUptimeUs, int statsType) {
diff --git a/core/java/com/android/internal/util/SyncResultReceiver.java b/core/java/com/android/internal/util/SyncResultReceiver.java
index 9a346ac..60af511 100644
--- a/core/java/com/android/internal/util/SyncResultReceiver.java
+++ b/core/java/com/android/internal/util/SyncResultReceiver.java
@@ -96,6 +96,19 @@
         return mBundle == null ? null : mBundle.getParcelable(EXTRA);
     }
 
+    /**
+     * Gets the optional result from an operation that returns an extra {@code int} (besides the
+     * result code).
+     *
+     * @return value set in the bundle, or {@code defaultValue} when not set.
+     */
+    public int getOptionalExtraIntResult(int defaultValue) throws TimeoutException {
+        waitResult();
+        if (mBundle == null || !mBundle.containsKey(EXTRA)) return defaultValue;
+
+        return mBundle.getInt(EXTRA);
+    }
+
     @Override
     public void send(int resultCode, Bundle resultData) {
         mResult = resultCode;
@@ -136,6 +149,18 @@
         return bundle;
     }
 
+    /**
+     * Creates a bundle for an {@code int} value so it can be retrieved by
+     * {@link #getParcelableResult()} - typically used to return an extra {@code int} (as the 1st
+     * is returned as the result code).
+     */
+    @NonNull
+    public static Bundle bundleFor(int value) {
+        final Bundle bundle = new Bundle();
+        bundle.putInt(EXTRA, value);
+        return bundle;
+    }
+
     /** @hide */
     public static final class TimeoutException extends RemoteException {
         private TimeoutException(String msg) {
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 4773e16..3205b5a 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -20,12 +20,16 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Paint.FontMetricsInt;
+import android.graphics.Path;
 import android.graphics.RectF;
+import android.graphics.Region;
 import android.hardware.input.InputManager;
 import android.hardware.input.InputManager.InputDeviceListener;
+import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Slog;
+import android.view.ISystemGestureExclusionListener;
 import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -34,6 +38,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.WindowInsets;
+import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
 import java.util.ArrayList;
@@ -124,12 +129,16 @@
     private int mActivePointerId;
     private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>();
     private final PointerCoords mTempCoords = new PointerCoords();
-    
+
+    private final Region mSystemGestureExclusion = new Region();
+    private final Path mSystemGestureExclusionPath = new Path();
+    private final Paint mSystemGestureExclusionPaint;
+
     private final VelocityTracker mVelocity;
     private final VelocityTracker mAltVelocity;
 
     private final FasterStringBuilder mText = new FasterStringBuilder();
-    
+
     private boolean mPrintCoords = true;
     
     public PointerLocationView(Context c) {
@@ -168,7 +177,11 @@
         mPathPaint.setARGB(255, 0, 96, 255);
         mPaint.setStyle(Paint.Style.STROKE);
         mPaint.setStrokeWidth(1);
-        
+
+        mSystemGestureExclusionPaint = new Paint();
+        mSystemGestureExclusionPaint.setARGB(25, 255, 0, 0);
+        mSystemGestureExclusionPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
         PointerState ps = new PointerState();
         mPointers.add(ps);
         mActivePointerId = 0;
@@ -236,6 +249,12 @@
 
         final int NP = mPointers.size();
 
+        if (!mSystemGestureExclusion.isEmpty()) {
+            mSystemGestureExclusionPath.reset();
+            mSystemGestureExclusion.getBoundaryPath(mSystemGestureExclusionPath);
+            canvas.drawPath(mSystemGestureExclusionPath, mSystemGestureExclusionPaint);
+        }
+
         // Labels
         if (mActivePointerId >= 0) {
             final PointerState ps = mPointers.get(mActivePointerId);
@@ -719,6 +738,12 @@
         super.onAttachedToWindow();
 
         mIm.registerInputDeviceListener(this, getHandler());
+        try {
+            WindowManagerGlobal.getWindowManagerService().registerSystemGestureExclusionListener(
+                    mSystemGestureExclusionListener, mContext.getDisplayId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
         logInputDevices();
     }
 
@@ -727,6 +752,12 @@
         super.onDetachedFromWindow();
 
         mIm.unregisterInputDeviceListener(this);
+        try {
+            WindowManagerGlobal.getWindowManagerService().unregisterSystemGestureExclusionListener(
+                    mSystemGestureExclusionListener, mContext.getDisplayId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     @Override
@@ -876,4 +907,17 @@
             return oldLength;
         }
     }
+
+    private ISystemGestureExclusionListener mSystemGestureExclusionListener =
+            new ISystemGestureExclusionListener.Stub() {
+        @Override
+        public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion) {
+            Region exclusion = Region.obtain(systemGestureExclusion);
+            getHandler().post(() -> {
+                mSystemGestureExclusion.set(exclusion);
+                exclusion.recycle();
+                invalidate();
+            });
+        }
+    };
 }
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index a698d66..9f4e3e5 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -68,9 +68,8 @@
                 deviceInfo.getKeyboardType(), kcmObj.get(), deviceInfo.hasVibrator(),
                 hasMic, deviceInfo.hasButtonUnderPad()));
 
-    const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
-    for (size_t i = 0; i < ranges.size(); i++) {
-        const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
+    const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
+    for (const InputDeviceInfo::MotionRange& range: ranges) {
         env->CallVoidMethod(inputDeviceObj.get(), gInputDeviceClassInfo.addMotionRange, range.axis,
                 range.source, range.min, range.max, range.flat, range.fuzz, range.resolution);
         if (env->ExceptionCheck()) {
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 7ad9223..f037407 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2305,4 +2305,8 @@
 
     // Open: Settings > Special App Access > Do not disturb control for app
     ZEN_ACCESS_DETAIL = 1692;
+
+    // OPEN: Settings > Face > Remove face
+    // OS: Q
+    DIALOG_FACE_REMOVE = 1693;
 }
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index c08d7ca..4ef26dd5 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -66,6 +66,10 @@
     optional bool can_show_light = 8;
     optional string group_key = 9 [ (.android.privacy).dest = DEST_EXPLICIT ];
     optional sint32 importance = 10;
+    // The package the notification was posted for.
+    optional string package = 11;
+    // The package that posted the notification. It might not be the same as package.
+    optional string delegate_package = 12;
 }
 
 message ListenersDisablingEffectsProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c7417bf..5427147 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -819,8 +819,7 @@
         android:permissionGroup="android.permission-group.UNDEFINED"
         android:label="@string/permlab_sdcardRead"
         android:description="@string/permdesc_sdcardRead"
-        android:protectionLevel="dangerous"
-        android:permissionFlags="removed" />
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write to external storage.
          <p class="note"><strong>Note:</strong> If <em>both</em> your <a
@@ -841,8 +840,7 @@
         android:permissionGroup="android.permission-group.UNDEFINED"
         android:label="@string/permlab_sdcardWrite"
         android:description="@string/permdesc_sdcardWrite"
-        android:protectionLevel="dangerous"
-        android:permissionFlags="removed" />
+        android:protectionLevel="dangerous" />
 
     <!-- Runtime permission controlling access to the user's shared aural media
          collection. -->
@@ -3929,6 +3927,10 @@
     <permission android:name="android.permission.MANAGE_ROLLBACKS"
         android:protectionLevel="signature|verifier" />
 
+    <!-- @SystemApi @TestApi @hide Allows testing apk level rollbacks. -->
+    <permission android:name="android.permission.TEST_MANAGE_ROLLBACKS"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi @hide Allows an application to mark other applications as harmful -->
     <permission android:name="android.permission.SET_HARMFUL_APP_WARNINGS"
         android:protectionLevel="signature|verifier" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 743496f..9d48fe3 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8108,7 +8108,7 @@
 
     <!-- Use <code>autofill-service</code> as the root tag of the XML resource that describes a
          {@link android.service.autofill.AutofillService}, which is referenced from its
-         {@link android.service.autofill#SERVICE_META_DATA} meta-data entry.
+         {@link android.service.autofill.AutofillService#SERVICE_META_DATA} meta-data entry.
     -->
     <declare-styleable name="AutofillService">
         <!-- Fully qualified class name of an activity that allows the user to modify
@@ -8134,6 +8134,23 @@
     </declare-styleable>
 
     <!-- =============================== -->
+    <!-- Content Capture attributes -->
+    <!-- =============================== -->
+    <eat-comment />
+
+    <!-- Use <code>content-capture-service</code> as the root tag of the XML resource that describes
+         a {@link android.service.contentcapture.ContentCaptureService}, which is referenced from
+         its {@link android.service.contentcapture.ContentCaptureService#SERVICE_META_DATA}
+         meta-data entry.
+         @hide @SystemApi
+    -->
+    <declare-styleable name="ContentCaptureService">
+        <!-- Fully qualified class name of an activity that allows the user to modify
+             the settings for this service. -->
+        <attr name="settingsActivity" />
+    </declare-styleable>
+
+    <!-- =============================== -->
     <!-- Contacts meta-data attributes -->
     <!-- =============================== -->
     <eat-comment />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 7322a54..6fb4744 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -656,6 +656,7 @@
                  Settings.Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
                  Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED,
                  Settings.Secure.ODI_CAPTIONS_ENABLED,
+                 Settings.Secure.ODI_CAPTIONS_OPTED_OUT,
                  Settings.Secure.PACKAGE_VERIFIER_STATE,
                  Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
                  Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 66146c9..4266ba9f 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -24,10 +24,16 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 
+import android.app.Instrumentation;
+import android.content.Context;
 import android.graphics.Point;
 import android.platform.test.annotations.Presubmit;
 import android.view.SurfaceControl.Transaction;
+import android.view.WindowManager.BadTokenException;
+import android.view.WindowManager.LayoutParams;
+import android.widget.TextView;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -47,7 +53,6 @@
     private SurfaceSession mSession = new SurfaceSession();
     private SurfaceControl mLeash;
     @Mock Transaction mMockTransaction;
-    @Mock InsetsController mMockController;
 
     @Before
     public void setup() {
@@ -55,8 +60,21 @@
         mLeash = new SurfaceControl.Builder(mSession)
                 .setName("testSurface")
                 .build();
-        mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, new InsetsState(),
-                () -> mMockTransaction, mMockController);
+        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        instrumentation.runOnMainSync(() -> {
+            final Context context = instrumentation.getTargetContext();
+            // cannot mock ViewRootImpl since it's final.
+            final ViewRootImpl viewRootImpl = new ViewRootImpl(context, context.getDisplay());
+            try {
+                viewRootImpl.setView(new TextView(context), new LayoutParams(), null);
+            } catch (BadTokenException e) {
+                // activity isn't running, lets ignore BadTokenException.
+            }
+            mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, new InsetsState(),
+                    () -> mMockTransaction, new InsetsController(viewRootImpl));
+        });
+        instrumentation.waitForIdleSync();
+
         mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash, new Point()));
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java
index 37f818a..ade3a99 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java
@@ -44,8 +44,6 @@
         counter.stepAtomic();
         counter.stepAtomic();
         assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(0, counter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // timeBase on (i.e. unplugged)
         timeBase.setRunning(true, 2, 2);
@@ -54,8 +52,6 @@
         counter.stepAtomic();
         counter.stepAtomic();
         assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // timeBase off (i.e. plugged in)
         timeBase.setRunning(false, 3, 3);
@@ -63,16 +59,12 @@
         counter.stepAtomic();
         counter.stepAtomic();
         assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // timeBase on (i.e. unplugged)
         timeBase.setRunning(true, 4, 4);
         counter.stepAtomic();
         counter.stepAtomic();
         assertEquals(6, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(6, counter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(2, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
     }
 
 
@@ -88,8 +80,6 @@
         timeBase.setRunning(true, 1, 1);
         origCounter.stepAtomic(); origCounter.stepAtomic(); origCounter.stepAtomic(); // three times
         assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // Test summary parcelling (from origCounter)
         final Parcel summaryParcel = Parcel.obtain();
@@ -102,22 +92,16 @@
         // timeBase still on (i.e. unplugged)
         summaryCounter.stepAtomic(); // once
         assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // timeBase off (i.e. plugged in)
         timeBase.setRunning(false, 3, 3);
         summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice
         assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // timeBase on (i.e. unplugged)
         timeBase.setRunning(true, 4, 4);
         summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice
         assertEquals(6, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(3, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(2, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
 
         // Test full parcelling (from summaryCounter)
@@ -130,21 +114,15 @@
         // timeBase still on (i.e. unplugged)
         fullParcelCounter.stepAtomic(); // once
         assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // timeBase off (i.e. plugged in)
         timeBase.setRunning(false, 5, 5);
         fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice
         assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // timeBase on (i.e. unplugged)
         timeBase.setRunning(true, 6, 6);
         fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice
         assertEquals(9, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(6, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
-        assertEquals(2, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
index a42286f..78fa3fb 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
@@ -100,8 +100,70 @@
         assertEquals(30802, timer.getTotalDurationMsLocked(220302));
     }
 
+    /**
+     * Tests that reset(boolean detachIfReset) clears the correct times if detachIfReset is false.
+     */
     @SmallTest
     public void testReset() throws Exception {
+        final MockClocks clocks = new MockClocks();
+
+        final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
+        timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
+
+        final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks,
+                null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase);
+
+        timeBase.setRunning(true, /* uptimeUs */ 0, /* realtimeUs */ 100_000);
+        timer.startRunningLocked(700);
+        timer.stopRunningLocked(3_100);
+        assertFalse(timer.isRunningLocked());
+        assertEquals(0, timer.getCurrentDurationMsLocked(6_300));
+        assertEquals(2_400, timer.getMaxDurationMsLocked(6_301));
+        assertEquals(2_400, timer.getTotalDurationMsLocked(6_302));
+
+        timer.reset(false);
+        assertEquals(0, timer.getCurrentDurationMsLocked(12_000));
+        assertEquals(0, timer.getMaxDurationMsLocked(12_001));
+        assertEquals(0, timer.getTotalDurationMsLocked(12_002));
+
+        assertEquals(true, timeBase.hasObserver(timer));
+
+        timer.startRunningLocked(24_100);
+        clocks.uptime = clocks.realtime = 24_200;
+        timer.reset(false);
+        assertEquals(34_300, timer.getCurrentDurationMsLocked(58_500));
+        assertEquals(34_301, timer.getMaxDurationMsLocked(58_501));
+        assertEquals(34_302, timer.getTotalDurationMsLocked(58_502));
+    }
+
+    /**
+     * Tests that reset(boolean detachIfReset) clears the correct times if detachIfReset is true.
+     */
+    @SmallTest
+    public void testResetAndDetach() throws Exception {
+        final MockClocks clocks = new MockClocks();
+
+        final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
+        timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
+
+        final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks,
+                null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase);
+
+        timeBase.setRunning(true, /* uptimeUs */ 0, /* realtimeUs */ 100_000);
+        timer.startRunningLocked(700);
+        timer.stopRunningLocked(3_100);
+        assertFalse(timer.isRunningLocked());
+        assertEquals(0, timer.getCurrentDurationMsLocked(6_300));
+        assertEquals(2_400, timer.getMaxDurationMsLocked(6_301));
+        assertEquals(2_400, timer.getTotalDurationMsLocked(6_302));
+
+        timer.reset(true);
+        clocks.uptime = clocks.realtime = 7_000;
+        assertEquals(0, timer.getCurrentDurationMsLocked(8_000));
+        assertEquals(0, timer.getMaxDurationMsLocked(8_001));
+        assertEquals(0, timer.getTotalDurationMsLocked(8_002));
+
+        assertEquals(false, timeBase.hasObserver(timer));
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
index 0771829..4b37dd2 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
@@ -325,7 +325,7 @@
 
         // Get the total acquisition time
         long totalTime = u.getWifiMulticastTime(currentTimeMs*1000,
-                BatteryStats.STATS_SINCE_UNPLUGGED);
+                BatteryStats.STATS_SINCE_CHARGED);
         assertEquals("Miscalculations of Multicast wakelock acquisition time",
                 (releaseTimeMs - acquireTimeMs) * 1000, totalTime);
     }
@@ -347,7 +347,7 @@
 
         // Get the total acquisition time
         long totalTime =  u.getWifiMulticastTime(currentTimeMs*1000,
-                BatteryStats.STATS_SINCE_UNPLUGGED);
+                BatteryStats.STATS_SINCE_CHARGED);
         assertEquals("Miscalculations of Multicast wakelock acquisition time",
                 (currentTimeMs - acquireTimeMs) * 1000, totalTime);
     }
@@ -377,7 +377,7 @@
 
         // Get the total acquisition time
         long totalTime =  u.getWifiMulticastTime(currentTimeMs*1000,
-                BatteryStats.STATS_SINCE_UNPLUGGED);
+                BatteryStats.STATS_SINCE_CHARGED);
         assertEquals("Miscalculations of Multicast wakelock acquisition time",
                 (releaseTimeMs_2 - acquireTimeMs_1) * 1000, totalTime);
     }
@@ -407,7 +407,7 @@
 
         // Get the total acquisition time
         long totalTime =  u.getWifiMulticastTime(currentTimeMs*1000,
-                BatteryStats.STATS_SINCE_UNPLUGGED);
+                BatteryStats.STATS_SINCE_CHARGED);
         assertEquals("Miscalculations of Multicast wakelock acquisition time",
                 ((releaseTimeMs_1 - acquireTimeMs_1) + (releaseTimeMs_2 - acquireTimeMs_2))
                 * 1000, totalTime);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 3e33273..8f5dfc5 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.os;
 
-import static android.os.BatteryStats.STATS_CURRENT;
 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
 import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
 
@@ -388,7 +387,7 @@
         bi.noteWakupAlarmLocked("com.foo.bar", UID, null, "tag");
 
         Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
-        assertEquals(1, pkg.getWakeupAlarmStats().get("tag").getCountLocked(STATS_CURRENT));
+        assertEquals(1, pkg.getWakeupAlarmStats().get("tag").getCountLocked(STATS_SINCE_CHARGED));
         assertEquals(1, pkg.getWakeupAlarmStats().size());
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
index b9995c4..df549c5 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
@@ -44,15 +44,6 @@
             mLaunchedSince = 6064;
             mLaunched = true;
             mLaunches = 8085;
-            mLoadedStartTime = 9096;
-            mLoadedStarts = 10017;
-            mLoadedLaunches = 11118;
-            mLastStartTime = 12219;
-            mLastStarts = 13310;
-            mLastLaunches = 14411;
-            mUnpluggedStartTime = 15512;
-            mUnpluggedStarts = 16613;
-            mUnpluggedLaunches = 17714;
         }
 
         long getStartTime() {
@@ -94,42 +85,6 @@
         int getLaunches() {
             return mLaunches;
         }
-
-        long getLoadedStartTime() {
-            return mLoadedStartTime;
-        }
-
-        int getLoadedStarts() {
-            return mLoadedStarts;
-        }
-
-        int getLoadedLaunches() {
-            return mLoadedLaunches;
-        }
-
-        long getLastStartTime() {
-            return mLastStartTime;
-        }
-
-        int getLastStarts() {
-            return mLastStarts;
-        }
-
-        int getLastLaunches() {
-            return mLastLaunches;
-        }
-
-        long getUnpluggedStartTime() {
-            return mUnpluggedStartTime;
-        }
-
-        int getUnpluggedStarts() {
-            return mUnpluggedStarts;
-        }
-
-        int getUnpluggedLaunches() {
-            return mUnpluggedLaunches;
-        }
     }
 
     /**
@@ -147,29 +102,6 @@
     }
 
     /**
-     * Test OnTimeStarted
-     */
-    @SmallTest
-    public void testOnTimeStarted() throws Exception  {
-        MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
-        TestServ serv = new TestServ(bsi);
-
-        serv.populate();
-        serv.setRunning(true);
-        serv.onTimeStarted(111111, 20000, 222222);
-        Assert.assertEquals(18989, serv.getUnpluggedStartTime());
-        Assert.assertEquals(4042, serv.getUnpluggedStarts());
-        Assert.assertEquals(8085, serv.getUnpluggedLaunches());
-
-        serv.populate();
-        serv.setRunning(false);
-        serv.onTimeStarted(111111, 20000, 222222);
-        Assert.assertEquals(1010, serv.getUnpluggedStartTime());
-        Assert.assertEquals(4042, serv.getUnpluggedStarts());
-        Assert.assertEquals(8085, serv.getUnpluggedLaunches());
-    }
-
-    /**
      * Test parceling and unparceling.
      */
     @SmallTest
@@ -185,7 +117,7 @@
 
         TestServ serv = new TestServ(bsi);
         serv.readFromParcelLocked(parcel);
-   
+
         Assert.assertEquals(1010, serv.getStartTime());
         Assert.assertEquals(2021, serv.getRunningSince());
         Assert.assertTrue(serv.getRunning());
@@ -194,15 +126,8 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(0, serv.getLastStartTime());
-        Assert.assertEquals(0, serv.getLastStarts());
-        Assert.assertEquals(0, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+
+        parcel.recycle();
     }
 
     /**
@@ -267,15 +192,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -303,15 +219,6 @@
         Assert.assertEquals(777777L, serv.getLaunchedSince()); // <-- changed
         Assert.assertTrue(serv.getLaunched()); // <-- changed
         Assert.assertEquals(8086, serv.getLaunches()); // <-- changed
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -341,15 +248,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertFalse(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -375,19 +273,10 @@
         Assert.assertEquals(2021, serv.getRunningSince());
         Assert.assertTrue(serv.getRunning());
         Assert.assertEquals(4042, serv.getStarts());
-        Assert.assertEquals(777777L-6064+5053, serv.getLaunchedTime()); // <-- changed 
+        Assert.assertEquals(777777L-6064+5053, serv.getLaunchedTime()); // <-- changed
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertFalse(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -416,16 +305,7 @@
         Assert.assertEquals(5053, serv.getLaunchedTime());
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertFalse(serv.getLaunched());
-        Assert.assertEquals(8085-1, serv.getLaunches()); // <-- changed 
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+        Assert.assertEquals(8085-1, serv.getLaunches()); // <-- changed
     }
 
     /**
@@ -455,15 +335,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -492,15 +363,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -530,15 +392,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -568,15 +421,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -600,8 +444,6 @@
         serv.populate();
 
         Assert.assertEquals(8085, serv.getLaunches(BatteryStats.STATS_SINCE_CHARGED));
-        Assert.assertEquals(8085-11118, serv.getLaunches(BatteryStats.STATS_CURRENT));
-        Assert.assertEquals(8085-17714, serv.getLaunches(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // No change to fields
         Assert.assertEquals(1010, serv.getStartTime());
@@ -612,15 +454,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -637,10 +470,6 @@
 
         Assert.assertEquals(startTimeToNow,
                 serv.getStartTime(20000, BatteryStats.STATS_SINCE_CHARGED));
-        Assert.assertEquals(startTimeToNow-9096,
-                serv.getStartTime(20000, BatteryStats.STATS_CURRENT));
-        Assert.assertEquals(startTimeToNow-15512,
-                serv.getStartTime(20000, BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // No change to fields
         Assert.assertEquals(1010, serv.getStartTime());
@@ -651,15 +480,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
     /**
@@ -676,10 +496,6 @@
 
         Assert.assertEquals(startTimeToNow,
                 serv.getStartTime(20000, BatteryStats.STATS_SINCE_CHARGED));
-        Assert.assertEquals(startTimeToNow-9096,
-                serv.getStartTime(20000, BatteryStats.STATS_CURRENT));
-        Assert.assertEquals(startTimeToNow-15512,
-                serv.getStartTime(20000, BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // No change to fields
         Assert.assertEquals(1010, serv.getStartTime());
@@ -690,15 +506,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
 
 
@@ -712,8 +519,6 @@
         serv.populate();
 
         Assert.assertEquals(4042, serv.getStarts(BatteryStats.STATS_SINCE_CHARGED));
-        Assert.assertEquals(4042-10017, serv.getStarts(BatteryStats.STATS_CURRENT));
-        Assert.assertEquals(4042-16613, serv.getStarts(BatteryStats.STATS_SINCE_UNPLUGGED));
 
         // No change to fields
         Assert.assertEquals(1010, serv.getStartTime());
@@ -724,15 +529,6 @@
         Assert.assertEquals(6064, serv.getLaunchedSince());
         Assert.assertTrue(serv.getLaunched());
         Assert.assertEquals(8085, serv.getLaunches());
-        Assert.assertEquals(9096, serv.getLoadedStartTime());
-        Assert.assertEquals(10017, serv.getLoadedStarts());
-        Assert.assertEquals(11118, serv.getLoadedLaunches());
-        Assert.assertEquals(12219, serv.getLastStartTime());
-        Assert.assertEquals(13310, serv.getLastStarts());
-        Assert.assertEquals(14411, serv.getLastLaunches());
-        Assert.assertEquals(15512, serv.getUnpluggedStartTime());
-        Assert.assertEquals(16613, serv.getUnpluggedStarts());
-        Assert.assertEquals(17714, serv.getUnpluggedLaunches());
     }
     
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
index bce8b40..e5441c0 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
@@ -282,12 +282,6 @@
 
         Assert.assertEquals(100+300+666-400,
                 tb.computeUptime(666, BatteryStats.STATS_SINCE_CHARGED));
-        Assert.assertEquals(300+666-400,
-                tb.computeUptime(666, BatteryStats.STATS_CURRENT));
-        Assert.assertEquals(300+666-400-50,
-                tb.computeUptime(666, BatteryStats.STATS_SINCE_UNPLUGGED));
-
-        Assert.assertEquals(0, tb.computeUptime(666, 6000));
     }
 
     /**
@@ -301,12 +295,6 @@
 
         Assert.assertEquals(200+500+6666-600,
                 tb.computeRealtime(6666, BatteryStats.STATS_SINCE_CHARGED));
-        Assert.assertEquals(500+6666-600,
-                tb.computeRealtime(6666, BatteryStats.STATS_CURRENT));
-        Assert.assertEquals(500+6666-600-60,
-                tb.computeRealtime(6666, BatteryStats.STATS_SINCE_UNPLUGGED));
-
-        Assert.assertEquals(0, tb.computeUptime(666, 6000));
     }
 
     /**
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
index 87dc2f3..40e3a5f 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
@@ -66,30 +66,6 @@
             mCount = val;
         }
 
-        public int getLoadedCount() {
-            return mLoadedCount;
-        }
-
-        public void setLoadedCount(int val) {
-            mLoadedCount = val;
-        }
-
-        public int getLastCount() {
-            return mLastCount;
-        }
-
-        public void setLastCount(int val) {
-            mLastCount = val;
-        }
-
-        public int getUnpluggedCount() {
-            return mUnpluggedCount;
-        }
-
-        public void setUnpluggedCount(int val) {
-            mUnpluggedCount = val;
-        }
-
         public long getTotalTime() {
             return mTotalTime;
         }
@@ -98,30 +74,6 @@
             mTotalTime = val;
         }
 
-        public long getLoadedTime() {
-            return mLoadedTime;
-        }
-
-        public void setLoadedTime(long val) {
-            mLoadedTime = val;
-        }
-
-        public long getLastTime() {
-            return mLastTime;
-        }
-
-        public void setLastTime(long val) {
-            mLastTime = val;
-        }
-
-        public long getUnpluggedTime() {
-            return mUnpluggedTime;
-        }
-
-        public void setUnpluggedTime(long val) {
-            mUnpluggedTime = val;
-        }
-
         public long getTimeBeforeMark() {
             return mTimeBeforeMark;
         }
@@ -143,16 +95,12 @@
         TestTimer timer = new TestTimer(clocks, 0, timeBase);
         timer.nextComputeCurrentCount = 3000;
 
-        // Test that starting the timer counts the unplugged time and counters
+        // Test that stopping the timer updates mTotalTime and mCount
         timer.nextComputeRunTime = 4;
         timer.onTimeStarted(10, 20, 50);
-        Assert.assertEquals(50, timer.lastComputeRunTimeRealtime);
-        Assert.assertEquals(4, timer.getUnpluggedTime());
-        Assert.assertEquals(3000, timer.getUnpluggedCount());
-
-        // Test that stopping the timer updates mTotalTime and mCount
         timer.nextComputeRunTime = 17;
         timer.onTimeStopped(100, 130, 170);
+        Assert.assertEquals(170, timer.lastComputeRunTimeRealtime);
         Assert.assertEquals(17, timer.getTotalTime());
         Assert.assertEquals(3000, timer.getCount());
     }
@@ -168,13 +116,7 @@
         // Test write then read
         TestTimer timer1 = new TestTimer(clocks, 0, timeBase);
         timer1.setCount(1);
-        timer1.setLoadedCount(3);
-        timer1.setLastCount(4);
-        timer1.setUnpluggedCount(5);
         timer1.setTotalTime(9223372036854775807L);
-        timer1.setLoadedTime(9223372036854775806L);
-        timer1.setLastTime(9223372036854775805L);
-        timer1.setUnpluggedTime(9223372036854775804L);
         timer1.setTimeBeforeMark(9223372036854775803L);
         timer1.nextComputeRunTime = 201;
         timer1.nextComputeCurrentCount = 2;
@@ -187,13 +129,7 @@
 
         TestTimer timer2 = new TestTimer(clocks, 0, timeBase, parcel);
         Assert.assertEquals(2, timer2.getCount()); // from computeTotalCountLocked()
-        Assert.assertEquals(3, timer2.getLoadedCount());
-        Assert.assertEquals(0, timer2.getLastCount()); // NOT saved
-        Assert.assertEquals(5, timer2.getUnpluggedCount());
         Assert.assertEquals(201, timer2.getTotalTime()); // from computeRunTimeLocked()
-        Assert.assertEquals(9223372036854775806L, timer2.getLoadedTime());
-        Assert.assertEquals(0, timer2.getLastTime()); // NOT saved
-        Assert.assertEquals(9223372036854775804L, timer2.getUnpluggedTime());
         Assert.assertEquals(9223372036854775803L, timer2.getTimeBeforeMark());
 
         parcel.recycle();
@@ -224,25 +160,13 @@
 
         TestTimer timer = new TestTimer(clocks, 0, timeBase);
         timer.setCount(1);
-        timer.setLoadedCount(2);
-        timer.setLastCount(3);
-        timer.setUnpluggedCount(4);
         timer.setTotalTime(9223372036854775807L);
-        timer.setLoadedTime(9223372036854775806L);
-        timer.setLastTime(9223372036854775805L);
-        timer.setUnpluggedTime(9223372036854775804L);
         timer.setTimeBeforeMark(9223372036854775803L);
 
         timer.reset(false);
 
         Assert.assertEquals(0, timer.getCount());
-        Assert.assertEquals(0, timer.getLoadedCount());
-        Assert.assertEquals(0, timer.getLastCount());
-        Assert.assertEquals(4, timer.getUnpluggedCount());
         Assert.assertEquals(0, timer.getTotalTime());
-        Assert.assertEquals(0, timer.getLoadedTime());
-        Assert.assertEquals(0, timer.getLastTime());
-        Assert.assertEquals(9223372036854775804L, timer.getUnpluggedTime());
         Assert.assertEquals(0, timer.getTimeBeforeMark());
 
         // reset(false) shouldn't remove it from the list
@@ -259,25 +183,13 @@
 
         TestTimer timer = new TestTimer(clocks, 0, timeBase);
         timer.setCount(1);
-        timer.setLoadedCount(2);
-        timer.setLastCount(3);
-        timer.setUnpluggedCount(4);
         timer.setTotalTime(9223372036854775807L);
-        timer.setLoadedTime(9223372036854775806L);
-        timer.setLastTime(9223372036854775805L);
-        timer.setUnpluggedTime(9223372036854775804L);
         timer.setTimeBeforeMark(9223372036854775803L);
 
         timer.reset(true);
 
         Assert.assertEquals(0, timer.getCount());
-        Assert.assertEquals(0, timer.getLoadedCount());
-        Assert.assertEquals(0, timer.getLastCount());
-        Assert.assertEquals(4, timer.getUnpluggedCount());
         Assert.assertEquals(0, timer.getTotalTime());
-        Assert.assertEquals(0, timer.getLoadedTime());
-        Assert.assertEquals(0, timer.getLastTime());
-        Assert.assertEquals(9223372036854775804L, timer.getUnpluggedTime());
         Assert.assertEquals(0, timer.getTimeBeforeMark());
 
         // reset(true) should remove it from the list
@@ -299,13 +211,7 @@
 
         TestTimer timer1 = new TestTimer(clocks, 0, timeBase);
         timer1.setCount(1);
-        timer1.setLoadedCount(2);
-        timer1.setLastCount(3);
-        timer1.setUnpluggedCount(4);
         timer1.setTotalTime(9223372036854775807L);
-        timer1.setLoadedTime(9223372036854775806L);
-        timer1.setLastTime(9223372036854775805L);
-        timer1.setUnpluggedTime(9223372036854775804L);
         timer1.setTimeBeforeMark(9223372036854775803L);
 
         Parcel parcel = Parcel.obtain();
@@ -318,13 +224,7 @@
 
         // Make sure that all the values get touched
         timer2.setCount(666);
-        timer2.setLoadedCount(666);
-        timer2.setLastCount(666);
-        timer2.setUnpluggedCount(666);
         timer2.setTotalTime(666);
-        timer2.setLoadedTime(666);
-        timer2.setLastTime(666);
-        timer2.setUnpluggedTime(666);
         timer2.setTimeBeforeMark(666);
 
         parcel.setDataPosition(0);
@@ -333,13 +233,7 @@
         timer2.readSummaryFromParcelLocked(parcel);
 
         Assert.assertEquals(1, timer2.getCount());
-        Assert.assertEquals(1, timer2.getLoadedCount());
-        Assert.assertEquals(0, timer2.getLastCount());
-        Assert.assertEquals(1, timer2.getUnpluggedCount());
         Assert.assertEquals(9223372036854775800L, timer2.getTotalTime());
-        Assert.assertEquals(9223372036854775800L, timer2.getLoadedTime());
-        Assert.assertEquals(0, timer2.getLastTime());
-        Assert.assertEquals(9223372036854775800L, timer2.getUnpluggedTime());
         Assert.assertEquals(9223372036854775800L, timer2.getTimeBeforeMark());
 
         parcel.recycle();
@@ -359,32 +253,15 @@
 
         TestTimer timer = new TestTimer(clocks, 0, timeBase);
         timer.setCount(1);
-        timer.setLoadedCount(2);
-        timer.setLastCount(3);
-        timer.setUnpluggedCount(4);
         timer.setTotalTime(100);
-        timer.setLoadedTime(200);
-        timer.setLastTime(300);
-        timer.setUnpluggedTime(400);
         timer.setTimeBeforeMark(500);
 
         timer.nextComputeRunTime = 10000;
 
-        // Timer.getTotalTimeLocked(STATS_SINCE_CHARGED)
         timer.lastComputeRunTimeRealtime = -1;
         Assert.assertEquals(10000,
                 timer.getTotalTimeLocked(66, BatteryStats.STATS_SINCE_CHARGED));
         Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
-
-        // Timer.getTotalTimeLocked(STATS_CURRENT)
-        timer.lastComputeRunTimeRealtime = -1;
-        Assert.assertEquals(9800, timer.getTotalTimeLocked(66, BatteryStats.STATS_CURRENT));
-        Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
-
-        // Timer.getTotalTimeLocked(STATS_SINCE_UNPLUGGED)
-        timer.lastComputeRunTimeRealtime = -1;
-        Assert.assertEquals(9600, timer.getTotalTimeLocked(66, BatteryStats.STATS_SINCE_UNPLUGGED));
-        Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
     }
 
     /**
@@ -401,26 +278,11 @@
 
         TestTimer timer = new TestTimer(clocks, 0, timeBase);
         timer.setCount(1);
-        timer.setLoadedCount(2);
-        timer.setLastCount(3);
-        timer.setUnpluggedCount(4);
         timer.setTotalTime(100);
-        timer.setLoadedTime(200);
-        timer.setLastTime(300);
-        timer.setUnpluggedTime(400);
         timer.setTimeBeforeMark(500);
 
-        // Timer.getCountLocked(STATS_SINCE_CHARGED)
         timer.nextComputeCurrentCount = 10000;
         Assert.assertEquals(10000, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
-
-        // Timer.getCountLocked(STATS_CURRENT)
-        timer.nextComputeCurrentCount = 10000;
-        Assert.assertEquals(9998, timer.getCountLocked(BatteryStats.STATS_CURRENT));
-
-        // Timer.getCountLocked(STATS_SINCE_UNPLUGGED)
-        timer.nextComputeCurrentCount = 10000;
-        Assert.assertEquals(9996, timer.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
     }
 
     /**
@@ -437,13 +299,7 @@
 
         TestTimer timer = new TestTimer(clocks, 0, timeBase);
         timer.setCount(1);
-        timer.setLoadedCount(2);
-        timer.setLastCount(3);
-        timer.setUnpluggedCount(4);
         timer.setTotalTime(100);
-        timer.setLoadedTime(200);
-        timer.setLastTime(300);
-        timer.setUnpluggedTime(400);
         timer.setTimeBeforeMark(500);
 
         timer.nextComputeRunTime = 10000;
@@ -460,30 +316,16 @@
 
         TestTimer timer = new TestTimer(clocks, 0, timeBase);
         timer.setTotalTime(100);
-        timer.setLoadedTime(200);
-        timer.setLastTime(300);
-        timer.setUnpluggedTime(400);
         timer.setTimeBeforeMark(500);
         timer.setCount(1);
-        timer.setLoadedCount(2);
-        timer.setLastCount(3);
-        timer.setUnpluggedCount(4);
         timer.setTotalTime(9223372036854775807L);
-        timer.setLoadedTime(9223372036854775806L);
-        timer.setLastTime(9223372036854775805L);
-        timer.setUnpluggedTime(9223372036854775804L);
         timer.setTimeBeforeMark(9223372036854775803L);
 
         StringBuilder sb = new StringBuilder();
         StringBuilderPrinter pw = new StringBuilderPrinter(sb);
 
         timer.logState(pw, "  ");
-
-        Assert.assertEquals(
-                      "  mCount=1 mLoadedCount=2 mLastCount=3 mUnpluggedCount=4\n"
-                    + "  mTotalTime=9223372036854775807 mLoadedTime=9223372036854775806\n"
-                    + "  mLastTime=9223372036854775805 mUnpluggedTime=9223372036854775804\n",
-                sb.toString());
+        Assert.assertEquals("  mCount=1\n  mTotalTime=9223372036854775807\n", sb.toString());
     }
 }
 
diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
index 0516bb7..ee5d2d6 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
@@ -16,14 +16,12 @@
 
 package com.android.internal.os;
 
-import static android.os.BatteryStats.STATS_CURRENT;
 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
-import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED;
 
 import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounterArray;
 import static com.android.internal.os.BatteryStatsImpl.TimeBase;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertArrayEquals;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
@@ -41,8 +39,6 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-import java.util.Arrays;
-
 /**
  * Test class for {@link BatteryStatsImpl.LongSamplingCounterArray}.
  *
@@ -57,14 +53,15 @@
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class com.android.internal.os.LongSamplingCounterArrayTest -w \
  *     com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
+ *
+ * or just do
+ * atest frameworks/base/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class LongSamplingCounterArrayTest {
 
     private static final long[] COUNTS = {1111, 2222, 3333, 4444};
-    private static final long[] LOADED_COUNTS = {5555, 6666, 7777, 8888};
-    private static final long[] UNPLUGGED_COUNTS = {44444, 55555, 66666, 77777};
     private static final long[] ZEROES = {0, 0, 0, 0};
 
     @Mock private TimeBase mTimeBase;
@@ -80,75 +77,54 @@
     @Test
     public void testReadWriteParcel() {
         final Parcel parcel = Parcel.obtain();
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
         LongSamplingCounterArray.writeToParcel(parcel, mCounterArray);
         parcel.setDataPosition(0);
 
         // Now clear counterArray and verify values are read from parcel correctly.
-        updateCounts(null, null, null);
+        updateCounts(null);
         mCounterArray = LongSamplingCounterArray.readFromParcel(parcel, mTimeBase);
-        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
-                "Unexpected unpluggedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mCounts);
         parcel.recycle();
     }
 
     @Test
     public void testReadWriteSummaryParcel() {
         final Parcel parcel = Parcel.obtain();
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
         LongSamplingCounterArray.writeSummaryToParcelLocked(parcel, mCounterArray);
         parcel.setDataPosition(0);
 
         // Now clear counterArray and verify values are read from parcel correctly.
-        updateCounts(null, null, null);
+        updateCounts(null);
         mCounterArray = LongSamplingCounterArray.readSummaryFromParcelLocked(parcel, mTimeBase);
-        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mCounts);
         parcel.recycle();
     }
 
     @Test
     public void testOnTimeStarted() {
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
         mCounterArray.onTimeStarted(0, 0, 0);
-        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts,
-                "Unexpected unpluggedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mCounts);
     }
 
     @Test
     public void testOnTimeStopped() {
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
         mCounterArray.onTimeStopped(0, 0, 0);
-        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
-                "Unexpected unpluggedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mCounts);
     }
 
     @Test
     public void testGetCountsLocked() {
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
 
         when(mTimeBase.isRunning()).thenReturn(false);
-        assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED),
-                "Unexpected values");
-        assertArrayEquals(subtract(COUNTS, LOADED_COUNTS),
-                mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values");
-        assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS),
-                mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values");
+        assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED));
 
         when(mTimeBase.isRunning()).thenReturn(true);
-        assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED),
-                "Unexpected values");
-        assertArrayEquals(subtract(COUNTS, LOADED_COUNTS),
-                mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values");
-        assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS),
-                mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values");
+        assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED));
     }
 
     private long[] subtract(long[] val, long[] toSubtract) {
@@ -163,64 +139,45 @@
 
     @Test
     public void testAddCountLocked() {
-        updateCounts(null, null, null);
+        updateCounts(null);
         final long[] deltas = {123, 234, 345, 456};
         when(mTimeBase.isRunning()).thenReturn(true);
         mCounterArray.addCountLocked(deltas);
-        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        assertArrayEquals(deltas, mCounterArray.mCounts);
 
-        updateCounts(null, null, null);
+        updateCounts(null);
         mCounterArray.addCountLocked(deltas, false);
-        assertArrayEquals(null, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        assertArrayEquals(null, mCounterArray.mCounts);
         mCounterArray.addCountLocked(deltas, true);
-        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        assertArrayEquals(deltas, mCounterArray.mCounts);
 
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
         final long[] newCounts = new long[deltas.length];
         for (int i = 0; i < deltas.length; ++i) {
             newCounts[i] = COUNTS[i] + deltas[i];
         }
         mCounterArray.addCountLocked(deltas);
-        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
-                "Unexpected unpluggedCounts");
+        assertArrayEquals(newCounts, mCounterArray.mCounts);
 
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
         mCounterArray.addCountLocked(deltas, false);
-        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
-                "Unexpected unpluggedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mCounts);
         mCounterArray.addCountLocked(deltas, true);
-        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
-                "Unexpected unpluggedCounts");
+        assertArrayEquals(newCounts, mCounterArray.mCounts);
     }
 
     @Test
     public void testReset() {
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
         // Test with detachIfReset=false
         mCounterArray.reset(false /* detachIfReset */);
-        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mCounts);
         verifyZeroInteractions(mTimeBase);
 
-        initializeCounterArrayWithDefaultValues();
+        updateCounts(COUNTS);
         // Test with detachIfReset=true
         mCounterArray.reset(true /* detachIfReset */);
-        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
-        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
-        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mCounts);
         verify(mTimeBase).remove(mCounterArray);
         verifyNoMoreInteractions(mTimeBase);
     }
@@ -232,18 +189,7 @@
         verifyNoMoreInteractions(mTimeBase);
     }
 
-    private void initializeCounterArrayWithDefaultValues() {
-        updateCounts(COUNTS, LOADED_COUNTS, UNPLUGGED_COUNTS);
-    }
-
-    private void assertArrayEquals(long[] expected, long[] actual, String msg) {
-        assertTrue(msg + ", expected: " + Arrays.toString(expected)
-                + ", actual: " + Arrays.toString(actual), Arrays.equals(expected, actual));
-    }
-
-    private void updateCounts(long[] counts, long[] loadedCounts, long[] unpluggedCounts) {
+    private void updateCounts(long[] counts) {
         mCounterArray.mCounts = counts == null ? null : counts.clone();
-        mCounterArray.mLoadedCounts = loadedCounts == null ? null : loadedCounts.clone();
-        mCounterArray.mUnpluggedCounts = unpluggedCounts == null ? null : unpluggedCounts.clone();
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java
index d2f5735..dccc3d3 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java
@@ -51,7 +51,6 @@
 public class LongSamplingCounterTest {
 
     private static final long COUNT = 1111;
-    private static final long CURRENT_COUNT = 5555;
 
     @Mock
     private TimeBase mTimeBase;
@@ -67,116 +66,87 @@
     @Test
     public void testReadWriteParcel() {
         final Parcel parcel = Parcel.obtain();
-        updateCounts(COUNT, CURRENT_COUNT);
+        mCounter.addCountLocked(COUNT, true);
+        assertEquals(COUNT, getCount());
         mCounter.writeToParcel(parcel);
         parcel.setDataPosition(0);
 
-        // Now clear counterArray and verify values are read from parcel correctly.
-        updateCounts(0, 0);
+        // Now change count but verify values are read from parcel correctly.
+        mCounter.addCountLocked(7 * COUNT, true);
+        assertEquals(8 * COUNT, getCount());
 
         mCounter = new LongSamplingCounter(mTimeBase, parcel);
-        assertEquals(COUNT, mCounter.mCount);
-        assertEquals(CURRENT_COUNT, mCounter.mCurrentCount);
+        assertEquals(COUNT, getCount());
         parcel.recycle();
     }
 
     @Test
     public void testReadWriteSummaryParcel() {
         final Parcel parcel = Parcel.obtain();
-        updateCounts(COUNT, CURRENT_COUNT);
+        mCounter.addCountLocked(COUNT, true);
+        assertEquals(COUNT, getCount());
         mCounter.writeSummaryFromParcelLocked(parcel);
         parcel.setDataPosition(0);
 
-        // Now clear counterArray and verify values are read from parcel correctly.
-        updateCounts(0, 0);
+        // Now change count but verify values are read from parcel correctly.
+        mCounter.addCountLocked(7 * COUNT, true);
+        assertEquals(8 * COUNT, getCount());
 
         mCounter.readSummaryFromParcelLocked(parcel);
-        assertEquals(COUNT, mCounter.mCount);
+        assertEquals(COUNT, getCount());
         parcel.recycle();
     }
 
     @Test
     public void testOnTimeStarted() {
-        updateCounts(COUNT, CURRENT_COUNT);
+        mCounter.addCountLocked(COUNT, true);
+        assertEquals(COUNT, getCount());
         mCounter.onTimeStarted(0, 0, 0);
-        assertEquals(COUNT, mCounter.mCount);
-        assertEquals(COUNT, mCounter.mUnpluggedCount);
+        assertEquals(COUNT, getCount());
     }
 
     @Test
     public void testOnTimeStopped() {
-        updateCounts(COUNT, CURRENT_COUNT);
+        mCounter.addCountLocked(COUNT, true);
+        assertEquals(COUNT, getCount());
         mCounter.onTimeStopped(0, 0, 0);
-        assertEquals(COUNT, mCounter.mCount);
+        assertEquals(COUNT, getCount());
     }
 
     @Test
     public void testAddCountLocked() {
-        updateCounts(0, 0);
-        assertEquals(0, mCounter.getCountLocked(0));
+        assertEquals(0, getCount());
         when(mTimeBase.isRunning()).thenReturn(true);
         mCounter.addCountLocked(111);
         assertEquals(111, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(111, mCounter.mCurrentCount);
         mCounter.addCountLocked(222);
         assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(333, mCounter.mCurrentCount);
 
         when(mTimeBase.isRunning()).thenReturn(false);
         mCounter.addCountLocked(456);
         assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(789, mCounter.mCurrentCount);
 
         mCounter.addCountLocked(444, true);
         assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(1233, mCounter.mCurrentCount);
         mCounter.addCountLocked(567, false);
         assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(1800, mCounter.mCurrentCount);
     }
 
-    @Test
-    public void testUpdate() {
-        updateCounts(0, 0);
-        assertEquals(0, mCounter.getCountLocked(0));
-        when(mTimeBase.isRunning()).thenReturn(true);
-        mCounter.update(111);
-        assertEquals(111, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(111, mCounter.mCurrentCount);
-        mCounter.update(333);
-        assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(333, mCounter.mCurrentCount);
-
-        when(mTimeBase.isRunning()).thenReturn(false);
-        mCounter.update(789);
-        assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(789, mCounter.mCurrentCount);
-        mCounter.update(100);
-        assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(100, mCounter.mCurrentCount);
-
-        mCounter.update(544, true);
-        assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(544, mCounter.mCurrentCount);
-        mCounter.update(1544, false);
-        assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED));
-        assertEquals(1544, mCounter.mCurrentCount);
-    }
 
     @Test
     public void testReset() {
-        updateCounts(COUNT, CURRENT_COUNT);
+        mCounter.addCountLocked(COUNT, true);
+        assertEquals(COUNT, getCount());
         // Test with detachIfReset=false
         mCounter.reset(false /* detachIfReset */);
-        assertEquals(0, mCounter.mCount);
-        assertEquals(CURRENT_COUNT, mCounter.mCurrentCount);
+        assertEquals(0, getCount());
         verifyZeroInteractions(mTimeBase);
 
-        updateCounts(COUNT, CURRENT_COUNT);
+        mCounter.addCountLocked(COUNT, true);
+        assertEquals(COUNT, getCount());
         // Test with detachIfReset=true
         mCounter.reset(true /* detachIfReset */);
-        assertEquals(0, mCounter.mCount);
-        assertEquals(CURRENT_COUNT, mCounter.mCurrentCount);
+        assertEquals(0, getCount());
         verify(mTimeBase).remove(mCounter);
         verifyNoMoreInteractions(mTimeBase);
     }
@@ -188,8 +158,7 @@
         verifyNoMoreInteractions(mTimeBase);
     }
 
-    private void updateCounts(long total, long current) {
-        mCounter.mCount = total;
-        mCounter.mCurrentCount = current;
+    private long getCount() {
+        return mCounter.getCountLocked(STATS_SINCE_CHARGED);
     }
 }
diff --git a/core/tests/overlaytests/device/assets/package-name.txt b/core/tests/overlaytests/device/assets/package-name.txt
new file mode 100644
index 0000000..8094438
--- /dev/null
+++ b/core/tests/overlaytests/device/assets/package-name.txt
@@ -0,0 +1 @@
+com.android.overlaytest
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
index 91fcdbb..f86743a 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
@@ -17,9 +17,12 @@
 package com.android.overlaytest;
 
 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.app.UiAutomation;
+import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -30,6 +33,8 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.internal.util.ArrayUtils;
+
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -291,6 +296,33 @@
         assertEquals(getExpected(no, so, mo), actual);
     }
 
+    @Test
+    public void testAssetsNotPossibleToOverlay() throws Throwable {
+        final AssetManager am = mResources.getAssets();
+
+        // AssetManager#list will include assets from all loaded non-overlay
+        // APKs, including the framework; framework-res.apk contains at least
+        // assets/{images,webkit}. Rather than checking the list, verify that
+        // assets only present in overlays are never part of the list.
+        String[] files = am.list("");
+        assertTrue(ArrayUtils.contains(files, "package-name.txt"));
+        assertFalse(ArrayUtils.contains(files, "foo.txt"));
+        assertFalse(ArrayUtils.contains(files, "bar.txt"));
+
+        String contents = null;
+        try (InputStream is = am.open("package-name.txt")) {
+            final BufferedReader reader = new BufferedReader(
+                    new InputStreamReader(is, StandardCharsets.UTF_8));
+            StringBuilder str = new StringBuilder();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                str.append(line);
+            }
+            contents = str.toString();
+        }
+        assertEquals("com.android.overlaytest", contents);
+    }
+
     /*
      * testMatrix* tests
      *
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
index 1719158..8ac6953 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
@@ -18,5 +18,6 @@
         package="com.android.overlaytest.app_overlay_one"
         android:versionCode="1"
         android:versionName="1.0">
+        <application android:hasCode="false" />
         <overlay android:targetPackage="com.android.overlaytest" android:priority="1" />
 </manifest>
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/foo.txt b/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/foo.txt
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/foo.txt
@@ -0,0 +1 @@
+foo
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/package-name.txt b/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/package-name.txt
new file mode 100644
index 0000000..087cb96
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/package-name.txt
@@ -0,0 +1 @@
+com.android.overlaytest.app_overlay_one
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml
index ae8307c..f3c39cc 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml
@@ -18,5 +18,6 @@
         package="com.android.overlaytest.app_overlay_two"
         android:versionCode="1"
         android:versionName="1.0">
+        <application android:hasCode="false" />
         <overlay android:targetPackage="com.android.overlaytest" android:priority="2" />
 </manifest>
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/bar.txt b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/bar.txt
new file mode 100644
index 0000000..5716ca5
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/bar.txt
@@ -0,0 +1 @@
+bar
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/package-name.txt b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/package-name.txt
new file mode 100644
index 0000000..1318565
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/package-name.txt
@@ -0,0 +1 @@
+com.android.overlaytest.app_overlay_two
diff --git a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml
index 77ea16a..73a83e0 100644
--- a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml
+++ b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml
@@ -18,5 +18,6 @@
         package="com.android.overlaytest.framework"
         android:versionCode="1"
         android:versionName="1.0">
+        <application android:hasCode="false" />
         <overlay android:targetPackage="android" android:priority="1" />
 </manifest>
diff --git a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java
index 27986cc..f9672d2 100644
--- a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java
+++ b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java
@@ -155,12 +155,26 @@
         }
     }
 
+    private void delay() {
+        try {
+            Thread.sleep(100);
+        } catch (InterruptedException e) {
+        }
+    }
+
+    private void installPackage(String pkg) throws Exception {
+        super.installPackage(pkg);
+        delay();
+    }
+
     private void setPackageEnabled(String pkg, boolean enabled) throws Exception {
         getDevice().executeShellCommand("cmd package " + (enabled ? "enable " : "disable ") + pkg);
+        delay();
     }
 
     private void setOverlayEnabled(String pkg, boolean enabled) throws Exception {
         getDevice().executeShellCommand("cmd overlay " + (enabled ? "enable " : "disable ") + pkg);
+        delay();
     }
 
     private boolean overlayManagerContainsPackage(String pkg) throws Exception {
diff --git a/core/tests/overlaytests/host/test-apps/SignatureOverlay/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/SignatureOverlay/AndroidManifest.xml
index b08ac96..26b3875 100644
--- a/core/tests/overlaytests/host/test-apps/SignatureOverlay/AndroidManifest.xml
+++ b/core/tests/overlaytests/host/test-apps/SignatureOverlay/AndroidManifest.xml
@@ -16,5 +16,6 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.server.om.hosttest.signature_overlay">
+    <application android:hasCode="false" />
     <overlay android:targetPackage="android" />
 </manifest>
diff --git a/core/tests/overlaytests/host/test-apps/SignatureOverlay/static/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/SignatureOverlay/static/AndroidManifest.xml
index 139dd96..8a66423 100644
--- a/core/tests/overlaytests/host/test-apps/SignatureOverlay/static/AndroidManifest.xml
+++ b/core/tests/overlaytests/host/test-apps/SignatureOverlay/static/AndroidManifest.xml
@@ -16,5 +16,6 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.server.om.hosttest.signature_overlay">
+    <application android:hasCode="false" />
     <overlay android:targetPackage="android" android:isStatic="true" />
 </manifest>
diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v1/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v1/AndroidManifest.xml
index 73804eb..b6ff0c3 100644
--- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v1/AndroidManifest.xml
+++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v1/AndroidManifest.xml
@@ -16,5 +16,6 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.server.om.hosttest.app_overlay">
+    <application android:hasCode="false" />
     <overlay android:targetPackage="com.android.server.om.hosttest.update_overlay_test" />
 </manifest>
diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v2/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v2/AndroidManifest.xml
index 9ec7d06..f1a3981 100644
--- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v2/AndroidManifest.xml
+++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v2/AndroidManifest.xml
@@ -16,6 +16,7 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.server.om.hosttest.app_overlay">
+    <application android:hasCode="false" />
     <overlay android:targetPackage="com.android.server.om.hosttest.update_overlay_test"
         android:category="android.theme" />
 </manifest>
diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/framework/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/UpdateOverlay/framework/AndroidManifest.xml
index 8c8fe94..025d1a2 100644
--- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/framework/AndroidManifest.xml
+++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/framework/AndroidManifest.xml
@@ -16,5 +16,6 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.server.om.hosttest.framework_overlay">
+    <application android:hasCode="false" />
     <overlay android:targetPackage="android" />
 </manifest>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 44d71e2..28d311e 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -202,17 +202,15 @@
         <new-permission name="android.permission.ACCESS_BACKGROUND_LOCATION" />
     </split-permission>
 
-    <!-- Apps holding either the legacy READ or WRITE permissions will inherit
-         the ability to <em>read</em> new typed permissions in the Q release; they
-         won't gain the ability to <em>write</em> that content. -->
-    <!-- STOPSHIP(b/112545973): change targetSdk to Q when SDK version finalised -->
+    <!-- STOPSHIP: change targetSdk to Q when SDK version finalised -->
+    <!-- Old apps might not understand the modern permission model, hence their view needs to be expanded -->
     <split-permission name="android.permission.READ_EXTERNAL_STORAGE"
                       targetSdk="10000">
         <new-permission name="android.permission.READ_MEDIA_AUDIO" />
         <new-permission name="android.permission.READ_MEDIA_VIDEO" />
         <new-permission name="android.permission.READ_MEDIA_IMAGES" />
     </split-permission>
-    <!-- STOPSHIP(b/112545973): change targetSdk to Q when SDK version finalised -->
+    <!-- STOPSHIP: change targetSdk to Q when SDK version finalised -->
     <split-permission name="android.permission.WRITE_EXTERNAL_STORAGE"
                       targetSdk="10000">
         <new-permission name="android.permission.READ_MEDIA_AUDIO" />
@@ -220,6 +218,20 @@
         <new-permission name="android.permission.READ_MEDIA_IMAGES" />
     </split-permission>
 
+    <!-- An app using the typed media permissions might be grandfathered and then uses the old storage model -->
+    <split-permission name="android.permission.READ_MEDIA_AUDIO">
+        <new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
+        <new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    </split-permission>
+    <split-permission name="android.permission.READ_MEDIA_VIDEO">
+        <new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
+        <new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    </split-permission>
+    <split-permission name="android.permission.READ_MEDIA_IMAGES">
+        <new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
+        <new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    </split-permission>
+
     <!-- This is a list of all the libraries available for application
          code to link against. -->
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index fcd5d56..94f69b8 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -307,6 +307,7 @@
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
         <permission name="android.permission.STATUS_BAR_SERVICE"/>
         <permission name="android.permission.REQUEST_INCIDENT_REPORT_APPROVAL"/>
+        <permission name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/docs/html/reference/images/text/style/lineheightspan.png b/docs/html/reference/images/text/style/lineheightspan.png
new file mode 100644
index 0000000..18f5753
--- /dev/null
+++ b/docs/html/reference/images/text/style/lineheightspan.png
Binary files differ
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 0d52338..9c4b5e8 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -1809,6 +1809,45 @@
     }
 
     /**
+     * <p>Computes the chromaticity coordinates of a specified correlated color
+     * temperature (CCT) on the Planckian locus. The specified CCT must be
+     * greater than 0. A meaningful CCT range is [1667, 25000].</p>
+     *
+     * <p>The transform is computed using the methods in Kang et
+     * al., <i>Design of Advanced Color - Temperature Control System for HDTV
+     * Applications</i>, Journal of Korean Physical Society 41, 865-871
+     * (2002).</p>
+     *
+     * @param cct The correlated color temperature, in Kelvin
+     * @return Corresponding XYZ values
+     * @throws IllegalArgumentException If cct is invalid
+     *
+     * @hide
+     */
+    @NonNull
+    @Size(3)
+    public static float[] cctToXyz(@IntRange(from = 1) int cct) {
+        if (cct < 1) {
+            throw new IllegalArgumentException("Temperature must be greater than 0");
+        }
+
+        final float icct = 1e3f / cct;
+        final float icct2 = icct * icct;
+        final float x = cct <= 4000.0f ?
+            0.179910f + 0.8776956f * icct - 0.2343589f * icct2 - 0.2661239f * icct2 * icct :
+            0.240390f + 0.2226347f * icct + 2.1070379f * icct2 - 3.0258469f * icct2 * icct;
+
+        final float x2 = x * x;
+        final float y = cct <= 2222.0f ?
+            -0.20219683f + 2.18555832f * x - 1.34811020f * x2 - 1.1063814f * x2 * x :
+            cct <= 4000.0f ?
+            -0.16748867f + 2.09137015f * x - 1.37418593f * x2 - 0.9549476f * x2 * x :
+            -0.37001483f + 3.75112997f * x - 5.8733867f * x2 + 3.0817580f * x2 * x;
+
+        return xyYToXyz(new float[] {x, y});
+    }
+
+    /**
      * <p>Computes the chromaticity coordinates of a CIE series D illuminant
      * from the specified correlated color temperature (CCT). The specified CCT
      * must be greater than 0. A meaningful CCT range is [4000, 25000].</p>
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 9995f1e..c8b361b 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -33,7 +33,6 @@
 import android.graphics.fonts.FontVariationAxis;
 import android.graphics.fonts.SystemFonts;
 import android.os.Build;
-import android.os.Build.VERSION_CODES;
 import android.os.ParcelFileDescriptor;
 import android.provider.FontRequest;
 import android.provider.FontsContract;
@@ -48,7 +47,6 @@
 import com.android.internal.util.Preconditions;
 
 import dalvik.annotation.optimization.CriticalNative;
-import dalvik.system.VMRuntime;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -266,16 +264,7 @@
                 if (familyBuilder == null) {
                     familyBuilder = new FontFamily.Builder(fontBuilder.build());
                 } else {
-                    try {
-                        familyBuilder.addFont(fontBuilder.build());
-                    } catch (IllegalArgumentException e) {
-                        if (VMRuntime.getRuntime().getTargetSdkVersion() <= VERSION_CODES.P) {
-                            // Surpress the IllegalArgumentException for keeping the backward
-                            // compatibility.
-                            continue;
-                        }
-                        throw e;
-                    }
+                    familyBuilder.addFont(fontBuilder.build());
                 }
             }
             if (familyBuilder == null) {
@@ -297,6 +286,10 @@
             typeface = new Typeface.CustomFallbackBuilder(family)
                     .setStyle(bestFont.getStyle())
                     .build();
+        } catch (IllegalArgumentException e) {
+            // To be a compatible behavior with API28 or before, catch IllegalArgumentExcetpion
+            // thrown by native code and returns null.
+            return null;
         } catch (IOException e) {
             typeface = Typeface.DEFAULT;
         }
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index d74f27c..9519704 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -310,6 +310,9 @@
   // Start from the back.
   for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) {
     const ApkAssets* apk_assets = *iter;
+    if (apk_assets->IsOverlay()) {
+      continue;
+    }
 
     auto func = [&](const StringPiece& name, FileType type) {
       AssetDir::FileInfo info;
@@ -336,6 +339,13 @@
                                                    Asset::AccessMode mode,
                                                    ApkAssetsCookie* out_cookie) const {
   for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) {
+    // Prevent RRO from modifying assets and other entries accessed by file
+    // path. Explicitly asking for a path in a given package (denoted by a
+    // cookie) is still OK.
+    if (apk_assets_[i]->IsOverlay()) {
+      continue;
+    }
+
     std::unique_ptr<Asset> asset = apk_assets_[i]->Open(filename, mode);
     if (asset) {
       if (out_cookie != nullptr) {
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index db2d038..35bbb58 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -80,6 +80,10 @@
     return loaded_arsc_.get();
   }
 
+  inline bool IsOverlay() const {
+    return idmap_asset_.get() != nullptr;
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ApkAssets);
 
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 9298be6..5f43b48 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -41,6 +41,7 @@
 namespace android {
 
 class Bitmap;
+class AutoBackendTextureRelease;
 
 namespace uirenderer {
 
@@ -135,6 +136,7 @@
     friend class DispatchFrameCallbacks;
     friend class RenderProxy;
     friend class DummyVsyncSource;
+    friend class android::AutoBackendTextureRelease;
     friend class android::uirenderer::TestUtils;
     friend class android::uirenderer::WebViewFunctor;
     friend class android::uirenderer::skiapipeline::VkFunctorDrawHandler;
diff --git a/libs/hwui/surfacetexture/ImageConsumer.cpp b/libs/hwui/surfacetexture/ImageConsumer.cpp
index 077a8f7..65d95ad 100644
--- a/libs/hwui/surfacetexture/ImageConsumer.cpp
+++ b/libs/hwui/surfacetexture/ImageConsumer.cpp
@@ -24,13 +24,17 @@
 #include "renderthread/VulkanManager.h"
 #include "utils/Color.h"
 #include <GrAHardwareBufferUtils.h>
+#include <GrBackendSurface.h>
 
 // Macro for including the SurfaceTexture name in log messages
 #define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
 
+using namespace android::uirenderer::renderthread;
+
 namespace android {
 
 void ImageConsumer::onFreeBufferLocked(int slotIndex) {
+    // This callback may be invoked on any thread.
     mImageSlots[slotIndex].clear();
 }
 
@@ -46,55 +50,141 @@
     mImageSlots[buf].eglFence() = EGL_NO_SYNC_KHR;
 }
 
+/**
+ * AutoBackendTextureRelease manages EglImage/VkImage lifetime. It is a ref-counted object
+ * that keeps GPU resources alive until the last SKImage object using them is destroyed.
+ */
+class AutoBackendTextureRelease {
+public:
+    static void releaseProc(SkImage::ReleaseContext releaseContext);
+
+    AutoBackendTextureRelease(GrContext* context, GraphicBuffer* buffer);
+
+    const GrBackendTexture& getTexture() const { return mBackendTexture; }
+
+    void ref() { mUsageCount++; }
+
+    void unref(bool releaseImage);
+
+    inline sk_sp<SkImage> getImage() { return mImage; }
+
+    void makeImage(sp<GraphicBuffer>& graphicBuffer, android_dataspace dataspace,
+                   GrContext* context);
+
+private:
+    // The only way to invoke dtor is with unref, when mUsageCount is 0.
+    ~AutoBackendTextureRelease() {}
+
+    GrBackendTexture mBackendTexture;
+    GrAHardwareBufferUtils::DeleteImageProc mDeleteProc;
+    GrAHardwareBufferUtils::DeleteImageCtx mDeleteCtx;
+
+    // Starting with refcount 1, because the first ref is held by SurfaceTexture. Additional refs
+    // are held by SkImages.
+    int mUsageCount = 1;
+
+    // mImage is the SkImage created from mBackendTexture.
+    sk_sp<SkImage> mImage;
+};
+
+AutoBackendTextureRelease::AutoBackendTextureRelease(GrContext* context, GraphicBuffer* buffer) {
+    bool createProtectedImage =
+        0 != (buffer->getUsage() & GraphicBuffer::USAGE_PROTECTED);
+    GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(
+        context,
+        reinterpret_cast<AHardwareBuffer*>(buffer),
+        buffer->getPixelFormat(),
+        false);
+    mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture(
+        context,
+        reinterpret_cast<AHardwareBuffer*>(buffer),
+        buffer->getWidth(),
+        buffer->getHeight(),
+        &mDeleteProc,
+        &mDeleteCtx,
+        createProtectedImage,
+        backendFormat,
+        false);
+}
+
+void AutoBackendTextureRelease::unref(bool releaseImage) {
+    if (!RenderThread::isCurrent()) {
+        // EGLImage needs to be destroyed on RenderThread to prevent memory leak.
+        // ~SkImage dtor for both pipelines needs to be invoked on RenderThread, because it is not
+        // thread safe.
+        RenderThread::getInstance().queue().post([this, releaseImage]() { unref(releaseImage); });
+        return;
+    }
+
+    if (releaseImage) {
+        mImage.reset();
+    }
+
+    mUsageCount--;
+    if (mUsageCount <= 0) {
+        if (mBackendTexture.isValid()) {
+            mDeleteProc(mDeleteCtx);
+            mBackendTexture = {};
+        }
+        delete this;
+    }
+}
+
+void AutoBackendTextureRelease::releaseProc(SkImage::ReleaseContext releaseContext) {
+    AutoBackendTextureRelease* textureRelease =
+        reinterpret_cast<AutoBackendTextureRelease*>(releaseContext);
+    textureRelease->unref(false);
+}
+
+void AutoBackendTextureRelease::makeImage(sp<GraphicBuffer>& graphicBuffer,
+                                          android_dataspace dataspace, GrContext* context) {
+    SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(
+        graphicBuffer->getPixelFormat());
+    mImage = SkImage::MakeFromTexture(context,
+        mBackendTexture,
+        kTopLeft_GrSurfaceOrigin,
+        colorType,
+        kPremul_SkAlphaType,
+        uirenderer::DataSpaceToColorSpace(dataspace),
+        releaseProc,
+        this);
+    if (mImage.get()) {
+        // The following ref will be counteracted by releaseProc, when SkImage is discarded.
+        ref();
+    }
+}
+
 void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer,
                                               android_dataspace dataspace, bool forceCreate,
                                               GrContext* context) {
-    if (!mImage.get() || dataspace != mDataspace || forceCreate) {
+    if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace
+            || forceCreate) {
         if (!graphicBuffer.get()) {
             clear();
             return;
         }
 
-        if (!mBackendTexture.isValid()) {
-            clear();
-            bool createProtectedImage =
-                0 != (graphicBuffer->getUsage() & GraphicBuffer::USAGE_PROTECTED);
-            GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(
-                context,
-                reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
-                graphicBuffer->getPixelFormat(),
-                false);
-            mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture(
-                context,
-                reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
-                graphicBuffer->getWidth(),
-                graphicBuffer->getHeight(),
-                &mDeleteProc,
-                &mDeleteCtx,
-                createProtectedImage,
-                backendFormat,
-                false);
+        if (!mTextureRelease) {
+            mTextureRelease = new AutoBackendTextureRelease(context, graphicBuffer.get());
         }
+
         mDataspace = dataspace;
-        SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(
-            graphicBuffer->getPixelFormat());
-        mImage = SkImage::MakeFromTexture(context,
-            mBackendTexture,
-            kTopLeft_GrSurfaceOrigin,
-            colorType,
-            kPremul_SkAlphaType,
-            uirenderer::DataSpaceToColorSpace(dataspace));
+        mTextureRelease->makeImage(graphicBuffer, dataspace, context);
     }
 }
 
 void ImageConsumer::ImageSlot::clear() {
-    mImage.reset();
-    if (mBackendTexture.isValid()) {
-        mDeleteProc(mDeleteCtx);
-        mBackendTexture = {};
+    if (mTextureRelease) {
+        // The following unref counteracts the initial mUsageCount of 1, set by default initializer.
+        mTextureRelease->unref(true);
+        mTextureRelease = nullptr;
     }
 }
 
+sk_sp<SkImage> ImageConsumer::ImageSlot::getImage() {
+    return mTextureRelease ? mTextureRelease->getImage() : nullptr;
+}
+
 sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
                                            uirenderer::RenderState& renderState) {
     BufferItem item;
diff --git a/libs/hwui/surfacetexture/ImageConsumer.h b/libs/hwui/surfacetexture/ImageConsumer.h
index eee0a0a..2fdece9 100644
--- a/libs/hwui/surfacetexture/ImageConsumer.h
+++ b/libs/hwui/surfacetexture/ImageConsumer.h
@@ -25,7 +25,6 @@
 #include <cutils/compiler.h>
 #include <gui/BufferItem.h>
 #include <system/graphics.h>
-#include <GrBackendSurface.h>
 
 namespace GrAHardwareBufferUtils {
 typedef void* DeleteImageCtx;
@@ -38,6 +37,7 @@
 class RenderState;
 }
 
+class AutoBackendTextureRelease;
 class SurfaceTexture;
 
 /*
@@ -81,16 +81,14 @@
 
         void createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace,
                             bool forceCreate, GrContext* context);
+
         void clear();
 
         inline EGLSyncKHR& eglFence() { return mEglFence; }
 
-        inline sk_sp<SkImage> getImage() { return mImage; }
+        sk_sp<SkImage> getImage();
 
     private:
-        // mImage is the SkImage created from mGraphicBuffer.
-        sk_sp<SkImage> mImage;
-
         // the dataspace associated with the current image
         android_dataspace mDataspace;
 
@@ -100,11 +98,11 @@
          */
         EGLSyncKHR mEglFence;
 
-        GrBackendTexture mBackendTexture;
-
-        GrAHardwareBufferUtils::DeleteImageProc mDeleteProc;
-
-        GrAHardwareBufferUtils::DeleteImageCtx mDeleteCtx;
+        /**
+         * mTextureRelease may outlive ImageConsumer, if the last ref is held by an SkImage.
+         * ImageConsumer holds one ref to mTextureRelease, which is decremented by "clear".
+         */
+        AutoBackendTextureRelease* mTextureRelease = nullptr;
     };
 
     /**
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
new file mode 100644
index 0000000..6a35920
--- /dev/null
+++ b/location/java/android/location/GnssCapabilities.java
@@ -0,0 +1,153 @@
+/*
+ * 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.location;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A container of supported GNSS chipset capabilities.
+ *
+ * @hide
+ */
+@SystemApi
+public final class GnssCapabilities {
+    /** The GNSS chipset supports low power mode. */
+    public static final int LOW_POWER_MODE                                              = 0;
+
+    /** The GNSS chipset supports blacklisting satellites. */
+    public static final int SATELLITE_BLACKLIST                                         = 1;
+
+    /** The GNSS chipset supports geofencing. */
+    public static final int GEOFENCING                                                  = 2;
+
+    /** The GNSS chipset supports measurements.*/
+    public static final int MEASUREMENTS                                                = 3;
+
+    /** The GNSS chipset supports navigation messages. */
+    public static final int NAV_MESSAGES                                                = 4;
+
+    /** The GNSS chipset supports measurement corrections. */
+    public static final int MEASUREMENT_CORRECTIONS                                     = 5;
+
+    /** The GNSS chipset supports line-of-sight satellite identification measurement corrections. */
+    public static final int MEASUREMENT_CORRECTIONS_LOS_SATS                            = 6;
+
+    /** The GNSS chipset supports per satellite excess-path-length measurement corrections. */
+    public static final int MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH                  = 7;
+
+    /** The GNSS chipset supports reflecting planes measurement corrections. */
+    public static final int MEASUREMENT_CORRECTIONS_REFLECTING_PLANE                    = 8;
+
+    private static final int MIN_CAPABILITY = 0;
+    private static final int MAX_CAPABILITY = MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;
+
+    /**
+     * GNSS capability.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            LOW_POWER_MODE,
+            SATELLITE_BLACKLIST,
+            GEOFENCING,
+            MEASUREMENTS,
+            NAV_MESSAGES,
+            MEASUREMENT_CORRECTIONS,
+            MEASUREMENT_CORRECTIONS_LOS_SATS,
+            MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH,
+            MEASUREMENT_CORRECTIONS_REFLECTING_PLANE
+    })
+    public @interface Capability {}
+
+    /**
+     * @hide
+     */
+    public static final long INVALID_CAPABILITIES = -1;
+
+    /** A bitmask of supported GNSS capabilities. */
+    private final long mGnssCapabilities;
+
+    static GnssCapabilities of(long gnssCapabilities) {
+        return new GnssCapabilities(gnssCapabilities);
+    }
+
+    private GnssCapabilities(long gnssCapabilities) {
+        mGnssCapabilities = gnssCapabilities;
+    }
+
+    /**
+     * Returns {@code true} if the {@code capability} is supported by the GNSS implementation.
+     */
+    public boolean hasCapability(@Capability int capability) {
+        return isValidCapability(capability) && (mGnssCapabilities & (1 << capability)) != 0;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("GnssCapabilities: (");
+        int capability = 0;
+        boolean addSeparator = false;
+        long gnssCapabilities = mGnssCapabilities;
+        while (gnssCapabilities != 0) {
+            if ((gnssCapabilities & 1) != 0) {
+                if (addSeparator) {
+                    sb.append(' ');
+                } else {
+                    addSeparator = true;
+                }
+                sb.append(toStringCapability(capability));
+            }
+            gnssCapabilities >>= 1;
+            ++capability;
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+
+    private boolean isValidCapability(@Capability int capability) {
+        return capability >= MIN_CAPABILITY && capability <= MAX_CAPABILITY;
+    }
+
+    private static String toStringCapability(@Capability int capability) {
+        switch (capability) {
+            case LOW_POWER_MODE:
+                return "LOW_POWER_MODE";
+            case SATELLITE_BLACKLIST:
+                return "SATELLITE_BLACKLIST";
+            case GEOFENCING:
+                return "GEOFENCING";
+            case MEASUREMENTS:
+                return "MEASUREMENTS";
+            case NAV_MESSAGES:
+                return "NAV_MESSAGES";
+            case MEASUREMENT_CORRECTIONS:
+                return "MEASUREMENT_CORRECTIONS";
+            case MEASUREMENT_CORRECTIONS_LOS_SATS:
+                return "MEASUREMENT_CORRECTIONS_LOS_SATS";
+            case MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH:
+                return "MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH";
+            case MEASUREMENT_CORRECTIONS_REFLECTING_PLANE:
+                return "MEASUREMENT_CORRECTIONS_REFLECTING_PLANE";
+            default:
+                return "Unknown(" + capability + ")";
+        }
+    }
+}
diff --git a/location/java/android/location/GnssMeasurementCallbackTransport.java b/location/java/android/location/GnssMeasurementCallbackTransport.java
index 1188b13b..8cb8c0b 100644
--- a/location/java/android/location/GnssMeasurementCallbackTransport.java
+++ b/location/java/android/location/GnssMeasurementCallbackTransport.java
@@ -63,7 +63,7 @@
                 measurementCorrections, getContext().getPackageName());
     }
 
-    protected int getGnssCapabilities() throws RemoteException {
+    protected long getGnssCapabilities() throws RemoteException {
         return mLocationManager.getGnssCapabilities(getContext().getPackageName());
     }
 
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 60c7748..ce464b7 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -42,6 +42,8 @@
     public static final int CONSTELLATION_BEIDOU = 5;
     /** Constellation type constant for Galileo. */
     public static final int CONSTELLATION_GALILEO = 6;
+    /** Constellation type constant for IRNSS. */
+    public static final int CONSTELLATION_IRNSS = 7;
 
     /** @hide */
     public static final int GNSS_SV_FLAGS_NONE = 0;
@@ -94,7 +96,7 @@
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({CONSTELLATION_UNKNOWN, CONSTELLATION_GPS, CONSTELLATION_SBAS, CONSTELLATION_GLONASS,
-            CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO})
+            CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO, CONSTELLATION_IRNSS})
     public @interface ConstellationType {}
 
     final int[] mSvidWithFlags;
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index c371c5f..93dc6fa 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -29,6 +29,7 @@
 import android.location.ILocationListener;
 import android.location.Location;
 import android.location.LocationRequest;
+import android.location.LocationTime;
 import android.os.Bundle;
 
 import com.android.internal.location.ProviderProperties;
@@ -66,7 +67,7 @@
     boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener, in String packageName);
     void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections,
             in String packageName);
-    int getGnssCapabilities(in String packageName);
+    long getGnssCapabilities(in String packageName);
     void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
 
     boolean addGnssNavigationMessageListener(
@@ -104,6 +105,7 @@
     void setTestProviderLocation(String provider, in Location loc, String opPackageName);
     void setTestProviderEnabled(String provider, boolean enabled, String opPackageName);
     List<LocationRequest> getTestProviderCurrentRequests(String provider, String opPackageName);
+    LocationTime getGnssTimeMillis();
 
     // --- deprecated ---
     void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime,
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 01f1798..edf304c 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1986,15 +1986,19 @@
     }
 
     /**
-     * Returns the integer capability flags of the GNSS chipset as defined in {@code
-     * IGnssCallback.hal}
+     * Returns the supported capabilities of the GNSS chipset or {@code null} if there is an error
+     * in obtaining the capabilities.
      *
      * @hide
      */
     @SystemApi
-    public int getGnssCapabilities() {
+    public @Nullable GnssCapabilities getGnssCapabilities() {
         try {
-            return mGnssMeasurementCallbackTransport.getGnssCapabilities();
+            long gnssCapabilities = mGnssMeasurementCallbackTransport.getGnssCapabilities();
+            if (gnssCapabilities == GnssCapabilities.INVALID_CAPABILITIES) {
+                return null;
+            }
+            return GnssCapabilities.of(gnssCapabilities);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/location/java/android/location/LocationTime.aidl b/location/java/android/location/LocationTime.aidl
new file mode 100644
index 0000000..f626363
--- /dev/null
+++ b/location/java/android/location/LocationTime.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.location;
+
+parcelable LocationTime;
diff --git a/location/java/android/location/LocationTime.java b/location/java/android/location/LocationTime.java
new file mode 100644
index 0000000..e5535d1
--- /dev/null
+++ b/location/java/android/location/LocationTime.java
@@ -0,0 +1,73 @@
+/*
+ * 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.location;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Data class for passing location derived time.
+ * @hide
+ */
+public final class LocationTime implements Parcelable {
+
+    private final long mTime;
+    private final long mElapsedRealtimeNanos;
+
+    public LocationTime(long time, long elapsedRealtimeNanos) {
+        mTime = time;
+        mElapsedRealtimeNanos = elapsedRealtimeNanos;
+    }
+
+    /**
+     * The current time, according to the Gnss location provider. */
+    public long getTime() {
+        return mTime;
+    }
+
+    /**
+     * The elapsed nanos since boot {@link #getTime} was computed at.
+     */
+    public long getElapsedRealtimeNanos() {
+        return mElapsedRealtimeNanos;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeLong(mTime);
+        out.writeLong(mElapsedRealtimeNanos);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final @NonNull Parcelable.Creator<LocationTime> CREATOR =
+            new Parcelable.Creator<LocationTime>() {
+                public LocationTime createFromParcel(Parcel in) {
+                    long time = in.readLong();
+                    long elapsedRealtimeNanos = in.readLong();
+                    return new LocationTime(time, elapsedRealtimeNanos);
+                }
+
+                public LocationTime[] newArray(int size) {
+                    return new LocationTime[size];
+                }
+            };
+}
diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java
index fbe184b..13ff108 100644
--- a/media/apex/java/android/media/MediaPlayer2.java
+++ b/media/apex/java/android/media/MediaPlayer2.java
@@ -274,8 +274,7 @@
  * successful transition. Any other value will be an error. Call {@link #getState()} to
  * determine the current state. </p>
  */
-public class MediaPlayer2 implements AutoCloseable
-                                            , AudioRouting {
+public class MediaPlayer2 implements AutoCloseable, AudioRouting {
     static {
         System.loadLibrary("media2_jni");
         native_init();
@@ -1810,12 +1809,10 @@
     public MediaTimestamp getTimestamp() {
         try {
             // TODO: get the timestamp from native side
-            return new MediaTimestamp.Builder()
-                    .setMediaTimestamp(
-                        getCurrentPosition() * 1000L,
-                        System.nanoTime(),
-                        getState() == PLAYER_STATE_PLAYING ? getPlaybackParams().getSpeed() : 0.f)
-                    .build();
+            return new MediaTimestamp(
+                    getCurrentPosition() * 1000L,
+                    System.nanoTime(),
+                    getState() == PLAYER_STATE_PLAYING ? getPlaybackParams().getSpeed() : 0.f);
         } catch (IllegalStateException e) {
             return null;
         }
@@ -2643,13 +2640,11 @@
                             return;
                         }
                         Iterator<Value> in = playerMsg.getValuesList().iterator();
-                        SubtitleData data = new SubtitleData.Builder()
-                                .setSubtitleData(
-                                    in.next().getInt32Value(),  // trackIndex
-                                    in.next().getInt64Value(),  // startTimeUs
-                                    in.next().getInt64Value(),  // durationUs
-                                    in.next().getBytesValue().toByteArray())  // data
-                                .build();
+                        SubtitleData data = new SubtitleData(
+                                in.next().getInt32Value(),  // trackIndex
+                                in.next().getInt64Value(),  // startTimeUs
+                                in.next().getInt64Value(),  // durationUs
+                                in.next().getBytesValue().toByteArray());  // data
                         sendEvent(new EventNotifier() {
                             @Override
                             public void notify(EventCallback callback) {
@@ -2673,11 +2668,9 @@
                             return;
                         }
                         Iterator<Value> in = playerMsg.getValuesList().iterator();
-                        data = new TimedMetaData.Builder()
-                                .setTimedMetaData(
-                                    in.next().getInt64Value(),  // timestampUs
-                                    in.next().getBytesValue().toByteArray())  // metaData
-                                .build();
+                        data = new TimedMetaData(
+                                in.next().getInt64Value(),  // timestampUs
+                                in.next().getBytesValue().toByteArray());  // metaData
                     } else {
                         data = null;
                     }
diff --git a/media/apex/java/android/media/Session2Command.java b/media/apex/java/android/media/Session2Command.java
index 20d6391..6822ea5 100644
--- a/media/apex/java/android/media/Session2Command.java
+++ b/media/apex/java/android/media/Session2Command.java
@@ -32,6 +32,10 @@
  * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
  * {@link #getCustomCommand()} shouldn't be {@code null}.
  * <p>
+ * Refer to the
+ * <a href="{@docRoot}reference/androidx/media2/SessionCommand2.html">AndroidX SessionCommand</a>
+ * class for the list of valid commands.
+ * <p>
  * This API is not generally intended for third party application developers.
  * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
  * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a>
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
index 333cd2d..4aa0b90 100644
--- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.media.AudioAttributes.AttributeUsage;
 import android.media.audiopolicy.AudioMix;
 import android.media.audiopolicy.AudioMixingRule;
 import android.media.projection.MediaProjection;
@@ -41,12 +42,9 @@
  * <pre>
  *     MediaProjection mediaProjection;
  *     // Retrieve a audio capable projection from the MediaProjectionManager
- *     AudioAttributes mediaAttr = new AudioAttributes.Builder()
- *         .setUsage(AudioAttributes.USAGE_MEDIA)
- *         .build();
  *     AudioPlaybackCaptureConfiguration config =
  *              new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)
- *         .addMatchingUsage(mediaAttr)
+ *         .addMatchingUsage(AudioAttributes.USAGE_MEDIA)
  *         .build();
  *     AudioRecord record = new AudioRecord.Builder()
  *         .setAudioPlaybackCaptureConfig(config)
@@ -68,6 +66,15 @@
     }
 
     /**
+     * @return the {@code MediaProjection} used to build this object.
+     * @see {@code Builder.Builder}
+     */
+    public @NonNull MediaProjection getMediaProjection() {
+        return mProjection;
+    }
+
+
+    /**
      * Returns a mix that routes audio back into the app while still playing it from the speakers.
      *
      * @param audioFormat The format in which to capture the audio.
@@ -78,9 +85,6 @@
                 .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK | AudioMix.ROUTE_FLAG_RENDER)
                 .build();
     }
-    MediaProjection getMediaProjection() {
-        return mProjection;
-    }
 
     /** Builder for creating {@link AudioPlaybackCaptureConfiguration} instances. */
     public static final class Builder {
@@ -121,14 +125,13 @@
          * attributes.
          *
          * @throws IllegalStateException if called in conjunction with
-         *     {@link #excludeUsage(AudioAttributes)}.
+         *     {@link #excludeUsage(int)}.
          */
-        public @NonNull Builder addMatchingUsage(@NonNull AudioAttributes audioAttributes) {
-            Preconditions.checkNotNull(audioAttributes);
+        public @NonNull Builder addMatchingUsage(@AttributeUsage int usage) {
             Preconditions.checkState(
                     mUsageMatchType != MATCH_TYPE_EXCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
-            mAudioMixingRuleBuilder
-                    .addRule(audioAttributes, AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
+            mAudioMixingRuleBuilder.addRule(new AudioAttributes.Builder().setUsage(usage).build(),
+                                            AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
             mUsageMatchType = MATCH_TYPE_INCLUSIVE;
             return this;
         }
@@ -156,14 +159,15 @@
          * given attributes.
          *
          * @throws IllegalStateException if called in conjunction with
-         *     {@link #addMatchingUsage(AudioAttributes)}.
+         *     {@link #addMatchingUsage(int)}.
          */
-        public @NonNull Builder excludeUsage(@NonNull AudioAttributes audioAttributes) {
-            Preconditions.checkNotNull(audioAttributes);
+        public @NonNull Builder excludeUsage(@AttributeUsage int usage) {
             Preconditions.checkState(
                     mUsageMatchType != MATCH_TYPE_INCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
-            mAudioMixingRuleBuilder.excludeRule(audioAttributes,
-                    AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
+            mAudioMixingRuleBuilder.excludeRule(new AudioAttributes.Builder()
+                                                    .setUsage(usage)
+                                                    .build(),
+                                                AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
             mUsageMatchType = MATCH_TYPE_EXCLUSIVE;
             return this;
         }
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 2ec9355..a687c14 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.util.Log;
@@ -31,6 +32,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -1332,7 +1334,7 @@
         private Range<Rational> mBlockAspectRatioRange;
         private Range<Long> mBlocksPerSecondRange;
         private Map<Size, Range<Long>> mMeasuredFrameRates;
-        private Vector<PerformancePoint> mPerformancePoints;
+        private List<PerformancePoint> mPerformancePoints;
         private Range<Integer> mFrameRateRange;
 
         private int mBlockWidth;
@@ -1620,45 +1622,136 @@
          * rate.
          */
         public static final class PerformancePoint {
+            private Size mBlockSize; // codec block size in macroblocks
+            private int mWidth; // width in macroblocks
+            private int mHeight; // height in macroblocks
+            private int mMaxFrameRate; // max frames per second
+            private long mMaxMacroBlockRate; // max macro block rate
+
             /**
-             * (Maximum) number of macroblocks in the frame.
+             * Maximum number of macroblocks in the frame.
              *
              * Video frames are conceptually divided into 16-by-16 pixel blocks called macroblocks.
              * Most coding standards operate on these 16-by-16 pixel blocks; thus, codec performance
              * is characterized using such blocks.
+             *
+             * @hide
              */
-            public final int macroBlocks;
+            @TestApi
+            public int getMaxMacroBlocks() {
+                return saturateLongToInt(mWidth * (long)mHeight);
+            }
 
             /**
-             * (Maximum) frame rate in frames per second.
+             * Maximum frame rate in frames per second.
+             *
+             * @hide
              */
-            public final int frameRate;
+            @TestApi
+            public int getMaxFrameRate() {
+                return mMaxFrameRate;
+            }
 
             /**
-             * (Maximum) number of macroblocks processed per second.
+             * Maximum number of macroblocks processed per second.
+             *
+             * @hide
              */
-            public final long macroBlockRate;
+            @TestApi
+            public long getMaxMacroBlockRate() {
+                return mMaxMacroBlockRate;
+            }
 
-            /* package private */
-            PerformancePoint(int width_, int height_, int frameRate_, int maxFrameRate_) {
-                macroBlocks = saturateLongToInt(
-                        ((Math.max(1, (long)width_) + 15) / 16)
-                                * ((Math.max(1, (long)height_) + 15) / 16));
-                frameRate = Math.max(1, frameRate_);
-                macroBlockRate = Math.max(maxFrameRate_, frameRate) * macroBlocks;
+            /** Convert to a debug string */
+            public String toString() {
+                int blockWidth = 16 * mBlockSize.getWidth();
+                int blockHeight = 16 * mBlockSize.getHeight();
+                int origRate = (int)Utils.divUp(mMaxMacroBlockRate, getMaxMacroBlocks());
+                String info = (mWidth * 16) + "x" + (mHeight * 16) + "@" + origRate;
+                if (origRate < mMaxFrameRate) {
+                    info += ", max " + mMaxFrameRate + "fps";
+                }
+                if (blockWidth > 16 || blockHeight > 16) {
+                    info += ", " + blockWidth + "x" + blockHeight + " blocks";
+                }
+                return "PerformancePoint(" + info + ")";
+            }
+
+            /**
+             * Create a detailed performance point with custom max frame rate and macroblock size.
+             *
+             * @param width  frame width in pixels
+             * @param height frame height in pixels
+             * @param frameRate frames per second for frame width and height
+             * @param maxFrameRate maximum frames per second for any frame size
+             * @param blockSize block size for codec implementation. Must be powers of two in both
+             *        width and height.
+             *
+             * @throws IllegalArgumentException if the blockSize dimensions are not powers of two.
+             *
+             * @hide
+             */
+            @TestApi
+            public PerformancePoint(
+                    int width, int height, int frameRate, int maxFrameRate,
+                    @NonNull Size blockSize) {
+                checkPowerOfTwo(blockSize.getWidth(), "block width");
+                checkPowerOfTwo(blockSize.getHeight(), "block height");
+
+                mBlockSize = new Size(Utils.divUp(blockSize.getWidth(), 16),
+                                      Utils.divUp(blockSize.getHeight(), 16));
+                // these are guaranteed not to overflow as we decimate by 16
+                mWidth = (int)(Utils.divUp(Math.max(1L, width),
+                                           Math.max(blockSize.getWidth(), 16))
+                               * mBlockSize.getWidth());
+                mHeight = (int)(Utils.divUp(Math.max(1L, height),
+                                            Math.max(blockSize.getHeight(), 16))
+                                * mBlockSize.getHeight());
+                mMaxFrameRate = Math.max(1, Math.max(frameRate, maxFrameRate));
+                mMaxMacroBlockRate = Math.max(1, frameRate) * getMaxMacroBlocks();
+                Log.i("PP", "Created " + this);
+            }
+
+            /**
+             * Convert a performance point to a larger blocksize.
+             *
+             * @param pp performance point
+             * @param blockSize block size for codec implementation
+             *
+             * @hide
+             */
+            @TestApi
+            public PerformancePoint(@NonNull PerformancePoint pp, @NonNull Size newBlockSize) {
+                this(
+                        pp.mWidth * 16, pp.mHeight * 16,
+                        // guaranteed not to overflow as these were multiplied at construction
+                        (int)Utils.divUp(pp.mMaxMacroBlockRate, pp.getMaxMacroBlocks()),
+                        pp.mMaxFrameRate,
+                        new Size(Math.max(newBlockSize.getWidth(), pp.mBlockSize.getWidth() * 16),
+                                 Math.max(newBlockSize.getHeight(), pp.mBlockSize.getHeight() * 16))
+                );
+                /*
+                // these are guaranteed not to overflow as size * blockSize is decimated by 16
+                width = align(pp.width * pp.blockSize.getWidth(), blockSize.getWidth());
+                height = align(pp.height * pp.blockSize.getHeight(), blockSize.getHeight());
+                frameRate = pp.frameRate;
+                macroBlockRate = align(pp.macroBlockRate, blockSize.getWidth * blockSize.getHeight());
+                */
+                Log.i("PP", " from " + pp + " and " + newBlockSize);
             }
 
             /**
              * Create a performance point for a given frame size and frame rate.
              *
-             * @param width_ width of the frame in pixels
-             * @param height_ height of the frame in pixels
-             * @param frameRate_ frame rate in frames per second
+             * @param width width of the frame in pixels
+             * @param height height of the frame in pixels
+             * @param frameRate frame rate in frames per second
              */
-            public PerformancePoint(int width_, int height_, int frameRate_) {
-                this(width_, height_, frameRate_, frameRate_ /* maxFrameRate */);
+            public PerformancePoint(int width, int height, int frameRate) {
+                this(width, height, frameRate, frameRate /* maxFrameRate */, new Size(16, 16));
             }
 
+            /** Saturates a long value to int */
             private int saturateLongToInt(long value) {
                 if (value < Integer.MIN_VALUE) {
                     return Integer.MIN_VALUE;
@@ -1669,6 +1762,19 @@
                 }
             }
 
+            /* This method may overflow */
+            private int align(int value, int alignment) {
+                return Utils.divUp(value, alignment) * alignment;
+            }
+
+            /** Checks that value is a power of two. */
+            private void checkPowerOfTwo2(int value, @NonNull String description) {
+                if (value == 0 || (value & (value - 1)) != 0) {
+                    throw new IllegalArgumentException(
+                            description + " (" + value + ") must be a power of 2");
+                }
+            }
+
             /**
              * Checks whether the performance point covers a media format.
              *
@@ -1680,7 +1786,7 @@
                 PerformancePoint other = new PerformancePoint(
                         format.getInteger(MediaFormat.KEY_WIDTH, 0),
                         format.getInteger(MediaFormat.KEY_HEIGHT, 0),
-                        // safely convert ceil(double) to int through float case and Math.round
+                        // safely convert ceil(double) to int through float cast and Math.round
                         Math.round((float)(
                                 Math.ceil(format.getNumber(MediaFormat.KEY_FRAME_RATE, 0)
                                         .doubleValue()))));
@@ -1690,7 +1796,7 @@
             /**
              * Checks whether the performance point covers another performance point. Use this
              * method to determine if a performance point advertised by a codec covers the
-             * performance point required. This method can also be used for lose ordering as this
+             * performance point required. This method can also be used for loose ordering as this
              * method is transitive.
              *
              * @param other other performance point considered
@@ -1698,91 +1804,139 @@
              * @return {@code true} if the performance point covers the other.
              */
             public boolean covers(@NonNull PerformancePoint other) {
-                return (macroBlocks >= other.macroBlocks
-                        && frameRate >= other.frameRate
-                        && macroBlockRate >= other.macroBlockRate);
+                // convert performance points to common block size
+                Size commonSize = getCommonBlockSize(other);
+                PerformancePoint aligned = new PerformancePoint(this, commonSize);
+                PerformancePoint otherAligned = new PerformancePoint(other, commonSize);
+
+                return (aligned.getMaxMacroBlocks() >= otherAligned.getMaxMacroBlocks()
+                        && aligned.mMaxFrameRate >= otherAligned.mMaxFrameRate
+                        && aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate);
             }
 
+            private @NonNull Size getCommonBlockSize(@NonNull PerformancePoint other) {
+                return new Size(
+                        Math.max(mBlockSize.getWidth(), other.mBlockSize.getWidth()) * 16,
+                        Math.max(mBlockSize.getHeight(), other.mBlockSize.getHeight()) * 16);
+            }
 
             @Override
             public boolean equals(Object o) {
                 if (o instanceof PerformancePoint) {
+                    // convert performance points to common block size
                     PerformancePoint other = (PerformancePoint)o;
-                    return (macroBlocks == other.macroBlocks
-                            && frameRate == other.frameRate
-                            && macroBlockRate == other.macroBlockRate);
+                    Size commonSize = getCommonBlockSize(other);
+                    PerformancePoint aligned = new PerformancePoint(this, commonSize);
+                    PerformancePoint otherAligned = new PerformancePoint(other, commonSize);
+
+                    return (aligned.getMaxMacroBlocks() == otherAligned.getMaxMacroBlocks()
+                            && aligned.mMaxFrameRate == otherAligned.mMaxFrameRate
+                            && aligned.mMaxMacroBlockRate == otherAligned.mMaxMacroBlockRate);
                 }
                 return false;
             }
 
             /** 480p 24fps */
+            @NonNull
             public static final PerformancePoint SD_24 = new PerformancePoint(720, 480, 24);
             /** 576p 25fps */
+            @NonNull
             public static final PerformancePoint SD_25 = new PerformancePoint(720, 576, 25);
             /** 480p 30fps */
+            @NonNull
             public static final PerformancePoint SD_30 = new PerformancePoint(720, 480, 30);
             /** 480p 48fps */
+            @NonNull
             public static final PerformancePoint SD_48 = new PerformancePoint(720, 480, 48);
             /** 576p 50fps */
+            @NonNull
             public static final PerformancePoint SD_50 = new PerformancePoint(720, 576, 50);
             /** 480p 60fps */
+            @NonNull
             public static final PerformancePoint SD_60 = new PerformancePoint(720, 480, 60);
 
             /** 720p 24fps */
+            @NonNull
             public static final PerformancePoint HD_24 = new PerformancePoint(1280, 720, 24);
             /** 720p 25fps */
+            @NonNull
             public static final PerformancePoint HD_25 = new PerformancePoint(1280, 720, 25);
             /** 720p 30fps */
+            @NonNull
             public static final PerformancePoint HD_30 = new PerformancePoint(1280, 720, 30);
             /** 720p 50fps */
+            @NonNull
             public static final PerformancePoint HD_50 = new PerformancePoint(1280, 720, 50);
             /** 720p 60fps */
+            @NonNull
             public static final PerformancePoint HD_60 = new PerformancePoint(1280, 720, 60);
             /** 720p 100fps */
+            @NonNull
             public static final PerformancePoint HD_100 = new PerformancePoint(1280, 720, 100);
             /** 720p 120fps */
+            @NonNull
             public static final PerformancePoint HD_120 = new PerformancePoint(1280, 720, 120);
             /** 720p 200fps */
+            @NonNull
             public static final PerformancePoint HD_200 = new PerformancePoint(1280, 720, 200);
             /** 720p 240fps */
+            @NonNull
             public static final PerformancePoint HD_240 = new PerformancePoint(1280, 720, 240);
 
             /** 1080p 24fps */
+            @NonNull
             public static final PerformancePoint FHD_24 = new PerformancePoint(1920, 1080, 24);
             /** 1080p 25fps */
+            @NonNull
             public static final PerformancePoint FHD_25 = new PerformancePoint(1920, 1080, 25);
             /** 1080p 30fps */
+            @NonNull
             public static final PerformancePoint FHD_30 = new PerformancePoint(1920, 1080, 30);
             /** 1080p 50fps */
+            @NonNull
             public static final PerformancePoint FHD_50 = new PerformancePoint(1920, 1080, 50);
             /** 1080p 60fps */
+            @NonNull
             public static final PerformancePoint FHD_60 = new PerformancePoint(1920, 1080, 60);
             /** 1080p 100fps */
+            @NonNull
             public static final PerformancePoint FHD_100 = new PerformancePoint(1920, 1080, 100);
             /** 1080p 120fps */
+            @NonNull
             public static final PerformancePoint FHD_120 = new PerformancePoint(1920, 1080, 120);
             /** 1080p 200fps */
+            @NonNull
             public static final PerformancePoint FHD_200 = new PerformancePoint(1920, 1080, 200);
             /** 1080p 240fps */
+            @NonNull
             public static final PerformancePoint FHD_240 = new PerformancePoint(1920, 1080, 240);
 
             /** 2160p 24fps */
+            @NonNull
             public static final PerformancePoint UHD_24 = new PerformancePoint(3840, 2160, 24);
             /** 2160p 25fps */
+            @NonNull
             public static final PerformancePoint UHD_25 = new PerformancePoint(3840, 2160, 25);
             /** 2160p 30fps */
+            @NonNull
             public static final PerformancePoint UHD_30 = new PerformancePoint(3840, 2160, 30);
             /** 2160p 50fps */
+            @NonNull
             public static final PerformancePoint UHD_50 = new PerformancePoint(3840, 2160, 50);
             /** 2160p 60fps */
+            @NonNull
             public static final PerformancePoint UHD_60 = new PerformancePoint(3840, 2160, 60);
             /** 2160p 100fps */
+            @NonNull
             public static final PerformancePoint UHD_100 = new PerformancePoint(3840, 2160, 100);
             /** 2160p 120fps */
+            @NonNull
             public static final PerformancePoint UHD_120 = new PerformancePoint(3840, 2160, 120);
             /** 2160p 200fps */
+            @NonNull
             public static final PerformancePoint UHD_200 = new PerformancePoint(3840, 2160, 200);
             /** 2160p 240fps */
+            @NonNull
             public static final PerformancePoint UHD_240 = new PerformancePoint(3840, 2160, 240);
         }
 
@@ -1803,10 +1957,7 @@
          */
         @Nullable
         public List<PerformancePoint> getSupportedPerformancePoints() {
-            if (mPerformancePoints == null) {
-                return null;
-            }
-            return new ArrayList<PerformancePoint>(mPerformancePoints);
+            return mPerformancePoints;
         }
 
         /**
@@ -1945,7 +2096,7 @@
             mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper();
         }
 
-        private @Nullable Vector<PerformancePoint> getPerformancePoints(Map<String, Object> map) {
+        private @Nullable List<PerformancePoint> getPerformancePoints(Map<String, Object> map) {
             Vector<PerformancePoint> ret = new Vector<>();
             final String prefix = "performance-point-";
             Set<String> keys = map.keySet();
@@ -1959,7 +2110,7 @@
                     // This means that component knowingly did not publish performance points.
                     // This is different from when the component forgot to publish performance
                     // points.
-                    return ret;
+                    return Collections.unmodifiableList(ret);
                 }
                 String[] temp = key.split("-");
                 if (temp.length != 4) {
@@ -1974,23 +2125,32 @@
                 if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
                     continue;
                 }
-                ret.add(new PerformancePoint(
+                PerformancePoint given = new PerformancePoint(
                         size.getWidth(), size.getHeight(), range.getLower().intValue(),
-                        range.getUpper().intValue()));
+                        range.getUpper().intValue(), new Size(mBlockWidth, mBlockHeight));
+                PerformancePoint rotated = new PerformancePoint(
+                        size.getHeight(), size.getWidth(), range.getLower().intValue(),
+                        range.getUpper().intValue(), new Size(mBlockWidth, mBlockHeight));
+                ret.add(given);
+                if (!given.covers(rotated)) {
+                    ret.add(rotated);
+                }
             }
+
             // check if the component specified no performance point indication
             if (ret.size() == 0) {
                 return null;
             }
 
             // sort reversed by area first, then by frame rate
-            ret.sort((a, b) -> -((a.macroBlocks != b.macroBlocks) ?
-                                        (a.macroBlocks < b.macroBlocks ? -1 : 1) :
-                                (a.macroBlockRate != b.macroBlockRate) ?
-                                        (a.macroBlockRate < b.macroBlockRate ? -1 : 1) :
-                                (a.frameRate != b.frameRate) ?
-                                        (a.frameRate < b.frameRate ? -1 : 1) : 0));
-            return ret;
+            ret.sort((a, b) ->
+                     -((a.getMaxMacroBlocks() != b.getMaxMacroBlocks()) ?
+                               (a.getMaxMacroBlocks() < b.getMaxMacroBlocks() ? -1 : 1) :
+                       (a.getMaxMacroBlockRate() != b.getMaxMacroBlockRate()) ?
+                               (a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) :
+                       (a.getMaxFrameRate() != b.getMaxFrameRate()) ?
+                               (a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0));
+            return Collections.unmodifiableList(ret);
         }
 
         private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) {
@@ -3404,14 +3564,29 @@
 
         public static final int VP8ProfileMain = 0x01;
 
+        /** VP9 Profile 0 4:2:0 8-bit */
         public static final int VP9Profile0 = 0x01;
+
+        /** VP9 Profile 1 4:2:2 8-bit */
         public static final int VP9Profile1 = 0x02;
+
+        /** VP9 Profile 2 4:2:0 10-bit */
         public static final int VP9Profile2 = 0x04;
+
+        /** VP9 Profile 3 4:2:2 10-bit */
         public static final int VP9Profile3 = 0x08;
+
         // HDR profiles also support passing HDR metadata
+        /** VP9 Profile 2 4:2:0 10-bit HDR */
         public static final int VP9Profile2HDR = 0x1000;
+
+        /** VP9 Profile 3 4:2:2 10-bit HDR */
         public static final int VP9Profile3HDR = 0x2000;
+
+        /** VP9 Profile 2 4:2:0 10-bit HDR10Plus */
         public static final int VP9Profile2HDR10Plus = 0x4000;
+
+        /** VP9 Profile 3 4:2:2 10-bit HDR10Plus */
         public static final int VP9Profile3HDR10Plus = 0x8000;
 
         public static final int VP9Level1  = 0x1;
@@ -3489,35 +3664,34 @@
         public static final int DolbyVisionLevelUhd48   = 0x80;
         public static final int DolbyVisionLevelUhd60   = 0x100;
 
-        // Profiles and levels for AV1 Codec, corresponding to the
-        // definitions in
+        // Profiles and levels for AV1 Codec, corresponding to the definitions in
         // "AV1 Bitstream & Decoding Process Specification", Annex A
-        // found at
-        // https://aomedia.org/av1-bitstream-and-decoding-process-specification/
+        // found at https://aomedia.org/av1-bitstream-and-decoding-process-specification/
 
         /**
-         * AV1 Main profile.
+         * AV1 Main profile 4:2:0 8-bit
+         *
          * See definition in
-         * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a>
+         * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/">AV1 Specification</a>
          * Annex A.
          */
-        public static final int AV1Profile0     = 0x1;
+        public static final int AV1ProfileMain8   = 0x1;
 
         /**
-         * AV1 High profile.
+         * AV1 Main profile 4:2:0 10-bit
+         *
          * See definition in
-         * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a>
+         * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/">AV1 Specification</a>
          * Annex A.
          */
-        public static final int AV1Profile1     = 0x2;
+        public static final int AV1ProfileMain10  = 0x2;
 
-        /**
-         * AV1 Professional profile.
-         * See definition in
-         * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a>
-         * Annex A.
-         */
-        public static final int AV1Profile2     = 0x4;
+
+        /** AV1 Main profile 4:2:0 10-bit with HDR10. */
+        public static final int AV1ProfileMain10HDR10 = 0x1000;
+
+        /** AV1 Main profile 4:2:0 10-bit with HDR10Plus. */
+        public static final int AV1ProfileMain10HDR10Plus = 0x2000;
 
         public static final int AV1Level2       = 0x1;
         public static final int AV1Level21      = 0x2;
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 0e4fa14..8686c59 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1047,6 +1047,15 @@
      */
     public static final String KEY_CA_PRIVATE_DATA = "ca-private-data";
 
+    /**
+     * A key describing the maximum number of B frames between I or P frames,
+     * to be used by a video encoder.
+     * The associated value is an integer. The default value is 0, which means
+     * that no B frames are allowed. Note that non-zero value does not guarantee
+     * B frames; it's up to the encoder to decide.
+     */
+    public static final String KEY_MAX_BFRAMES = "max-bframes";
+
     /* package private */ MediaFormat(@NonNull Map<String, Object> map) {
         mMap = map;
     }
diff --git a/media/java/android/media/MediaTimestamp.java b/media/java/android/media/MediaTimestamp.java
index da3362a..0777ba3 100644
--- a/media/java/android/media/MediaTimestamp.java
+++ b/media/java/android/media/MediaTimestamp.java
@@ -16,8 +16,7 @@
 
 package android.media;
 
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
+import android.annotation.FloatRange;
 
 /**
  * An immutable object that represents the linear correlation between the media time
@@ -76,6 +75,7 @@
      * greater than 1.0 if media clock is faster than the system clock;
      * less than 1.0 if media clock is slower than the system clock.
      */
+    @FloatRange(from = 0.0f, to = Float.MAX_VALUE)
     public float getMediaClockRate() {
         return clockRate;
     }
@@ -87,11 +87,19 @@
     /** @hide - accessor shorthand */
     public final float clockRate;
 
-    /** @hide */
-    MediaTimestamp(long mediaUs, long systemNs, float rate) {
-        mediaTimeUs = mediaUs;
-        nanoTime = systemNs;
-        clockRate = rate;
+    /**
+     * Constructor.
+     *
+     * @param mediaTimeUs the media time of the anchor in microseconds
+     * @param nanoTimeNs the {@link java.lang.System#nanoTime system time} corresponding to the
+     *                  media time in nanoseconds.
+     * @param clockRate the rate of the media clock in relation to the system time.
+     */
+    public MediaTimestamp(long mediaTimeUs, long nanoTimeNs,
+            @FloatRange(from = 0.0f, to = Float.MAX_VALUE) float clockRate) {
+        this.mediaTimeUs = mediaTimeUs;
+        this.nanoTime = nanoTimeNs;
+        this.clockRate = clockRate;
     }
 
     /** @hide */
@@ -120,71 +128,4 @@
                 + " clockRate=" + clockRate
                 + "}";
     }
-
-    /**
-     * Builder class for {@link MediaTimestamp} objects.
-     * <p> Here is an example where <code>Builder</code> is used to define the
-     * {@link MediaTimestamp}:
-     *
-     * <pre class="prettyprint">
-     * MediaTimestamp mts = new MediaTimestamp.Builder()
-     *         .setMediaTimestamp(mediaTime, systemTime, rate)
-     *         .build();
-     * </pre>
-     * @hide
-     */
-    @SystemApi
-    public static final class Builder {
-        long mMediaTimeUs;
-        long mNanoTime;
-        float mClockRate = 1.0f;
-
-        /**
-         * Constructs a new Builder with the defaults.
-         */
-        public Builder() {
-        }
-
-        /**
-         * Constructs a new Builder from a given {@link MediaTimestamp} instance
-         * @param mts the {@link MediaTimestamp} object whose data will be reused
-         * in the new Builder.
-         */
-        public Builder(@NonNull MediaTimestamp mts) {
-            if (mts == null) {
-                throw new IllegalArgumentException("null MediaTimestamp is not allowed");
-            }
-            mMediaTimeUs = mts.mediaTimeUs;
-            mNanoTime = mts.nanoTime;
-            mClockRate = mts.clockRate;
-        }
-
-        /**
-         * Combines all of the fields that have been set and return a new
-         * {@link MediaTimestamp} object.
-         *
-         * @return a new {@link MediaTimestamp} object
-         */
-        public @NonNull MediaTimestamp build() {
-            return new MediaTimestamp(mMediaTimeUs, mNanoTime, mClockRate);
-        }
-
-        /**
-         * Sets the info of media timestamp.
-         *
-         * @param mediaTimeUs the media time of the anchor in microseconds
-         * @param nanoTime the {@link java.lang.System#nanoTime system time} corresponding to
-         *     the media time in nanoseconds.
-         * @param clockRate the rate of the media clock in relation to the system time.
-         * @return the same Builder instance.
-         */
-        public @NonNull Builder setMediaTimestamp(
-                long mediaTimeUs, long nanoTime, float clockRate) {
-            mMediaTimeUs = mediaTimeUs;
-            mNanoTime = nanoTime;
-            mClockRate = clockRate;
-
-            return this;
-        }
-    }
 }
diff --git a/media/java/android/media/SubtitleData.java b/media/java/android/media/SubtitleData.java
index 2c6c61f..2ef6982 100644
--- a/media/java/android/media/SubtitleData.java
+++ b/media/java/android/media/SubtitleData.java
@@ -17,11 +17,8 @@
 package android.media;
 
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 
-import java.util.Arrays;
-
 /**
  * Class encapsulating subtitle data, as received through the
  * {@link MediaPlayer.OnSubtitleDataListener} interface.
@@ -82,12 +79,23 @@
         }
     }
 
-    /** @hide */
+    /**
+     * Constructor.
+     *
+     * @param trackIndex the index of the media player track which contains this subtitle data.
+     * @param startTimeUs the start time in microsecond for the subtitle data
+     * @param durationUs the duration in microsecond for the subtitle data
+     * @param data the data array for the subtitle data. It should not be null.
+     *            No data copying is made.
+     */
     public SubtitleData(int trackIndex, long startTimeUs, long durationUs, @NonNull byte[] data) {
+        if (data == null) {
+            throw new IllegalArgumentException("null data is not allowed");
+        }
         mTrackIndex = trackIndex;
         mStartTimeUs = startTimeUs;
         mDurationUs = durationUs;
-        mData = (data != null ? data : new byte[0]);
+        mData = data;
     }
 
     /**
@@ -141,80 +149,4 @@
 
         return true;
     }
-
-    /**
-     * Builder class for {@link SubtitleData} objects.
-     * <p> Here is an example where <code>Builder</code> is used to define the
-     * {@link SubtitleData}:
-     *
-     * <pre class="prettyprint">
-     * SubtitleData sd = new SubtitleData.Builder()
-     *         .setSubtitleData(trackIndex, startTime, duration, data)
-     *         .build();
-     * </pre>
-     * @hide
-     */
-    @SystemApi
-    public static final class Builder {
-        private int mTrackIndex;
-        private long mStartTimeUs;
-        private long mDurationUs;
-        private byte[] mData = new byte[0];
-
-        /**
-         * Constructs a new Builder with the defaults.
-         */
-        public Builder() {
-        }
-
-        /**
-         * Constructs a new Builder from a given {@link SubtitleData} instance
-         * @param sd the {@link SubtitleData} object whose data will be reused
-         * in the new Builder. It should not be null. The data array is copied.
-         */
-        public Builder(@NonNull SubtitleData sd) {
-            if (sd == null) {
-                throw new IllegalArgumentException("null SubtitleData is not allowed");
-            }
-            mTrackIndex = sd.mTrackIndex;
-            mStartTimeUs = sd.mStartTimeUs;
-            mDurationUs = sd.mDurationUs;
-            if (sd.mData != null) {
-                mData = Arrays.copyOf(sd.mData, sd.mData.length);
-            }
-        }
-
-        /**
-         * Combines all of the fields that have been set and return a new
-         * {@link SubtitleData} object. <code>IllegalStateException</code> will be
-         * thrown if there is conflict between fields.
-         *
-         * @return a new {@link SubtitleData} object
-         */
-        public @NonNull SubtitleData build() {
-            return new SubtitleData(mTrackIndex, mStartTimeUs, mDurationUs, mData);
-        }
-
-        /**
-         * Sets the info of subtitle data.
-         *
-         * @param trackIndex the index of the media player track which contains this subtitle data.
-         * @param startTimeUs the start time in microsecond for the subtile data
-         * @param durationUs the duration in microsecond for the subtile data
-         * @param data the data array for the subtile data. It should not be null.
-         *     No data copying is made.
-         * @return the same Builder instance.
-         */
-        public @NonNull Builder setSubtitleData(
-                int trackIndex, long startTimeUs, long durationUs, @NonNull byte[] data) {
-            if (data == null) {
-                throw new IllegalArgumentException("null data is not allowed");
-            }
-            mTrackIndex = trackIndex;
-            mStartTimeUs = startTimeUs;
-            mDurationUs = durationUs;
-            mData = data;
-            return this;
-        }
-    }
 }
diff --git a/media/java/android/media/TimedMetaData.java b/media/java/android/media/TimedMetaData.java
index 990760c..b99b30c 100644
--- a/media/java/android/media/TimedMetaData.java
+++ b/media/java/android/media/TimedMetaData.java
@@ -17,11 +17,8 @@
 package android.media;
 
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 
-import java.util.Arrays;
-
 /**
  * Class that embodies one timed metadata access unit, including
  *
@@ -52,7 +49,11 @@
     }
 
     /**
-     * @hide
+     * Constructor.
+     *
+     * @param timestampUs the timestamp in microsecond for the timed metadata
+     * @param metaData the metadata array for the timed metadata. No data copying is made.
+     *     It should not be null.
      */
     public TimedMetaData(long timestampUs, @NonNull byte[] metaData) {
         if (metaData == null) {
@@ -90,71 +91,4 @@
 
         return true;
     }
-
-    /**
-     * Builder class for {@link TimedMetaData} objects.
-     * <p> Here is an example where <code>Builder</code> is used to define the
-     * {@link TimedMetaData}:
-     *
-     * <pre class="prettyprint">
-     * TimedMetaData tmd = new TimedMetaData.Builder()
-     *         .setTimedMetaData(timestamp, metaData)
-     *         .build();
-     * </pre>
-     * @hide
-     */
-    @SystemApi
-    public static final class Builder {
-        private long mTimestampUs;
-        private byte[] mMetaData = new byte[0];
-
-        /**
-         * Constructs a new Builder with the defaults.
-         */
-        public Builder() {
-        }
-
-        /**
-         * Constructs a new Builder from a given {@link TimedMetaData} instance
-         * @param tmd the {@link TimedMetaData} object whose data will be reused
-         * in the new Builder. It should not be null. The metadata array is copied.
-         */
-        public Builder(@NonNull TimedMetaData tmd) {
-            if (tmd == null) {
-                throw new IllegalArgumentException("null TimedMetaData is not allowed");
-            }
-            mTimestampUs = tmd.mTimestampUs;
-            if (tmd.mMetaData != null) {
-                mMetaData = Arrays.copyOf(tmd.mMetaData, tmd.mMetaData.length);
-            }
-        }
-
-        /**
-         * Combines all of the fields that have been set and return a new
-         * {@link TimedMetaData} object. <code>IllegalStateException</code> will be
-         * thrown if there is conflict between fields.
-         *
-         * @return a new {@link TimedMetaData} object
-         */
-        public @NonNull TimedMetaData build() {
-            return new TimedMetaData(mTimestampUs, mMetaData);
-        }
-
-        /**
-         * Sets the info of timed metadata.
-         *
-         * @param timestamp the timestamp in microsecond for the timed metadata
-         * @param metaData the metadata array for the timed metadata. No data copying is made.
-         *     It should not be null.
-         * @return the same Builder instance.
-         */
-        public @NonNull Builder setTimedMetaData(long timestamp, @NonNull byte[] metaData) {
-            if (metaData == null) {
-                throw new IllegalArgumentException("null metaData is not allowed");
-            }
-            mTimestampUs = timestamp;
-            mMetaData = metaData;
-            return this;
-        }
-    }
 }
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 6c48cdb..d41f416 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -409,6 +409,10 @@
                 final int match_rule = rule & ~RULE_EXCLUSION_MASK;
                 while (crIterator.hasNext()) {
                     final AudioMixMatchCriterion criterion = crIterator.next();
+
+                    if ((criterion.mRule & ~RULE_EXCLUSION_MASK) != match_rule) {
+                        continue; // The two rules are not of the same type
+                    }
                     switch (match_rule) {
                         case RULE_MATCH_ATTRIBUTE_USAGE:
                             // "usage"-based rule
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index a288d010..bda5743 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -52,6 +52,7 @@
 import android.webkit.CookieManager;
 import android.webkit.SslErrorHandler;
 import android.webkit.WebChromeClient;
+import android.webkit.WebResourceRequest;
 import android.webkit.WebSettings;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
@@ -409,8 +410,7 @@
                     TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
                     getResources().getDisplayMetrics());
         private int mPagesLoaded;
-        // the host of the page that this webview is currently loading. Can be null when undefined.
-        private String mHostname;
+        private String mMainFrameUrl;
 
         // If we haven't finished cleaning up the history, don't allow going back.
         public boolean allowBack() {
@@ -436,7 +436,6 @@
             }
             final URL url = makeURL(urlString);
             Log.d(TAG, "onPageStarted: " + sanitizeURL(url));
-            mHostname = host(url);
             // For internally generated pages, leave URL bar listing prior URL as this is the URL
             // the page refers to.
             if (!urlString.startsWith(INTERNAL_ASSETS)) {
@@ -480,17 +479,28 @@
             return Integer.toString((int)dp) + "px";
         }
 
+        // Check if webview is trying to load the main frame and record its url.
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
+            if (request.isForMainFrame()) {
+                mMainFrameUrl = request.getUrl().toString();
+            }
+            return false;
+        }
+
         // A web page consisting of a large broken lock icon to indicate SSL failure.
 
         @Override
         public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
-            final URL url = makeURL(error.getUrl());
-            final String host = host(url);
+            final URL errorUrl = makeURL(error.getUrl());
+            final URL mainFrameUrl = makeURL(mMainFrameUrl);
             Log.d(TAG, String.format("SSL error: %s, url: %s, certificate: %s",
-                    sslErrorName(error), sanitizeURL(url), error.getCertificate()));
-            if (url == null || !Objects.equals(host, mHostname)) {
-                // Ignore ssl errors for resources coming from a different hostname than the page
-                // that we are currently loading, and only cancel the request.
+                    sslErrorName(error), sanitizeURL(errorUrl), error.getCertificate()));
+            if (errorUrl == null
+                    // Ignore SSL errors from resources by comparing the main frame url with SSL
+                    // error url.
+                    || !errorUrl.equals(mainFrameUrl)) {
+                Log.d(TAG, "onReceivedSslError: mMainFrameUrl = " + mMainFrameUrl);
                 handler.cancel();
                 return;
             }
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index 335d951..19e9108 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -277,9 +277,9 @@
         }
 
         @Override
-        public void notifyAcceptPartialConnectivity() {
+        public void setAcceptPartialConnectivity() {
             checkNetworkStackCallingPermission();
-            mNm.notifyAcceptPartialConnectivity();
+            mNm.setAcceptPartialConnectivity();
         }
 
         @Override
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 9d91487..73b203c 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -319,7 +319,8 @@
     private final DnsStallDetector mDnsStallDetector;
     private long mLastProbeTime;
     // Set to true if data stall is suspected and reset to false after metrics are sent to statsd.
-    private boolean mCollectDataStallMetrics = false;
+    private boolean mCollectDataStallMetrics;
+    private boolean mAcceptPartialConnectivity;
 
     public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
             SharedLog validationLog) {
@@ -386,10 +387,11 @@
     }
 
     /**
-     * ConnectivityService notifies NetworkMonitor that the user accepts partial connectivity and
-     * NetworkMonitor should ignore the https probe.
+     * ConnectivityService notifies NetworkMonitor that the user already accepted partial
+     * connectivity previously, so NetworkMonitor can validate the network even if it has partial
+     * connectivity.
      */
-    public void notifyAcceptPartialConnectivity() {
+    public void setAcceptPartialConnectivity() {
         sendMessage(EVENT_ACCEPT_PARTIAL_CONNECTIVITY);
     }
 
@@ -651,9 +653,11 @@
                 case EVENT_DNS_NOTIFICATION:
                     mDnsStallDetector.accumulateConsecutiveDnsTimeoutCount(message.arg1);
                     break;
+                // Set mAcceptPartialConnectivity to true and if network start evaluating or
+                // re-evaluating and get the result of partial connectivity, ProbingState will
+                // disable HTTPS probe and transition to EvaluatingPrivateDnsState.
                 case EVENT_ACCEPT_PARTIAL_CONNECTIVITY:
-                    mUseHttps = false;
-                    transitionTo(mEvaluatingPrivateDnsState);
+                    mAcceptPartialConnectivity = true;
                     break;
                 default:
                     break;
@@ -849,6 +853,14 @@
                     // ignore any re-evaluation requests. After, restart the
                     // evaluation process via EvaluatingState#enter.
                     return (mEvaluateAttempts < IGNORE_REEVALUATE_ATTEMPTS) ? HANDLED : NOT_HANDLED;
+                // Disable HTTPS probe and transition to EvaluatingPrivateDnsState because:
+                // 1. Network is connected and finish the network validation.
+                // 2. NetworkMonitor detects network is partial connectivity and user accepts it.
+                case EVENT_ACCEPT_PARTIAL_CONNECTIVITY:
+                    mAcceptPartialConnectivity = true;
+                    mUseHttps = false;
+                    transitionTo(mEvaluatingPrivateDnsState);
+                    return HANDLED;
                 default:
                     return NOT_HANDLED;
             }
@@ -1081,7 +1093,12 @@
                         logNetworkEvent(NetworkEvent.NETWORK_PARTIAL_CONNECTIVITY);
                         notifyNetworkTested(NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY,
                                 probeResult.redirectUrl);
-                        transitionTo(mWaitingForNextProbeState);
+                        if (mAcceptPartialConnectivity) {
+                            mUseHttps = false;
+                            transitionTo(mEvaluatingPrivateDnsState);
+                        } else {
+                            transitionTo(mWaitingForNextProbeState);
+                        }
                     } else {
                         logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
                         notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, probeResult.redirectUrl);
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index d93aef2..d732c4e 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -583,7 +583,7 @@
         verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                 .notifyNetworkTested(NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY, null);
 
-        nm.notifyAcceptPartialConnectivity();
+        nm.setAcceptPartialConnectivity();
         verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                 .notifyNetworkTested(NETWORK_TEST_RESULT_VALID, null);
     }
diff --git a/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml b/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml
index 0eefd4b..7db6014 100644
--- a/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml
+++ b/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml
@@ -31,7 +31,7 @@
     </style>
 
     <style name="AppEntitiesHeader.Text.Summary"
-           parent="@android:style/TextAppearance.Material.Body1">
+           parent="@*android:style/TextAppearance.DeviceDefault.Body1">
         <item name="android:textColor">?android:attr/textColorSecondary</item>
         <item name="android:textSize">14sp</item>
     </style>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index d3dde92..c6a995cb 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -113,6 +113,9 @@
     <!-- Summary for Connected wifi network without internet -->
     <string name="wifi_connected_no_internet">Connected, no internet</string>
 
+    <!-- Summary for connected wifi network with partial internet connectivity [CHAR LIMIT=50] -->
+    <string name="wifi_limited_connection">Limited connection</string>
+
     <!-- Wi-Fi status indicating that the current network is connected, but has no internet access. -->
     <string name="wifi_status_no_internet">No internet</string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 081f8a0..bb8c8a6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -1,7 +1,6 @@
 package com.android.settingslib.bluetooth;
 
 import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -10,7 +9,6 @@
 import androidx.annotation.DrawableRes;
 
 import com.android.settingslib.R;
-import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
 
 import java.util.List;
 
@@ -51,38 +49,29 @@
 
     public static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context,
             CachedBluetoothDevice cachedDevice) {
-        return getBtClassDrawableWithDescription(context, cachedDevice, 1 /* iconScale */);
-    }
-
-    public static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context,
-            CachedBluetoothDevice cachedDevice, float iconScale) {
         BluetoothClass btClass = cachedDevice.getBtClass();
-        final int level = cachedDevice.getBatteryLevel();
         if (btClass != null) {
             switch (btClass.getMajorDeviceClass()) {
                 case BluetoothClass.Device.Major.COMPUTER:
                     return new Pair<>(getBluetoothDrawable(context,
-                            com.android.internal.R.drawable.ic_bt_laptop, level, iconScale),
+                            com.android.internal.R.drawable.ic_bt_laptop),
                             context.getString(R.string.bluetooth_talkback_computer));
 
                 case BluetoothClass.Device.Major.PHONE:
                     return new Pair<>(
                             getBluetoothDrawable(context,
-                                    com.android.internal.R.drawable.ic_phone, level,
-                                    iconScale),
+                                    com.android.internal.R.drawable.ic_phone),
                             context.getString(R.string.bluetooth_talkback_phone));
 
                 case BluetoothClass.Device.Major.PERIPHERAL:
                     return new Pair<>(
-                            getBluetoothDrawable(context, HidProfile.getHidClassDrawable(btClass),
-                                    level, iconScale),
+                            getBluetoothDrawable(context, HidProfile.getHidClassDrawable(btClass)),
                             context.getString(R.string.bluetooth_talkback_input_peripheral));
 
                 case BluetoothClass.Device.Major.IMAGING:
                     return new Pair<>(
                             getBluetoothDrawable(context,
-                                    com.android.internal.R.drawable.ic_settings_print, level,
-                                    iconScale),
+                                    com.android.internal.R.drawable.ic_settings_print),
                             context.getString(R.string.bluetooth_talkback_imaging));
 
                 default:
@@ -94,38 +83,33 @@
         for (LocalBluetoothProfile profile : profiles) {
             int resId = profile.getDrawableResource(btClass);
             if (resId != 0) {
-                return new Pair<>(getBluetoothDrawable(context, resId, level, iconScale), null);
+                return new Pair<>(getBluetoothDrawable(context, resId), null);
             }
         }
         if (btClass != null) {
             if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
                 return new Pair<>(
                         getBluetoothDrawable(context,
-                                com.android.internal.R.drawable.ic_bt_headset_hfp, level,
-                                iconScale),
+                                com.android.internal.R.drawable.ic_bt_headset_hfp),
                         context.getString(R.string.bluetooth_talkback_headset));
             }
             if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
                 return new Pair<>(
                         getBluetoothDrawable(context,
-                                com.android.internal.R.drawable.ic_bt_headphones_a2dp, level,
-                                iconScale),
+                                com.android.internal.R.drawable.ic_bt_headphones_a2dp),
                         context.getString(R.string.bluetooth_talkback_headphone));
             }
         }
         return new Pair<>(
                 getBluetoothDrawable(context,
-                        com.android.internal.R.drawable.ic_settings_bluetooth, level, iconScale),
+                        com.android.internal.R.drawable.ic_settings_bluetooth),
                 context.getString(R.string.bluetooth_talkback_bluetooth));
     }
 
-    public static Drawable getBluetoothDrawable(Context context, @DrawableRes int resId,
-            int batteryLevel, float iconScale) {
-        if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
-            return BluetoothDeviceLayerDrawable.createLayerDrawable(context, resId, batteryLevel,
-                    iconScale);
-        } else {
-            return context.getDrawable(resId);
-        }
+    /**
+     * Get bluetooth drawable by {@code resId}
+     */
+    public static Drawable getBluetoothDrawable(Context context, @DrawableRes int resId) {
+        return context.getDrawable(resId);
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 800c401..3acbcd3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1424,6 +1424,9 @@
                     int id = context.getResources()
                             .getIdentifier("network_available_sign_in", "string", "android");
                     return context.getString(id);
+                } else if (nc.hasCapability(
+                        NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
+                    return context.getString(R.string.wifi_limited_connection);
                 } else if (!nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
                     return context.getString(R.string.wifi_connected_no_internet);
                 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 2ab369c..5352936 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -11,6 +11,7 @@
 package com.android.settingslib.wifi;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 
 import android.content.Context;
@@ -158,6 +159,9 @@
             if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) {
                 statusLabel = mContext.getString(R.string.wifi_status_sign_in_required);
                 return;
+            } else if (networkCapabilities.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
+                statusLabel = mContext.getString(R.string.wifi_limited_connection);
+                return;
             } else if (!networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
                 statusLabel = mContext.getString(R.string.wifi_status_no_internet);
                 return;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index 7a71551..b713e08 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -15,36 +15,55 @@
  */
 package com.android.settingslib.bluetooth;
 
-import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
-import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothClass;
+import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.util.Pair;
 
-import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
-
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
 public class BluetoothUtilsTest {
 
-    @Test
-    public void testGetBluetoothDrawable_noBatteryLevel_returnSimpleDrawable() {
-        final Drawable drawable = BluetoothUtils.getBluetoothDrawable(
-                RuntimeEnvironment.application, com.android.internal.R.drawable.ic_bt_laptop,
-                BluetoothDevice.BATTERY_LEVEL_UNKNOWN, 1 /* iconScale */);
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    private Context mContext;
 
-        assertThat(drawable).isNotInstanceOf(BluetoothDeviceLayerDrawable.class);
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
     }
 
     @Test
-    public void testGetBluetoothDrawable_hasBatteryLevel_returnLayerDrawable() {
-        final Drawable drawable = BluetoothUtils.getBluetoothDrawable(
-                RuntimeEnvironment.application, com.android.internal.R.drawable.ic_bt_laptop,
-                10 /* batteryLevel */, 1 /* iconScale */);
+    public void getBtClassDrawableWithDescription_typePhone_returnPhoneDrawable() {
+        when(mCachedBluetoothDevice.getBtClass().getMajorDeviceClass()).thenReturn(
+                BluetoothClass.Device.Major.PHONE);
+        final Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription(
+                mContext, mCachedBluetoothDevice);
 
-        assertThat(drawable).isInstanceOf(BluetoothDeviceLayerDrawable.class);
+        verify(mContext).getDrawable(com.android.internal.R.drawable.ic_phone);
     }
-}
+
+    @Test
+    public void getBtClassDrawableWithDescription_typeComputer_returnComputerDrawable() {
+        when(mCachedBluetoothDevice.getBtClass().getMajorDeviceClass()).thenReturn(
+                BluetoothClass.Device.Major.COMPUTER);
+        final Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription(
+                mContext, mCachedBluetoothDevice);
+
+        verify(mContext).getDrawable(com.android.internal.R.drawable.ic_bt_laptop);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java
index df4656a..e588b3d 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java
@@ -147,7 +147,7 @@
         // make sValue the default value
         executeShellCommand(
                 "device_config put " + sNamespace + " " + sKey + " " + sValue + " default");
-        // make newValue the current value (as set by a trusted package)
+        // make newValue the current value (as set by a untrusted package)
         executeShellCommand(
                 "device_config put " + sNamespace + " " + sKey + " " + newValue);
         String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
@@ -156,13 +156,7 @@
         // reset values that were set by untrusted packages
         executeShellCommand("device_config reset untrusted_defaults " + sNamespace);
         result = getFromContentProvider(mContentResolver, sNamespace, sKey);
-        // the current value was set by a trusted package, so it's not reset
-        assertEquals(newValue, result);
-
-        // reset values that were set by untrusted or trusted packages
-        executeShellCommand("device_config reset trusted_defaults " + sNamespace);
-        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
-        // the default value has been restored
+        // the current value was set by a untrusted package, so it's reset
         assertEquals(sValue, result);
     }
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d639e5e..441f88c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -86,6 +86,7 @@
     <uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
     <uses-permission android:name="android.permission.DELETE_PACKAGES" />
     <uses-permission android:name="android.permission.MANAGE_ROLLBACKS" />
+    <uses-permission android:name="android.permission.TEST_MANAGE_ROLLBACKS" />
     <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
     <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
@@ -178,6 +179,9 @@
     <!-- Permission needed to run network tests in CTS -->
     <uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" />
 
+    <!-- Permission needed to run keyguard manager tests in CTS -->
+    <uses-permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS" />
+
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
diff --git a/packages/SystemUI/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml
index 6c5c7fa..3d63b7d 100644
--- a/packages/SystemUI/res/layout/screen_record_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_record_dialog.xml
@@ -5,26 +5,25 @@
               android:clipChildren="false"
               android:clipToPadding="false"
               android:gravity="top"
-              android:orientation="vertical">
-
-    <Space
-        android:layout_width="match_parent"
-        android:layout_height="10dp"/>
+              android:orientation="vertical"
+              android:padding="@dimen/global_actions_padding"
+              android:background="@drawable/rounded_bg_full">
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:background="@android:color/white">
+        android:orientation="vertical">
         <CheckBox
             android:id="@+id/checkbox_mic"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:text="@string/screenrecord_mic_label"/>
         <CheckBox
             android:id="@+id/checkbox_taps"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:text="@string/screenrecord_taps_label"/>
         <Button
             android:id="@+id/record_button"
@@ -34,8 +33,4 @@
         />
     </LinearLayout>
 
-    <Space
-        android:layout_width="match_parent"
-        android:layout_height="10dp"/>
-
 </LinearLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index da43391..44fb141 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1069,10 +1069,10 @@
     <string name="battery_saver_notification_action_text">Turn off Battery Saver</string>
 
     <!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
-    <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will start capturing everything on your screen including notifications, passwords, photos, messages and payment information.</string>
+    <string name="media_projection_dialog_text">While recording or casting, <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> can capture any sensitive information, such as audio that you play and your passwords, payment info, photos, and messages.</string>
 
     <!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] -->
-    <string name="media_projection_dialog_title">Allow <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> to record or cast your screen?</string>
+    <string name="media_projection_dialog_title">Exposing sensitive info during casting/recording </string>
 
     <!-- Media projection permission dialog permanent grant check box. [CHAR LIMIT=NONE] -->
     <string name="media_projection_remember_text">Don\'t show again</string>
@@ -2370,12 +2370,29 @@
     <string name="bubbles_deep_link_button_description">Open <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
     <!-- Text used for content description of settings button in the header of expanded bubble
          view. [CHAR_LIMIT=NONE] -->
-    <string name="bubbles_settings_button_description">Open notification settings for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
+    <string name="bubbles_settings_button_description">Settings for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> bubbles</string>
     <!-- Text for asking the user whether bubbles (floating app content) should be enabled for an
          app. [CHAR LIMIT=NONE] -->
-    <string name="bubbles_prompt">Allow bubbles from this app?</string>
+    <string name="bubbles_prompt">Allow bubbles from <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
     <!-- Text used for button allowing user to opt out of bubbles [CHAR LIMIT=20] -->
-    <string name="no_bubbles">Block</string>
+    <string name="no_bubbles">Deny</string>
     <!-- Text used for button allowing user to approve / enable bubbles [CHAR LIMIT=20] -->
     <string name="yes_bubbles">Allow</string>
+    <!-- Text used for the button allowing users to postpone their decision to allow or deny bubbles [CHAR LIMIT=40] -->
+    <string name="ask_me_later_bubbles">Ask me later</string>
+    <!-- Content description when a bubble is focused. [CHAR LIMIT=NONE] -->
+    <string name="bubble_content_description_single"><xliff:g id="notification_title" example="some title">%1$s</xliff:g> from <xliff:g id="app_name" example="YouTube">%2$s</xliff:g></string>
+    <!-- Content description when the stack of bubbles is focused. [CHAR LIMIT=NONE] -->
+    <string name="bubble_content_description_stack"><xliff:g id="notification_title" example="some title">%1$s</xliff:g> from <xliff:g id="app_name" example="YouTube">%2$s</xliff:g> and <xliff:g id="bubble_count" example="4">%3$d</xliff:g> more</string>
+    <!-- Action in accessibility menu to move the stack of bubbles [CHAR LIMIT=20] -->
+    <string name="bubble_accessibility_action_move">Move</string>
+    <!-- Action in accessibility menu to move the stack of bubbles to the top left of the screen. [CHAR LIMIT=30] -->
+    <string name="bubble_accessibility_action_move_top_left">Move top left</string>
+    <!-- Action in accessibility menu to move the stack of bubbles to the top right of the screen. [CHAR LIMIT=30] -->
+    <string name="bubble_accessibility_action_move_top_right">Move top right</string>
+    <!-- Action in accessibility menu to move the stack of bubbles to the bottom left of the screen. [CHAR LIMIT=30]-->
+    <string name="bubble_accessibility_action_move_bottom_left">Move bottom left</string>
+    <!-- Action in accessibility menu to move the stack of bubbles to the bottom right of the screen. [CHAR LIMIT=30]-->
+    <string name="bubble_accessibility_action_move_bottom_right">Move bottom right</string>
+
 </resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 0f71ffb..6b07ed8 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -219,6 +219,7 @@
             IRecentsAnimationRunner runner = null;
             if (animationHandler != null) {
                 runner = new IRecentsAnimationRunner.Stub() {
+                    @Override
                     public void onAnimationStart(IRecentsAnimationController controller,
                             RemoteAnimationTarget[] apps, Rect homeContentInsets,
                             Rect minimizedHomeBounds) {
@@ -230,8 +231,9 @@
                                 homeContentInsets, minimizedHomeBounds);
                     }
 
-                    public void onAnimationCanceled() {
-                        animationHandler.onAnimationCanceled();
+                    @Override
+                    public void onAnimationCanceled(boolean deferredWithScreenshot) {
+                        animationHandler.onAnimationCanceled(deferredWithScreenshot);
                     }
                 };
             }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 9bebb14..1d9105c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -84,4 +84,20 @@
             Log.e(TAG, "Failed to finish recents animation", e);
         }
     }
+
+    public void setCancelWithDeferredScreenshot(boolean screenshot) {
+        try {
+            mAnimationController.setCancelWithDeferredScreenshot(screenshot);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to set cancel with deferred screenshot", e);
+        }
+    }
+
+    public void cleanupScreenshot() {
+        try {
+            mAnimationController.cleanupScreenshot();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to clean up screenshot of recents animation", e);
+        }
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
index a473db1..5850fda 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
@@ -29,5 +29,5 @@
     /**
      * Called when the animation into Recents was canceled. This call is made on the binder thread.
      */
-    void onAnimationCanceled();
-}
\ No newline at end of file
+    void onAnimationCanceled(boolean deferredWithScreenshot);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 0113d05..ed2a6b5 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -19,9 +19,7 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.opengl.GLSurfaceView;
-import android.os.Build;
 import android.service.wallpaper.WallpaperService;
-import android.util.Log;
 import android.view.SurfaceHolder;
 
 import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
@@ -34,15 +32,7 @@
     private static final String TAG = ImageWallpaper.class.getSimpleName();
 
     @Override
-    public void onCreate() {
-        super.onCreate();
-    }
-
-    @Override
     public Engine onCreateEngine() {
-        if (Build.IS_DEBUGGABLE) {
-            Log.v(TAG, "We are using GLEngine");
-        }
         return new GLEngine(this);
     }
 
@@ -72,8 +62,15 @@
             }
         }
 
+        @Override
+        public void onDestroy() {
+            if (mWallpaperSurfaceView != null) {
+                mWallpaperSurfaceView.onPause();
+            }
+        }
+
         private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView {
-            private WallpaperStatusListener mWallpaperChangedListener;
+            private WallpaperStatusListener mWallpaperStatusListener;
 
             GLWallpaperSurfaceView(Context context) {
                 super(context);
@@ -88,18 +85,18 @@
             @Override
             public void setRenderer(Renderer renderer) {
                 super.setRenderer(renderer);
-                mWallpaperChangedListener = (WallpaperStatusListener) renderer;
+                mWallpaperStatusListener = (WallpaperStatusListener) renderer;
             }
 
             private void notifyAmbientModeChanged(boolean inAmbient, long duration) {
-                if (mWallpaperChangedListener != null) {
-                    mWallpaperChangedListener.onAmbientModeChanged(inAmbient, duration);
+                if (mWallpaperStatusListener != null) {
+                    mWallpaperStatusListener.onAmbientModeChanged(inAmbient, duration);
                 }
             }
 
             private void notifyOffsetsChanged(float xOffset, float yOffset) {
-                if (mWallpaperChangedListener != null) {
-                    mWallpaperChangedListener.onOffsetsChanged(
+                if (mWallpaperStatusListener != null) {
+                    mWallpaperStatusListener.onOffsetsChanged(
                             xOffset, yOffset, getHolder().getSurfaceFrame());
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index e0ed111..4a2731e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -61,6 +61,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import java.lang.annotation.Retention;
 
@@ -74,7 +75,8 @@
  * The controller manages addition, removal, and visible state of bubbles on screen.
  */
 @Singleton
-public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener {
+public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener,
+        ConfigurationController.ConfigurationListener {
 
     private static final String TAG = "BubbleController";
 
@@ -84,6 +86,7 @@
     @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
             DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION})
     @interface DismissReason {}
+
     static final int DISMISS_USER_GESTURE = 1;
     static final int DISMISS_AGED = 2;
     static final int DISMISS_TASK_FINISHED = 3;
@@ -151,6 +154,7 @@
     public interface BubbleExpandListener {
         /**
          * Called when the expansion state of the bubble stack changes.
+         *
          * @param isExpanding whether it's expanding or collapsing
          * @param key the notification key associated with bubble being expanded
          */
@@ -179,13 +183,16 @@
 
     @Inject
     public BubbleController(Context context, StatusBarWindowController statusBarWindowController,
-                            BubbleData data) {
-        this(context, statusBarWindowController, data, null /* synchronizer */);
+            BubbleData data, ConfigurationController configurationController) {
+        this(context, statusBarWindowController, data, null /* synchronizer */,
+                configurationController);
     }
 
     public BubbleController(Context context, StatusBarWindowController statusBarWindowController,
-            BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer) {
+            BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer,
+            ConfigurationController configurationController) {
         mContext = context;
+        configurationController.addCallback(this /* configurationListener */);
 
         mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
         mNotificationEntryManager.addNotificationEntryListener(mEntryListener);
@@ -215,6 +222,20 @@
         mSurfaceSynchronizer = synchronizer;
     }
 
+    @Override
+    public void onUiModeChanged() {
+        if (mStackView != null) {
+            mStackView.onConfigChanged();
+        }
+    }
+
+    @Override
+    public void onOverlayChanged() {
+        if (mStackView != null) {
+            mStackView.onConfigChanged();
+        }
+    }
+
     /**
      * Set a listener to be notified when some states of the bubbles change.
      */
@@ -295,7 +316,7 @@
     /**
      * Adds or updates a bubble associated with the provided notification entry.
      *
-     * @param notif the notification associated with this bubble.
+     * @param notif          the notification associated with this bubble.
      * @param updatePosition whether this update should promote the bubble to the top of the stack.
      */
     public void updateBubble(NotificationEntry notif, boolean updatePosition) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 856b9d6..14e910f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -94,6 +94,9 @@
     private boolean mActivityViewReady = false;
     private PendingIntent mBubbleIntent;
 
+    private boolean mKeyboardVisible;
+    private boolean mNeedsNewHeight;
+
     private int mMinHeight;
     private int mHeaderHeight;
     private int mBubbleHeight;
@@ -227,21 +230,15 @@
                 true /* singleTaskInstance */);
         addView(mActivityView);
 
-        mActivityView.setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
-            ActivityView activityView = (ActivityView) view;
-            // Here we assume that the position of the ActivityView on the screen
-            // remains regardless of IME status. When we move ActivityView, the
-            // forwardedInsets should be computed not against the current location
-            // and size, but against the post-moved location and size.
-            Point displaySize = new Point();
-            view.getContext().getDisplay().getSize(displaySize);
-            int[] windowLocation = view.getLocationOnScreen();
-            final int windowBottom = windowLocation[1] + view.getHeight();
+        setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
+            // Keep track of IME displaying because we should not make any adjustments that might
+            // cause a config change while the IME is displayed otherwise it'll loose focus.
             final int keyboardHeight = insets.getSystemWindowInsetBottom()
                     - insets.getStableInsetBottom();
-            final int insetsBottom = Math.max(0,
-                    windowBottom + keyboardHeight - displaySize.y);
-            activityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom));
+            mKeyboardVisible = keyboardHeight != 0;
+            if (!mKeyboardVisible && mNeedsNewHeight) {
+                updateHeight();
+            }
             return view.onApplyWindowInsets(insets);
         });
 
@@ -258,6 +255,34 @@
         }
     }
 
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mKeyboardVisible = false;
+        mNeedsNewHeight = false;
+        if (mActivityView != null) {
+            mActivityView.setForwardedInsets(Insets.of(0, 0, 0, 0));
+        }
+    }
+
+    /**
+     * Called by {@link BubbleStackView} when the insets for the expanded state should be updated.
+     * This should be done post-move and post-animation.
+     */
+    void updateInsets(WindowInsets insets) {
+        if (usingActivityView()) {
+            Point displaySize = new Point();
+            mActivityView.getContext().getDisplay().getSize(displaySize);
+            int[] windowLocation = mActivityView.getLocationOnScreen();
+            final int windowBottom = windowLocation[1] + mActivityView.getHeight();
+            final int keyboardHeight = insets.getSystemWindowInsetBottom()
+                    - insets.getStableInsetBottom();
+            final int insetsBottom = Math.max(0,
+                    windowBottom + keyboardHeight - displaySize.y);
+            mActivityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom));
+        }
+    }
+
     /**
      * Creates a background with corners rounded based on how the view is configured to display
      */
@@ -354,6 +379,13 @@
         }
     }
 
+    /**
+     * Update bubble expanded view header when user toggles dark mode.
+     */
+    void updateHeaderColor() {
+        mHeaderView.setBackgroundColor(mContext.getColor(R.attr.colorAccent));
+    }
+
     private void updateHeaderView() {
         mSettingsIcon.setContentDescription(getResources().getString(
                 R.string.bubbles_settings_button_description, mAppName));
@@ -378,6 +410,8 @@
             mPermissionView.setVisibility(VISIBLE);
             ((ImageView) mPermissionView.findViewById(R.id.pkgicon)).setImageDrawable(mAppIcon);
             ((TextView) mPermissionView.findViewById(R.id.pkgname)).setText(mAppName);
+            ((TextView) mPermissionView.findViewById(R.id.prompt)).setText(
+                    getResources().getString(R.string.bubbles_prompt, mAppName));
             logBubbleClickEvent(mEntry.notification,
                     StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_DIALOG_SHOWN);
         }
@@ -441,9 +475,15 @@
             int height = Math.min(desiredHeight, max);
             height = Math.max(height, mMinHeight);
             LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams();
-            lp.height = height;
-            mBubbleHeight = height;
-            mActivityView.setLayoutParams(lp);
+            mNeedsNewHeight =  lp.height != height;
+            if (!mKeyboardVisible) {
+                // If the keyboard is visible... don't adjust the height because that will cause
+                // a configuration change and the keyboard will be lost.
+                lp.height = height;
+                mBubbleHeight = height;
+                mActivityView.setLayoutParams(lp);
+                mNeedsNewHeight = false;
+            }
         } else {
             mBubbleHeight = mNotifRow != null ? mNotifRow.getIntrinsicHeight() : mMinHeight;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 1cc6b87..580acb8 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -128,6 +128,7 @@
 
     private Bubble mExpandedBubble;
     private boolean mIsExpanded;
+    private boolean mImeVisible;
 
     private BubbleTouchHandler mTouchHandler;
     private BubbleController.BubbleExpandListener mExpandListener;
@@ -236,6 +237,35 @@
         setClipChildren(false);
         setFocusable(true);
         mBubbleContainer.bringToFront();
+
+        setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
+            final int keyboardHeight = insets.getSystemWindowInsetBottom()
+                    - insets.getStableInsetBottom();
+            if (!mIsExpanded) {
+                return view.onApplyWindowInsets(insets);
+            }
+            mImeVisible = keyboardHeight != 0;
+
+            float newY = getYPositionForExpandedView();
+            if (newY < 0) {
+                // TODO: This means our expanded content is too big to fit on screen. Right now
+                // we'll let it translate off but we should be clipping it & pushing the header
+                // down so that it always remains visible.
+            }
+            mExpandedViewYAnim.animateToFinalPosition(newY);
+            mExpandedAnimationController.updateYPosition(
+                    // Update the insets after we're done translating otherwise position
+                    // calculation for them won't be correct.
+                    () -> mExpandedBubble.expandedView.updateInsets(insets));
+            return view.onApplyWindowInsets(insets);
+        });
+    }
+
+    /**
+     * Handle config changes.
+     */
+    public void onConfigChanged() {
+        mExpandedBubble.expandedView.updateHeaderColor();
     }
 
     @Override
@@ -639,15 +669,6 @@
         }
     }
 
-    /**
-     * The width of the collapsed stack of bubbles.
-     */
-    public int getStackWidth() {
-        return mBubblePadding * (mBubbleContainer.getChildCount() - 1)
-                + mBubbleSize + mBubbleContainer.getPaddingEnd()
-                + mBubbleContainer.getPaddingStart();
-    }
-
     private void notifyExpansionChanged(NotificationEntry entry, boolean expanded) {
         if (mExpandListener != null) {
             mExpandListener.onBubbleExpandChanged(expanded, entry != null ? entry.key : null);
@@ -836,8 +857,13 @@
             // calculation is correct)
             mExpandedBubble.expandedView.updateView();
             final float y = getYPositionForExpandedView();
-            mExpandedViewContainer.setTranslationY(y);
-            // Then update the view so that ActivityView knows we translated
+            if (!mExpandedViewYAnim.isRunning()) {
+                // We're not animating so set the value
+                mExpandedViewContainer.setTranslationY(y);
+            } else {
+                // We are animating so update the value
+                mExpandedViewYAnim.animateToFinalPosition(y);
+            }
             mExpandedBubble.expandedView.updateView();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 1f29883..40e08be 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -198,6 +198,19 @@
     }
 
     /**
+     * Animates the bubbles to {@link #getExpandedY()} position. Used in response to IME showing.
+     */
+    public void updateYPosition(Runnable after) {
+        if (mLayout == null) return;
+
+        for (int i = 0; i < mLayout.getChildCount(); i++) {
+            boolean isLast = i == mLayout.getChildCount() - 1;
+            mLayout.animateValueForChildAtIndex(DynamicAnimation.TRANSLATION_Y, i,
+                    getExpandedY(), isLast ? after : null);
+        }
+    }
+
+    /**
      * Animates the bubbles, starting at the given index, to the left or right by the given number
      * of bubble widths. Passing zero for numBubbleWidths will animate the bubbles to their normal
      * positions.
@@ -213,18 +226,25 @@
 
     /** The Y value of the row of expanded bubbles. */
     public float getExpandedY() {
-        boolean showOnTop = mLayout != null
-                && BubbleController.showBubblesAtTop(mLayout.getContext());
-        final WindowInsets insets = mLayout != null ? mLayout.getRootWindowInsets() : null;
-        if (showOnTop && insets != null) {
+        if (mLayout == null || mLayout.getRootWindowInsets() == null) {
+            return 0;
+        }
+        final boolean showOnTop = BubbleController.showBubblesAtTop(mLayout.getContext());
+        final WindowInsets insets = mLayout.getRootWindowInsets();
+        if (showOnTop) {
             return mBubblePaddingPx + Math.max(
                     mStatusBarHeight,
                     insets.getDisplayCutout() != null
                             ? insets.getDisplayCutout().getSafeInsetTop()
                             : 0);
         } else {
-            int bottomInset = insets != null ? insets.getSystemWindowInsetBottom() : 0;
-            return mDisplaySize.y - mBubbleSizePx - (mPipDismissHeight - bottomInset);
+            int keyboardHeight = insets.getSystemWindowInsetBottom()
+                    - insets.getStableInsetBottom();
+            float bottomInset = keyboardHeight > 0
+                    ? keyboardHeight
+                    : (mPipDismissHeight - insets.getStableInsetBottom());
+            // Stable insets are excluded from display size, so we must subtract it
+            return mDisplaySize.y - mBubbleSizePx - mBubblePaddingPx - bottomInset;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index bc3f48d..031f562 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -164,16 +164,9 @@
                     if (screenX != -1 && screenY != -1) {
                         mDozeHost.onSlpiTap(screenX, screenY);
                     }
-                    // Logs screen wake up reason of either single or double tap.
-                    mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
-                            .setType(MetricsEvent.TYPE_UPDATE).setSubtype(pulseReason));
-                    mMachine.wakeUp();
+                    gentleWakeUp(pulseReason);
                 } else if (isPickup) {
-                    // Logs screen wake up reason of lift.
-                    mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
-                            .setType(MetricsEvent.TYPE_UPDATE)
-                            .setSubtype(DozeLog.REASON_SENSOR_PICKUP));
-                    mMachine.wakeUp();
+                    gentleWakeUp(pulseReason);
                 } else {
                     mDozeHost.extendPulse();
                 }
@@ -190,6 +183,20 @@
         }
     }
 
+    private void gentleWakeUp(int reason) {
+        // Log screen wake up reason (lift/pickup, tap, double-tap)
+        mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
+                .setType(MetricsEvent.TYPE_UPDATE)
+                .setSubtype(reason));
+        if (mDozeParameters.getDisplayNeedsBlanking()) {
+            // Let's prepare the display to wake-up by drawing black.
+            // This will cover the hardware wake-up sequence, where the display
+            // becomes black for a few frames.
+            mDozeHost.setAodDimmingScrim(255f);
+        }
+        mMachine.wakeUp();
+    }
+
     private void onProximityFar(boolean far) {
         final boolean near = !far;
         final DozeMachine.State state = mMachine.getState();
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
index a313336..21406e5 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
@@ -110,9 +110,10 @@
         mTextureBuffer.position(0);
     }
 
-    void setup() {
+    void setup(Bitmap bitmap) {
         setupAttributes();
         setupUniforms();
+        setupTexture(bitmap);
     }
 
     private void setupAttributes() {
@@ -159,7 +160,7 @@
         glDrawArrays(GL_TRIANGLES, 0, VERTICES.length / 2);
     }
 
-    void setupTexture(Bitmap bitmap) {
+    private void setupTexture(Bitmap bitmap) {
         final int[] tids = new int[1];
 
         if (bitmap == null) {
@@ -174,7 +175,7 @@
             return;
         }
 
-        // Bind a named texture to a texturing target.
+        // Bind a named texture to a target.
         glBindTexture(GL_TEXTURE_2D, tids[0]);
         // Load the bitmap data and copy it over into the texture object that is currently bound.
         GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
@@ -195,15 +196,8 @@
         glUniform1i(mUniTexture, 0);
     }
 
-    void adjustTextureCoordinates(Bitmap bitmap, int surfaceWidth, int surfaceHeight,
-            float xOffset, float yOffset) {
-        if (bitmap == null) {
-            Log.d(TAG, "adjustTextureCoordinates: invalid bitmap");
-            return;
-        }
-
-        int bitmapWidth = bitmap.getWidth();
-        int bitmapHeight = bitmap.getHeight();
+    void adjustTextureCoordinates(int bitmapWidth, int bitmapHeight,
+            int surfaceWidth, int surfaceHeight, float xOffset, float yOffset) {
         float ratioW = 1f;
         float ratioH = 1f;
         float rX = 0f;
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 9df6ba5..464cbe3 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -58,6 +58,10 @@
     private int mWidth = 0;
     private int mHeight = 0;
 
+    private Bitmap mBitmap;
+    private int mBitmapWidth = 0;
+    private int mBitmapHeight = 0;
+
     public ImageWallpaperRenderer(Context context, ImageGLView glView) {
         mWallpaperManager = context.getSystemService(WallpaperManager.class);
         if (mWallpaperManager == null) {
@@ -71,8 +75,12 @@
         mGLView = glView;
 
         if (mWallpaperManager != null) {
+            mBitmap = mWallpaperManager.getBitmap();
+            mBitmapWidth = mBitmap.getWidth();
+            mBitmapHeight = mBitmap.getHeight();
             // Compute per85 as transition threshold, this is an async work.
-            mImageProcessHelper.startComputingPercentile85(mWallpaperManager.getBitmap());
+            mImageProcessHelper.startComputingPercentile85(mBitmap);
+            mWallpaperManager.forgetLoadedWallpaper();
         }
     }
 
@@ -81,8 +89,8 @@
         glClearColor(0f, 0f, 0f, 1.0f);
         mProgram.useGLProgram(
                 R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
-        mWallpaper.setup();
-        mWallpaper.setupTexture(mWallpaperManager.getBitmap());
+        mWallpaper.setup(mBitmap);
+        mBitmap = null;
     }
 
     @Override
@@ -94,8 +102,8 @@
         }
         mWidth = width;
         mHeight = height;
-        mWallpaper.adjustTextureCoordinates(mWallpaperManager.getBitmap(),
-                width, height, mXOffset, mYOffset);
+        mWallpaper.adjustTextureCoordinates(
+                mBitmapWidth, mBitmapHeight, width, height, mXOffset, mYOffset);
     }
 
     @Override
@@ -132,13 +140,7 @@
 
     @Override
     public void onOffsetsChanged(float xOffset, float yOffset, Rect frame) {
-        if (frame == null || mWallpaperManager == null
-                || (xOffset == mXOffset && yOffset == mYOffset)) {
-            return;
-        }
-
-        Bitmap bitmap = mWallpaperManager.getBitmap();
-        if (bitmap == null) {
+        if (frame == null || (xOffset == mXOffset && yOffset == mYOffset)) {
             return;
         }
 
@@ -151,7 +153,8 @@
             Log.d(TAG, "onOffsetsChanged: width=" + width + ", height=" + height
                     + ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
         }
-        mWallpaper.adjustTextureCoordinates(bitmap, width, height, mXOffset, mYOffset);
+        mWallpaper.adjustTextureCoordinates(
+                mBitmapWidth, mBitmapHeight, width, height, mXOffset, mYOffset);
         requestRender();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 0be9e25..676e594 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2031,7 +2031,6 @@
     private void handleNotifyScreenTurnedOff() {
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff");
-            mStatusBarKeyguardViewManager.onScreenTurnedOff();
             mDrawnCallback = null;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index ccb8d9b..3433fa8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification
 
 import android.animation.ObjectAnimator
+import android.content.Context
 import android.util.FloatProperty
 import com.android.systemui.Interpolators
 import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -25,12 +26,14 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator
+import com.android.systemui.statusbar.phone.DozeParameters
 
 import javax.inject.Inject
 import javax.inject.Singleton
 
 @Singleton
 class NotificationWakeUpCoordinator @Inject constructor(
+        private val mContext: Context,
         private val mAmbientPulseManager: AmbientPulseManager,
         private val mStatusBarStateController: StatusBarStateController)
     : AmbientPulseManager.OnAmbientChangedListener, StatusBarStateController.StateListener {
@@ -59,10 +62,12 @@
     private var mLinearVisibilityAmount = 0.0f
     private var mWakingUp = false
     private val mEntrySetToClearWhenFinished = mutableSetOf<NotificationEntry>()
+    private val mDozeParameters: DozeParameters;
 
     init {
         mAmbientPulseManager.addListener(this)
         mStatusBarStateController.addCallback(this)
+        mDozeParameters = DozeParameters.getInstance(mContext)
     }
 
     fun setStackScroller(stackScroller: NotificationStackScrollLayout) {
@@ -194,7 +199,7 @@
     }
 
     override fun onAmbientStateChanged(entry: NotificationEntry, isPulsing: Boolean) {
-        var animate = true
+        var animate = mDozeParameters.getAlwaysOn() && !mDozeParameters.getDisplayNeedsBlanking()
         if (!isPulsing) {
             if (mLinearDozeAmount != 0.0f) {
                 if (entry.isRowDismissed) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index d7baeee..9630727c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -2432,7 +2432,7 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         int intrinsicBefore = getIntrinsicHeight();
         super.onLayout(changed, left, top, right, bottom);
-        if (intrinsicBefore != getIntrinsicHeight()) {
+        if (intrinsicBefore != getIntrinsicHeight() && intrinsicBefore != 0) {
             notifyHeightChanged(true  /* needsAnimation */);
         }
         if (mMenuRow.getMenuView() != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 410eeae..5a7df1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -303,7 +303,6 @@
             case MODE_SHOW_BOUNCER:
                 Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER");
                 if (!wasDeviceInteractive) {
-                    mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
                     mPendingShowBouncer = true;
                 } else {
                     showBouncer();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index c4b41d4..319a504 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1109,7 +1109,6 @@
             where.getLocationInWindow(mTmpInt2);
             mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
                     mTmpInt2[1] + where.getHeight() / 2);
-            mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
             mFalsingManager.onScreenOnFromTouch();
         }
     }
@@ -3005,7 +3004,7 @@
 
     private void updatePanelExpansionForKeyguard() {
         if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode()
-                != BiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
+                != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) {
             instantExpandNotificationsPanel();
         } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
             instantCollapseNotificationPanel();
@@ -3563,6 +3562,9 @@
         }
     }
 
+    /**
+     * Propagation of the bouncer state, indicating that it's fully visible.
+     */
     public void setBouncerShowing(boolean bouncerShowing) {
         mBouncerShowing = bouncerShowing;
         if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
@@ -3620,10 +3622,13 @@
             mWakeUpCoordinator.setWakingUp(true);
             mAmbientPulseManager.releaseAllImmediately();
             mVisualStabilityManager.setScreenOn(true);
-            updateNotificationPanelTouchState();
             updateVisibleToUser();
             updateIsKeyguard();
             mDozeServiceHost.stopDozing();
+            // This is intentionally below the stopDozing call above, since it avoids that we're
+            // unnecessarily animating the wakeUp transition. Animations should only be enabled
+            // once we fully woke up.
+            updateNotificationPanelTouchState();
             mPulseExpansionHandler.onStartedWakingUp();
         }
 
@@ -3736,7 +3741,6 @@
             PowerManager pm = mContext.getSystemService(PowerManager.class);
             pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
                     "com.android.systemui:CAMERA_GESTURE");
-            mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
         }
         vibrateForCameraGesture();
         if (!mStatusBarKeyguardViewManager.isShowing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index e8a5c7a..338886d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -85,6 +85,7 @@
         @Override
         public void onFullyShown() {
             updateStates();
+            mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), mContainer, "BOUNCER_VISIBLE");
         }
 
         @Override
@@ -346,14 +347,6 @@
         }
     }
 
-    public void onScreenTurnedOff() {
-        // TODO: remove
-    }
-
-    public void notifyDeviceWakeUpRequested() {
-        // TODO: remove
-    }
-
     public void setNeedsInput(boolean needsInput) {
         mStatusBarWindowController.setKeyguardNeedsInput(needsInput);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 4e9d892..63b6673 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -44,6 +44,7 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -66,6 +67,9 @@
     private IActivityManager mActivityManager;
     @Mock
     private DozeParameters mDozeParameters;
+    @Mock
+    private ConfigurationController mConfigurationController;
+
     private FrameLayout mStatusBarView;
     @Captor
     private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
@@ -97,6 +101,7 @@
         mStatusBarView = new FrameLayout(mContext);
         mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
 
+
         // Bubbles get added to status bar window view
         mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
                 mActivityManager, mDozeParameters);
@@ -115,7 +120,7 @@
 
         mBubbleData = new BubbleData();
         mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController,
-                mBubbleData);
+                mBubbleData, mConfigurationController);
         mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
         mBubbleController.setExpandListener(mBubbleExpandListener);
 
@@ -331,8 +336,9 @@
     static class TestableBubbleController extends BubbleController {
         // Let's assume surfaces can be synchronized immediately.
         TestableBubbleController(Context context,
-                StatusBarWindowController statusBarWindowController, BubbleData data) {
-            super(context, statusBarWindowController, data, Runnable::run);
+                StatusBarWindowController statusBarWindowController, BubbleData data,
+                ConfigurationController configurationController) {
+            super(context, statusBarWindowController, data, Runnable::run, configurationController);
         }
 
         @Override
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 8941182..1ac6bef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -136,13 +137,14 @@
     @Test
     public void testOnSensor_whenDockedWithNearAndDoubleTapScreen_shouldWakeUp() {
         doReturn(true).when(mDockManagerFake).isDocked();
+        doReturn(true).when(mParameters).getDisplayNeedsBlanking();
         mSensors.getMockProximitySensor().sendProximityResult(false /* far */);
 
         mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP,
                 false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
                 null /* rawValues */);
 
+        verify(mHost).setAodDimmingScrim(eq(255));
         verify(mMachine).wakeUp();
     }
-
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index db8357a..6889c57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -71,7 +71,7 @@
         mDependency.injectMockDependency(ConfigurationController.class);
         mDependency.injectMockDependency(ZenModeController.class);
         NotificationWakeUpCoordinator coordinator =
-                new NotificationWakeUpCoordinator(
+                new NotificationWakeUpCoordinator(mContext,
                         new AmbientPulseManager(mContext),
                         new StatusBarStateControllerImpl());
         PulseExpansionHandler expansionHandler = new PulseExpansionHandler(mContext, coordinator);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index cb5612d..5f7f422 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -29,6 +29,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -719,12 +720,25 @@
     public void testOnStartedWakingUp_isNotDozing() {
         mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
         when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
-
         mStatusBar.mDozeServiceHost.startDozing();
         verify(mStatusBarStateController).setIsDozing(eq(true));
+        clearInvocations(mNotificationPanelView);
 
         mStatusBar.mWakefulnessObserver.onStartedWakingUp();
         verify(mStatusBarStateController).setIsDozing(eq(false));
+        verify(mNotificationPanelView).expand(eq(false));
+    }
+
+    @Test
+    public void testOnStartedWakingUp_doesNotDismissBouncer_whenPulsing() {
+        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+        when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
+        mStatusBar.mDozeServiceHost.startDozing();
+        clearInvocations(mNotificationPanelView);
+
+        mStatusBar.setBouncerShowing(true);
+        mStatusBar.mWakefulnessObserver.onStartedWakingUp();
+        verify(mNotificationPanelView, never()).expand(anyBoolean());
     }
 
     static class TestableStatusBar extends StatusBar {
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index f106228..7447331 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7120,6 +7120,24 @@
     // Open: Settings > Special App Access > Do not disturb control for app
     ZEN_ACCESS_DETAIL = 1692;
 
+    // OPEN: Settings > Face > Remove face
+    // OS: Q
+    DIALOG_FACE_REMOVE = 1693;
+
+    // FIELD - Detailed reason in screen wake. One of WAKE_REASON_* in PowerManager.
+    // OS: Q
+    FIELD_SCREEN_WAKE_REASON = 1694;
+
+    // FIELD - Detailed reason in screen sleep. One of GO_TO_SLEEP_REASON_* in PowerManager.
+    // OS: Q
+    FIELD_SCREEN_SLEEP_REASON = 1695;
+
+    // UPDATE: The screen changed policy
+    //   SUBTYPE: The applied policy. One of the DISPLAY_POLICY_* constants in
+    //   DisplayManagerInternal.
+    // OS: Q
+    DISPLAY_POLICY = 1696;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 6597312..c1c125d 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -569,6 +569,42 @@
         }
     }
 
+    // Called by Shell command
+    boolean isDefaultAugmentedServiceEnabled(@UserIdInt int userId) {
+        enforceCallingPermissionForManagement();
+
+        synchronized (mLock) {
+            final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+            if (service != null) {
+                return service.mAugmentedAutofillResolver.isDefaultServiceEnabled(userId);
+            }
+        }
+        return false;
+    }
+
+    // Called by Shell command
+    boolean setDefaultAugmentedServiceEnabled(@UserIdInt int userId, boolean enabled) {
+        Slog.i(mTag, "setDefaultAugmentedServiceEnabled() for userId " + userId + ": " + enabled);
+        enforceCallingPermissionForManagement();
+
+        synchronized (mLock) {
+            final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+            if (service != null) {
+                final boolean changed = service.mAugmentedAutofillResolver
+                        .setDefaultServiceEnabled(userId, enabled);
+                if (changed) {
+                    service.updateRemoteAugmentedAutofillService();
+                    return true;
+                } else {
+                    if (debug) {
+                        Slog.d(TAG, "setDefaultAugmentedServiceEnabled(): already " + enabled);
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
     private void setLoggingLevelsLocked(boolean debug, boolean verbose) {
         com.android.server.autofill.Helper.sDebug = debug;
         android.view.autofill.Helper.sDebug = debug;
@@ -647,6 +683,14 @@
         send(receiver, value ? 1 : 0);
     }
 
+    private void send(@NonNull IResultReceiver receiver, int value1, int value2) {
+        try {
+            receiver.send(value1, SyncResultReceiver.bundleFor(value2));
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Error async reporting result to client: " + e);
+        }
+    }
+
     @Nullable
     @VisibleForTesting
     static Map<String, String[]> getWhitelistedCompatModePackages(String setting) {
@@ -967,14 +1011,20 @@
             // TODO(b/113281366): add a callback method on AM to be notified when a task is finished
             // so we can clean up sessions kept alive
             final int taskId = mAm.getTaskIdForActivity(activityToken, false);
-            final int sessionId;
+            final long result;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
-                sessionId = service.startSessionLocked(activityToken, taskId, getCallingUid(),
+                result = service.startSessionLocked(activityToken, taskId, getCallingUid(),
                         appCallback, autofillId, bounds, value, hasCallback, componentName,
                         compatMode, mAllowInstantService, flags);
             }
-            send(receiver, sessionId);
+            final int sessionId = (int) result;
+            final int resultFlags = (int) (result >> 32);
+            if (resultFlags != 0) {
+                send(receiver, sessionId, resultFlags);
+            } else {
+                send(receiver, sessionId);
+            }
         }
 
         @Override
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 9612346..720d319 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -18,6 +18,7 @@
 
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
+import static android.view.autofill.AutofillManager.FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY;
 import static android.view.autofill.AutofillManager.NO_SESSION;
 
 import static com.android.server.autofill.Helper.sDebug;
@@ -53,6 +54,7 @@
 import android.service.autofill.FieldClassification.Match;
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.FillEventHistory.Event;
+import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
 import android.service.autofill.UserData;
@@ -156,6 +158,7 @@
     /** When was {@link PruneTask} last executed? */
     private long mLastPrune = 0;
 
+    // TODO(b/128911469): move to AutofillManagerService
     /**
      * Object used to set the name of the augmented autofill service.
      */
@@ -221,7 +224,7 @@
                     session.removeSelfLocked();
                 }
             }
-            sendStateToClients(false);
+            sendStateToClients(/* resetClient= */ false);
         }
         updateRemoteAugmentedAutofillService();
         return enabledChanged;
@@ -278,8 +281,15 @@
         }
     }
 
+    /**
+     * Starts a new session.
+     *
+     * @return {@code long} whose right-most 32 bits represent the session id (which is always
+     * non-negative), and the left-most contains extra flags (currently either {@code 0} or
+     * {@link FillRequest#FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}).
+     */
     @GuardedBy("mLock")
-    int startSessionLocked(@NonNull IBinder activityToken, int taskId, int uid,
+    long startSessionLocked(@NonNull IBinder activityToken, int taskId, int uid,
             @NonNull IBinder appCallbackToken, @NonNull AutofillId autofillId,
             @NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback,
             @NonNull ComponentName componentName, boolean compatMode,
@@ -289,33 +299,48 @@
         }
 
         final String shortComponentName = componentName.toShortString();
+        boolean forAugmentedAutofillOnly = false;
 
         if (isAutofillDisabledLocked(componentName)) {
-            if (sDebug) {
-                Slog.d(TAG, "startSession(" + shortComponentName
-                        + "): ignored because disabled by service");
-            }
+            // Service disabled autofill; that means no session, unless the activity is whitelisted
+            // for augmented autofill
+            if (isWhitelistedForAugmentedAutofillLocked(componentName)) {
+                if (sDebug) {
+                    Slog.d(TAG, "startSession(" + shortComponentName + "): disabled by service but "
+                            + "whitelisted for augmented autofill");
+                }
+                forAugmentedAutofillOnly = true;
 
-            final IAutoFillManagerClient client = IAutoFillManagerClient.Stub
-                    .asInterface(appCallbackToken);
-            try {
-                client.setSessionFinished(AutofillManager.STATE_DISABLED_BY_SERVICE,
-                        /* autofillableIds= */ null);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Could not notify " + shortComponentName + " that it's disabled: " + e);
-            }
+            } else {
+                if (sDebug) {
+                    Slog.d(TAG, "startSession(" + shortComponentName + "): ignored because "
+                            + "disabled by service and not whitelisted for augmented autofill");
+                }
+                final IAutoFillManagerClient client = IAutoFillManagerClient.Stub
+                        .asInterface(appCallbackToken);
+                try {
+                    client.setSessionFinished(AutofillManager.STATE_DISABLED_BY_SERVICE,
+                            /* autofillableIds= */ null);
+                } catch (RemoteException e) {
+                    Slog.w(TAG,
+                            "Could not notify " + shortComponentName + " that it's disabled: " + e);
+                }
 
-            return NO_SESSION;
+                return NO_SESSION;
+            }
         }
 
-        if (sVerbose) Slog.v(TAG, "startSession(): token=" + activityToken + ", flags=" + flags);
+        if (sVerbose) {
+            Slog.v(TAG, "startSession(): token=" + activityToken + ", flags=" + flags
+                    + ", forAugmentedAutofillOnly=" + forAugmentedAutofillOnly);
+        }
 
         // Occasionally clean up abandoned sessions
         pruneAbandonedSessionsLocked();
 
         final Session newSession = createSessionByTokenLocked(activityToken, taskId, uid,
                 appCallbackToken, hasCallback, componentName, compatMode,
-                bindInstantServiceAllowed, flags);
+                bindInstantServiceAllowed, forAugmentedAutofillOnly, flags);
         if (newSession == null) {
             return NO_SESSION;
         }
@@ -324,12 +349,20 @@
                 "id=" + newSession.id + " uid=" + uid + " a=" + shortComponentName
                 + " s=" + mInfo.getServiceInfo().packageName
                 + " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds
-                + " hc=" + hasCallback + " f=" + flags;
+                + " hc=" + hasCallback + " f=" + flags + " aa=" + forAugmentedAutofillOnly;
         mMaster.logRequestLocked(historyItem);
 
         newSession.updateLocked(autofillId, virtualBounds, value, ACTION_START_SESSION, flags);
 
-        return newSession.id;
+        if (forAugmentedAutofillOnly) {
+            // Must embed the flag in the response, at the high-end side of the long.
+            // (session is always positive, so we don't have to worry about the signal bit)
+            final long extraFlags = ((long) FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) << 32;
+            final long result = extraFlags | newSession.id;
+            return result;
+        } else {
+            return newSession.id;
+        }
     }
 
     /**
@@ -435,7 +468,7 @@
     private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int taskId, int uid,
             @NonNull IBinder appCallbackToken, boolean hasCallback,
             @NonNull ComponentName componentName, boolean compatMode,
-            boolean bindInstantServiceAllowed, int flags) {
+            boolean bindInstantServiceAllowed, boolean forAugmentedAutofillOnly, int flags) {
         // use random ids so that one app cannot know that another app creates sessions
         int sessionId;
         int tries = 0;
@@ -446,15 +479,17 @@
                 return null;
             }
 
-            sessionId = sRandom.nextInt();
-        } while (sessionId == NO_SESSION || mSessions.indexOfKey(sessionId) >= 0);
+            sessionId = Math.abs(sRandom.nextInt());
+        } while (sessionId == 0 || sessionId == NO_SESSION
+                || mSessions.indexOfKey(sessionId) >= 0);
 
         assertCallerLocked(componentName, compatMode);
 
         final Session newSession = new Session(this, mUi, getContext(), mHandler, mUserId, mLock,
                 sessionId, taskId, uid, activityToken, appCallbackToken, hasCallback,
                 mUiLatencyHistory, mWtfHistory, mInfo.getServiceInfo().getComponentName(),
-                componentName, compatMode, bindInstantServiceAllowed, flags);
+                componentName, compatMode, bindInstantServiceAllowed, forAugmentedAutofillOnly,
+                flags);
         mSessions.put(newSession.id, newSession);
 
         return newSession;
@@ -634,7 +669,7 @@
             remoteFillServices.valueAt(i).destroy();
         }
 
-        sendStateToClients(true);
+        sendStateToClients(/* resetclient=*/ true);
         if (mClients != null) {
             mClients.kill();
             mClients = null;
@@ -889,8 +924,6 @@
         } else {
             pw.println();
             mInfo.dump(prefix2, pw);
-            pw.print(prefix); pw.print("Service Label: "); pw.println(getServiceLabelLocked());
-            pw.print(prefix); pw.print("Target SDK: "); pw.println(getTargedSdkLocked());
         }
         pw.print(prefix); pw.print("Default component: "); pw.println(getContext()
                 .getString(R.string.config_defaultAutofillService));
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index c562fb1..bbe37a5 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -109,6 +109,13 @@
                     + "implementation.");
             pw.println("    To reset, call with just the USER_ID argument.");
             pw.println("");
+            pw.println("  set default-augmented-service-enabled USER_ID [true|false]");
+            pw.println("    Enable / disable the default augmented autofill service for the user.");
+            pw.println("");
+            pw.println("  get default-augmented-service-enabled USER_ID");
+            pw.println("    Checks whether the default augmented autofill service is enabled for "
+                    + "the user.");
+            pw.println("");
             pw.println("  list sessions [--user USER_ID]");
             pw.println("    Lists all pending sessions.");
             pw.println("");
@@ -136,6 +143,8 @@
                 return getFullScreenMode(pw);
             case "bind-instant-service-allowed":
                 return getBindInstantService(pw);
+            case "default-augmented-service-enabled":
+                return getDefaultAugmentedServiceEnabled(pw);
             default:
                 pw.println("Invalid set: " + what);
                 return -1;
@@ -158,6 +167,8 @@
                 return setBindInstantService(pw);
             case "temporary-augmented-service":
                 return setTemporaryAugmentedService(pw);
+            case "default-augmented-service-enabled":
+                return setDefaultAugmentedServiceEnabled(pw);
             default:
                 pw.println("Invalid set: " + what);
                 return -1;
@@ -314,6 +325,23 @@
         return 0;
     }
 
+    private int getDefaultAugmentedServiceEnabled(PrintWriter pw) {
+        final int userId = getNextIntArgRequired();
+        final boolean enabled = mService.isDefaultAugmentedServiceEnabled(userId);
+        pw.println(enabled);
+        return 0;
+    }
+
+    private int setDefaultAugmentedServiceEnabled(PrintWriter pw) {
+        final int userId = getNextIntArgRequired();
+        final boolean enabled = Boolean.parseBoolean(getNextArgRequired());
+        final boolean changed = mService.setDefaultAugmentedServiceEnabled(userId, enabled);
+        if (!changed) {
+            pw.println("already " + enabled);
+        }
+        return 0;
+    }
+
     private int requestDestroy(PrintWriter pw) {
         if (!isNextArgSessions(pw)) {
             return -1;
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index ea47033..f08bab3 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -138,7 +138,11 @@
 
     private static AtomicInteger sIdCounter = new AtomicInteger();
 
-    /** ID of the session */
+    /**
+     * ID of the session.
+     *
+     * <p>It's always a positive number, to make it easier to embed it in a long.
+     */
     public final int id;
 
     /** uid the session is for */
@@ -277,6 +281,13 @@
     private ArraySet<AutofillId> mAugmentedAutofillableIds;
 
     /**
+     * When {@code true}, the session was created only to handle Augmented Autofill requests (i.e.,
+     * the session would not have existed otherwsie).
+     */
+    @GuardedBy("mLock")
+    private boolean mForAugmentedAutofillOnly;
+
+    /**
      * Receiver of assist data from the app's {@link Activity}.
      */
     private final IAssistDataReceiver mAssistReceiver = new IAssistDataReceiver.Stub() {
@@ -538,11 +549,12 @@
      */
     @GuardedBy("mLock")
     private void requestNewFillResponseLocked(int flags) {
-
-        if ((flags & FLAG_AUGMENTED_AUTOFILL_REQUEST) != 0) {
+        if (mForAugmentedAutofillOnly || (flags & FLAG_AUGMENTED_AUTOFILL_REQUEST) != 0) {
             // TODO(b/122858578): log metrics
             if (sVerbose) {
-                Slog.v(TAG, "requestNewFillResponse(): triggering augmented autofill instead");
+                Slog.v(TAG, "requestNewFillResponse(): triggering augmented autofill instead "
+                        + "(mForAugmentedAutofillOnly=" + mForAugmentedAutofillOnly
+                        + ", flags=" + flags + ")");
             }
             triggerAugmentedAutofillLocked();
             return;
@@ -564,8 +576,8 @@
         mRequestLogs.put(requestId, log);
 
         if (sVerbose) {
-            Slog.v(TAG, "Requesting structure for request #" + ordinal + " ,requestId="
-                    + requestId + ", flags=" + flags);
+            Slog.v(TAG, "Requesting structure for request #" + ordinal + " ,requestId=" + requestId
+                    + ", flags=" + flags);
         }
 
         // If the focus changes very quickly before the first request is returned each focus change
@@ -598,7 +610,10 @@
             @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory,
             @NonNull LocalLog wtfHistory, @NonNull ComponentName serviceComponentName,
             @NonNull ComponentName componentName, boolean compatMode,
-            boolean bindInstantServiceAllowed, int flags) {
+            boolean bindInstantServiceAllowed, boolean forAugmentedAutofillOnly, int flags) {
+        if (sessionId < 0) {
+            wtf(null, "Non-positive sessionId: %s", sessionId);
+        }
         id = sessionId;
         mFlags = flags;
         this.taskId = taskId;
@@ -616,6 +631,7 @@
         mWtfHistory = wtfHistory;
         mComponentName = componentName;
         mCompatMode = compatMode;
+        mForAugmentedAutofillOnly = forAugmentedAutofillOnly;
         setClientLocked(client);
 
         mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
@@ -727,14 +743,6 @@
         final long disableDuration = response.getDisableDuration();
         if (disableDuration > 0) {
             final int flags = response.getFlags();
-            if (sDebug) {
-                final StringBuilder message = new StringBuilder("Service disabled autofill for ")
-                        .append(mComponentName)
-                        .append(": flags=").append(flags)
-                        .append(", duration=");
-                TimeUtils.formatDuration(disableDuration, message);
-                Slog.d(TAG, message.toString());
-            }
             if ((flags & FillResponse.FLAG_DISABLE_ACTIVITY_ONLY) != 0) {
                 mService.disableAutofillForActivity(mComponentName, disableDuration,
                         id, mCompatMode);
@@ -742,6 +750,23 @@
                 mService.disableAutofillForApp(mComponentName.getPackageName(), disableDuration,
                         id, mCompatMode);
             }
+            // Although "standard" autofill is disabled, it might still trigger augmented autofill
+            if (triggerAugmentedAutofillLocked() != null) {
+                mForAugmentedAutofillOnly = true;
+                if (sDebug) {
+                    Slog.d(TAG, "Service disabled autofill for " + mComponentName
+                            + ", but session is kept for augmented autofill only");
+                }
+                return;
+            }
+            if (sDebug) {
+                final StringBuilder message = new StringBuilder("Service disabled autofill for ")
+                                .append(mComponentName)
+                                .append(": flags=").append(flags)
+                                .append(", duration=");
+                TimeUtils.formatDuration(disableDuration, message);
+                Slog.d(TAG, message.toString());
+            }
             sessionFinishedState = AutofillManager.STATE_DISABLED_BY_SERVICE;
         }
 
@@ -3005,6 +3030,9 @@
         pw.print(prefix); pw.print("mSaveOnAllViewsInvisible: "); pw.println(
                 mSaveOnAllViewsInvisible);
         pw.print(prefix); pw.print("mSelectedDatasetIds: "); pw.println(mSelectedDatasetIds);
+        if (mForAugmentedAutofillOnly) {
+            pw.print(prefix); pw.println("For Augmented Autofill Only");
+        }
         if (mAugmentedAutofillDestroyer != null) {
             pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer");
         }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index ffda581..7106664 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -362,8 +362,8 @@
      * @param dataManagementIntent An {@link Intent} that can be passed to {@link
      *     Context#startActivity} in order to launch the transport's data-management UI. It may be
      *     {@code null} if the transport does not offer any user-facing data management UI.
-     * @param dataManagementLabel A {@link String} to be used as the label for the transport's data
-     *     management affordance. This MUST be {@code null} when dataManagementIntent is {@code
+     * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's
+     *     data management affordance. This MUST be {@code null} when dataManagementIntent is {@code
      *     null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
      * @throws SecurityException If the UID of the calling process differs from the package UID of
      *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
@@ -375,7 +375,7 @@
             @Nullable Intent configurationIntent,
             String currentDestinationString,
             @Nullable Intent dataManagementIntent,
-            String dataManagementLabel) {
+            CharSequence dataManagementLabel) {
         UserBackupManagerService userBackupManagerService =
                 getServiceForUserIfCallerHasPermission(userId, "updateTransportAttributes()");
 
@@ -521,7 +521,7 @@
      * transport.
      */
     @Nullable
-    public String getDataManagementLabel(@UserIdInt int userId, String transportName) {
+    public CharSequence getDataManagementLabel(@UserIdInt int userId, String transportName) {
         UserBackupManagerService userBackupManagerService =
                 getServiceForUserIfCallerHasPermission(userId, "getDataManagementLabel()");
 
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 00cb6d3..8f0c5d8 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -630,8 +630,7 @@
             @Nullable Intent configurationIntent,
             String currentDestinationString,
             @Nullable Intent dataManagementIntent,
-            String dataManagementLabel) {
-
+            CharSequence dataManagementLabel) {
         if (isUserReadyForBackup(userId)) {
             mService.updateTransportAttributes(
                     userId,
@@ -710,19 +709,13 @@
     }
 
     @Override
-    public String getDataManagementLabelForUser(int userId, String transport)
+    public CharSequence getDataManagementLabelForUser(int userId, String transport)
             throws RemoteException {
         return isUserReadyForBackup(userId) ? mService.getDataManagementLabel(userId, transport)
                 : null;
     }
 
     @Override
-    public String getDataManagementLabel(String transport)
-            throws RemoteException {
-        return getDataManagementLabelForUser(binderGetCallingUserId(), transport);
-    }
-
-    @Override
     public IRestoreSession beginRestoreSessionForUser(
             int userId, String packageName, String transportID) throws RemoteException {
         return isUserReadyForBackup(userId) ? mService.beginRestoreSession(userId, packageName,
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index a7bada0..30ce4cf 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -284,7 +284,7 @@
      * @throws TransportNotRegisteredException if the transport is not registered.
      */
     @Nullable
-    public String getTransportDataManagementLabel(String transportName)
+    public CharSequence getTransportDataManagementLabel(String transportName)
             throws TransportNotRegisteredException {
         synchronized (mTransportLock) {
             return getRegisteredTransportDescriptionOrThrowLocked(transportName)
@@ -327,7 +327,7 @@
             @Nullable Intent configurationIntent,
             String currentDestinationString,
             @Nullable Intent dataManagementIntent,
-            @Nullable String dataManagementLabel) {
+            @Nullable CharSequence dataManagementLabel) {
         synchronized (mTransportLock) {
             TransportDescription description =
                     mRegisteredTransportsDescriptionMap.get(transportComponent);
@@ -678,7 +678,7 @@
                         transport.configurationIntent(),
                         transport.currentDestinationString(),
                         transport.dataManagementIntent(),
-                        transport.dataManagementLabel());
+                        transport.dataManagementIntentLabel());
         synchronized (mTransportLock) {
             mRegisteredTransportsDescriptionMap.put(transportComponent, description);
         }
@@ -707,7 +707,7 @@
         @Nullable private Intent configurationIntent;
         private String currentDestinationString;
         @Nullable private Intent dataManagementIntent;
-        @Nullable private String dataManagementLabel;
+        @Nullable private CharSequence dataManagementLabel;
 
         private TransportDescription(
                 String name,
@@ -715,7 +715,7 @@
                 @Nullable Intent configurationIntent,
                 String currentDestinationString,
                 @Nullable Intent dataManagementIntent,
-                @Nullable String dataManagementLabel) {
+                @Nullable CharSequence dataManagementLabel) {
             this.name = name;
             this.transportDirName = transportDirName;
             this.configurationIntent = configurationIntent;
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 32e2cac..447bd8c 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -2929,8 +2929,8 @@
      *     {@link Context#startActivity} in order to launch the transport's data-management UI. It
      *     may be {@code null} if the transport does not offer any user-facing data
      *     management UI.
-     * @param dataManagementLabel A {@link String} to be used as the label for the transport's data
-     *     management affordance. This MUST be {@code null} when dataManagementIntent is
+     * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's
+     *     data management affordance. This MUST be {@code null} when dataManagementIntent is
      *     {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
      * @throws SecurityException If the UID of the calling process differs from the package UID of
      *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
@@ -2941,7 +2941,7 @@
             @Nullable Intent configurationIntent,
             String currentDestinationString,
             @Nullable Intent dataManagementIntent,
-            @Nullable String dataManagementLabel) {
+            @Nullable CharSequence dataManagementLabel) {
         updateTransportAttributes(
                 Binder.getCallingUid(),
                 transportComponent,
@@ -2960,7 +2960,7 @@
             @Nullable Intent configurationIntent,
             String currentDestinationString,
             @Nullable Intent dataManagementIntent,
-            @Nullable String dataManagementLabel) {
+            @Nullable CharSequence dataManagementLabel) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "updateTransportAttributes");
 
@@ -3159,12 +3159,12 @@
      * Supply the menu label for affordances that fire the manage-data intent for the given
      * transport.
      */
-    public String getDataManagementLabel(String transportName) {
+    public CharSequence getDataManagementLabel(String transportName) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                 "getDataManagementLabel");
 
         try {
-            String label = mTransportManager.getTransportDataManagementLabel(transportName);
+            CharSequence label = mTransportManager.getTransportDataManagementLabel(transportName);
             if (MORE_DEBUG) {
                 Slog.d(TAG, "getDataManagementLabel() returning " + label);
             }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
index 86ad52d..fc9754a 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
@@ -114,7 +114,7 @@
             case "temporary-service":
                 return setTemporaryService(pw);
             case "default-service-enabled":
-                return setDefaultServiceEnabled();
+                return setDefaultServiceEnabled(pw);
             default:
                 pw.println("Invalid set: " + what);
                 return -1;
@@ -159,10 +159,13 @@
         return 0;
     }
 
-    private int setDefaultServiceEnabled() {
+    private int setDefaultServiceEnabled(PrintWriter pw) {
         final int userId = getNextIntArgRequired();
-        final boolean enabled = Boolean.parseBoolean(getNextArg());
-        mService.setDefaultServiceEnabled(userId, enabled);
+        final boolean enabled = Boolean.parseBoolean(getNextArgRequired());
+        final boolean changed = mService.setDefaultServiceEnabled(userId, enabled);
+        if (!changed) {
+            pw.println("already " + enabled);
+        }
         return 0;
     }
 
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index c423f9c..d7d97b3 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -27,12 +27,10 @@
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
 
-import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerInternal;
-import android.app.AppGlobals;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.content.ComponentName;
@@ -44,12 +42,12 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.contentcapture.ActivityEvent;
 import android.service.contentcapture.ActivityEvent.ActivityEventType;
 import android.service.contentcapture.ContentCaptureService;
+import android.service.contentcapture.ContentCaptureServiceInfo;
 import android.service.contentcapture.IContentCaptureServiceCallback;
 import android.service.contentcapture.SnapshotData;
 import android.util.ArrayMap;
@@ -107,6 +105,9 @@
     @GuardedBy("mLock")
     private boolean mZombie;
 
+    @GuardedBy("mLock")
+    private ContentCaptureServiceInfo mInfo;
+
     // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
 
     ContentCapturePerUserService(@NonNull ContentCaptureManagerService master,
@@ -144,33 +145,9 @@
     @Override // from PerUserSystemService
     protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent)
             throws NameNotFoundException {
-
-        int flags = PackageManager.GET_META_DATA;
-        final boolean isTemp = isTemporaryServiceSetLocked();
-        if (!isTemp) {
-            flags |= PackageManager.MATCH_SYSTEM_ONLY;
-        }
-
-        ServiceInfo si;
-        try {
-            si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, flags, mUserId);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Could not get service for " + serviceComponent + ": " + e);
-            return null;
-        }
-        if (si == null) {
-            Slog.w(TAG, "Could not get serviceInfo for " + (isTemp ? " (temp)" : "(default system)")
-                    + " " + serviceComponent.flattenToShortString());
-            return null;
-        }
-        if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) {
-            Slog.w(TAG, "ContentCaptureService from '" + si.packageName
-                    + "' does not require permission "
-                    + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
-            throw new SecurityException("Service does not require permission "
-                    + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
-        }
-        return si;
+        mInfo = new ContentCaptureServiceInfo(getContext(), serviceComponent,
+                isTemporaryServiceSetLocked(), mUserId);
+        return mInfo.getServiceInfo();
     }
 
     @Override // from PerUserSystemService
@@ -490,9 +467,16 @@
     protected void dumpLocked(String prefix, PrintWriter pw) {
         super.dumpLocked(prefix, pw);
 
+        final String prefix2 = prefix + "  ";
+        pw.print(prefix); pw.print("Service Info: ");
+        if (mInfo == null) {
+            pw.println("N/A");
+        } else {
+            pw.println();
+            mInfo.dump(prefix2, pw);
+        }
         pw.print(prefix); pw.print("Zombie: "); pw.println(mZombie);
 
-        final String prefix2 = prefix + "  ";
         if (mRemoteService != null) {
             pw.print(prefix); pw.println("remote service:");
             mRemoteService.dump(prefix2, pw);
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index a85b69b..39f7f0f 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -127,6 +127,7 @@
     // discharge stats before the device dies.
     private int mCriticalBatteryLevel;
 
+    // TODO: Current args don't work since "--unplugged" flag was purposefully removed.
     private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" };
 
     private static final String DUMPSYS_DATA_PATH = "/data/system/";
@@ -734,6 +735,7 @@
         mLastBatteryLevelChangedSentMs = SystemClock.elapsedRealtime();
     }
 
+    // TODO: Current code doesn't work since "--unplugged" flag in BSS was purposefully removed.
     private void logBatteryStatsLocked() {
         IBinder batteryInfoService = ServiceManager.getService(BatteryStats.SERVICE_NAME);
         if (batteryInfoService == null) return;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b2ee686..c069729 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2561,19 +2561,11 @@
 
                     final boolean partialConnectivity =
                             (msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
-                                    // If user accepts partial connectivity network, NetworkMonitor
-                                    // will skip https probing. It will make partial connectivity
-                                    // network becomes valid. But user still need to know this
-                                    // network is limited. So, it's needed to refer to
-                                    // acceptPartialConnectivity to add
-                                    // NET_CAPABILITY_PARTIAL_CONNECTIVITY into NetworkCapabilities
-                                    // of this network. So that user can see "Limited connection"
-                                    // in the settings.
                                     || (nai.networkMisc.acceptPartialConnectivity
                                             && nai.partialConnectivity);
                     // Once a network is determined to have partial connectivity, it cannot
                     // go back to full connectivity without a disconnect.
-                    final boolean partialConnectivityChange =
+                    final boolean partialConnectivityChanged =
                             (partialConnectivity && !nai.partialConnectivity);
 
                     final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID);
@@ -2584,17 +2576,6 @@
                         nai.captivePortalLoginNotified = true;
                         showNetworkNotification(nai, NotificationType.LOGGED_IN);
                     }
-                    // If this network has just connected and partial connectivity has just been
-                    // detected, tell NetworkMonitor if the user accepted partial connectivity on a
-                    // previous connect.
-                    if ((msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
-                            && nai.networkMisc.acceptPartialConnectivity) {
-                        try {
-                            nai.networkMonitor().notifyAcceptPartialConnectivity();
-                        } catch (RemoteException e) {
-                            e.rethrowFromSystemServer();
-                        }
-                    }
 
                     final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";
 
@@ -2624,7 +2605,7 @@
                             mNotifier.clearNotification(nai.network.netId,
                                     NotificationType.LOST_INTERNET);
                         }
-                    } else if (partialConnectivityChange) {
+                    } else if (partialConnectivityChanged) {
                         nai.partialConnectivity = partialConnectivity;
                         updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
                     }
@@ -3378,8 +3359,11 @@
             // Tear down the network.
             teardownUnneededNetwork(nai);
         } else {
+            // Inform NetworkMonitor that partial connectivity is acceptable. This will likely
+            // result in a partial connectivity result which will be processed by
+            // maybeHandleNetworkMonitorMessage.
             try {
-                nai.networkMonitor().notifyAcceptPartialConnectivity();
+                nai.networkMonitor().setAcceptPartialConnectivity();
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             }
@@ -3587,6 +3571,9 @@
         // because we're already prompting the user to sign in.
         if (nai == null || nai.everValidated || nai.everCaptivePortalDetected
                 || !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated
+                // TODO: Once the value of acceptPartialConnectivity is moved to IpMemoryStore,
+                // we should reevaluate how to handle acceptPartialConnectivity when network just
+                // connected.
                 || nai.networkMisc.acceptPartialConnectivity) {
             return;
         }
@@ -6395,6 +6382,9 @@
             // NetworkMonitor seeing the correct LinkProperties when starting.
             // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
             try {
+                if (networkAgent.networkMisc.acceptPartialConnectivity) {
+                    networkAgent.networkMonitor().setAcceptPartialConnectivity();
+                }
                 networkAgent.networkMonitor().notifyNetworkConnected();
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
diff --git a/services/core/java/com/android/server/DynamicAndroidService.java b/services/core/java/com/android/server/DynamicAndroidService.java
index 8488941..b02bfb1 100644
--- a/services/core/java/com/android/server/DynamicAndroidService.java
+++ b/services/core/java/com/android/server/DynamicAndroidService.java
@@ -25,6 +25,7 @@
 import android.os.IDynamicAndroidService;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.util.Slog;
 
 /**
@@ -34,6 +35,7 @@
 public class DynamicAndroidService extends IDynamicAndroidService.Stub implements DeathRecipient {
     private static final String TAG = "DynamicAndroidService";
     private static final String NO_SERVICE_ERROR = "no gsiservice";
+    private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
 
     private Context mContext;
     private volatile IGsiService mGsiService;
@@ -66,12 +68,27 @@
 
     private IGsiService getGsiService() throws RemoteException {
         checkPermission();
-        synchronized (this) {
-            if (mGsiService == null) {
-                mGsiService = connect(this);
-            }
-            return mGsiService;
+        if (!"running".equals(SystemProperties.get("init.svc.gsid"))) {
+            SystemProperties.set("ctl.start", "gsid");
         }
+        for (int sleepMs = 64; sleepMs <= (GSID_ROUGH_TIMEOUT_MS << 1); sleepMs <<= 1) {
+            try {
+                Thread.sleep(sleepMs);
+            } catch (InterruptedException e) {
+                Slog.e(TAG, "Interrupted when waiting for GSID");
+                break;
+            }
+            if ("running".equals(SystemProperties.get("init.svc.gsid"))) {
+                synchronized (this) {
+                    if (mGsiService == null) {
+                        mGsiService = connect(this);
+                    }
+                    return mGsiService;
+                }
+            }
+        }
+        Slog.e(TAG, "Unable to start gsid");
+        return null;
     }
 
     private void checkPermission() {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 6ef5b54..b89223b 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -64,6 +64,7 @@
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationRequest;
+import android.location.LocationTime;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -1824,12 +1825,7 @@
     @GuardedBy("mLock")
     private void removeProviderLocked(LocationProvider provider) {
         if (mProviders.remove(provider)) {
-            long identity = Binder.clearCallingIdentity();
-            try {
-                provider.onUseableChangedLocked(false);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
+            provider.onUseableChangedLocked(false);
         }
     }
 
@@ -2108,7 +2104,9 @@
         WorkSource worksource = new WorkSource();
         ProviderRequest providerRequest = new ProviderRequest();
 
-        if (records != null && !records.isEmpty()) {
+        // if provider is not active, it should not respond to requests
+
+        if (mProviders.contains(provider) && records != null && !records.isEmpty()) {
             long backgroundThrottleInterval;
 
             long identity = Binder.clearCallingIdentity();
@@ -2698,6 +2696,19 @@
     }
 
     @Override
+    public LocationTime getGnssTimeMillis() {
+        synchronized (mLock) {
+            Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
+            if (location == null) {
+                return null;
+            }
+            long currentNanos = SystemClock.elapsedRealtimeNanos();
+            long deltaMs = (currentNanos - location.getElapsedRealtimeNanos()) / 1000000L;
+            return new LocationTime(location.getTime() + deltaMs, currentNanos);
+        }
+    }
+
+    @Override
     public boolean injectLocation(Location location) {
         mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
                 "Location Hardware permission not granted to inject location");
@@ -2943,7 +2954,7 @@
     }
 
     @Override
-    public int getGnssCapabilities(String packageName) {
+    public long getGnssCapabilities(String packageName) {
         mContext.enforceCallingPermission(
                 android.Manifest.permission.LOCATION_HARDWARE,
                 "Location Hardware permission not granted to obtain GNSS chipset capabilities.");
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index d3298b9..61a7182 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -39,7 +39,6 @@
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_TETHERING;
 
-import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
 
 import android.annotation.NonNull;
@@ -70,7 +69,6 @@
 import android.os.IBinder;
 import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
-import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -112,13 +110,11 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.CountDownLatch;
 
 /**
  * @hide
  */
-public class NetworkManagementService extends INetworkManagementService.Stub
-        implements Watchdog.Monitor {
+public class NetworkManagementService extends INetworkManagementService.Stub {
 
     /**
      * Helper class that encapsulates NetworkManagementService dependencies and makes them
@@ -138,8 +134,6 @@
 
     private static final String TAG = "NetworkManagement";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final String NETD_TAG = "NetdConnector";
-    static final String NETD_SERVICE_NAME = "netd";
 
     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
 
@@ -149,44 +143,6 @@
      */
     public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
 
-    static class NetdResponseCode {
-        /* Keep in sync with system/netd/server/ResponseCode.h */
-        public static final int InterfaceListResult       = 110;
-        public static final int TetherInterfaceListResult = 111;
-        public static final int TetherDnsFwdTgtListResult = 112;
-        public static final int TtyListResult             = 113;
-        public static final int TetheringStatsListResult  = 114;
-
-        public static final int TetherStatusResult        = 210;
-        public static final int IpFwdStatusResult         = 211;
-        public static final int InterfaceGetCfgResult     = 213;
-        public static final int SoftapStatusResult        = 214;
-        public static final int InterfaceRxCounterResult  = 216;
-        public static final int InterfaceTxCounterResult  = 217;
-        public static final int QuotaCounterResult        = 220;
-        public static final int TetheringStatsResult      = 221;
-        public static final int DnsProxyQueryResult       = 222;
-        public static final int ClatdStatusResult         = 223;
-
-        public static final int InterfaceChange           = 600;
-        public static final int BandwidthControl          = 601;
-        public static final int InterfaceClassActivity    = 613;
-        public static final int InterfaceAddressChange    = 614;
-        public static final int InterfaceDnsServerInfo    = 615;
-        public static final int RouteChange               = 616;
-        public static final int StrictCleartext           = 617;
-    }
-
-    /**
-     * String indicating a softap command.
-     */
-    static final String SOFT_AP_COMMAND = "softap";
-
-    /**
-     * String passed back to netd connector indicating softap command success.
-     */
-    static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
-
     static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
 
     static final boolean MODIFY_OPERATION_ADD = true;
@@ -197,12 +153,6 @@
      */
     private final Context mContext;
 
-    /**
-     * connector object for communicating with netd
-     */
-    private final NativeDaemonConnector mConnector;
-
-    private final Handler mFgHandler;
     private final Handler mDaemonHandler;
 
     private final SystemServices mServices;
@@ -213,9 +163,6 @@
 
     private IBatteryStats mBatteryStats;
 
-    private final Thread mThread;
-    private CountDownLatch mConnectedSignal = new CountDownLatch(1);
-
     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
             new RemoteCallbackList<>();
 
@@ -307,32 +254,14 @@
      * @param context  Binder context for this service
      */
     private NetworkManagementService(
-            Context context, String socket, SystemServices services) {
+            Context context, SystemServices services) {
         mContext = context;
         mServices = services;
 
-        // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
-        mFgHandler = new Handler(FgThread.get().getLooper());
-
-        // Don't need this wake lock, since we now have a time stamp for when
-        // the network actually went inactive.  (It might be nice to still do this,
-        // but I don't want to do it through the power manager because that pollutes the
-        // battery stats history with pointless noise.)
-        //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
-
-        mConnector = new NativeDaemonConnector(
-                new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
-                FgThread.get().getLooper());
-        mThread = new Thread(mConnector, NETD_TAG);
-
         mDaemonHandler = new Handler(FgThread.get().getLooper());
 
         mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
 
-        // Add ourself to the Watchdog monitors.
-        Watchdog.getInstance().addMonitor(this);
-
         mServices.registerLocalService(new LocalService());
 
         synchronized (mTetheringStatsProviders) {
@@ -342,25 +271,17 @@
 
     @VisibleForTesting
     NetworkManagementService() {
-        mConnector = null;
         mContext = null;
         mDaemonHandler = null;
-        mFgHandler = null;
-        mThread = null;
         mServices = null;
         mNetdUnsolicitedEventListener = null;
     }
 
-    static NetworkManagementService create(Context context, String socket, SystemServices services)
+    static NetworkManagementService create(Context context, SystemServices services)
             throws InterruptedException {
         final NetworkManagementService service =
-                new NetworkManagementService(context, socket, services);
-        final CountDownLatch connectedSignal = service.mConnectedSignal;
+                new NetworkManagementService(context, services);
         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
-        service.mThread.start();
-        if (DBG) Slog.d(TAG, "Awaiting socket connection");
-        connectedSignal.await();
-        if (DBG) Slog.d(TAG, "Connected");
         if (DBG) Slog.d(TAG, "Connecting native netd service");
         service.connectNativeNetdService();
         if (DBG) Slog.d(TAG, "Connected");
@@ -368,7 +289,7 @@
     }
 
     public static NetworkManagementService create(Context context) throws InterruptedException {
-        return create(context, NETD_SERVICE_NAME, new SystemServices());
+        return create(context, new SystemServices());
     }
 
     public void systemReady() {
@@ -812,212 +733,6 @@
     }
 
     //
-    // Netd Callback handling
-    //
-
-    private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
-        @Override
-        public void onDaemonConnected() {
-            Slog.i(TAG, "onDaemonConnected()");
-            // event is dispatched from internal NDC thread, so we prepare the
-            // daemon back on main thread.
-            if (mConnectedSignal != null) {
-                // The system is booting and we're connecting to netd for the first time.
-                mConnectedSignal.countDown();
-                mConnectedSignal = null;
-            } else {
-                // We're reconnecting to netd after the socket connection
-                // was interrupted (e.g., if it crashed).
-                mFgHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        connectNativeNetdService();
-                        prepareNativeDaemon();
-                    }
-                });
-            }
-        }
-
-        @Override
-        public boolean onCheckHoldWakeLock(int code) {
-            return code == NetdResponseCode.InterfaceClassActivity;
-        }
-
-        @Override
-        public boolean onEvent(int code, String raw, String[] cooked) {
-            String errorMessage = String.format("Invalid event from daemon (%s)", raw);
-            switch (code) {
-            case NetdResponseCode.InterfaceChange:
-                    /*
-                     * a network interface change occured
-                     * Format: "NNN Iface added <name>"
-                     *         "NNN Iface removed <name>"
-                     *         "NNN Iface changed <name> <up/down>"
-                     *         "NNN Iface linkstatus <name> <up/down>"
-                     */
-                    if (cooked.length < 4 || !cooked[1].equals("Iface")) {
-                        throw new IllegalStateException(errorMessage);
-                    }
-                    if (cooked[2].equals("added")) {
-                        notifyInterfaceAdded(cooked[3]);
-                        return true;
-                    } else if (cooked[2].equals("removed")) {
-                        notifyInterfaceRemoved(cooked[3]);
-                        return true;
-                    } else if (cooked[2].equals("changed") && cooked.length == 5) {
-                        notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
-                        return true;
-                    } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
-                        notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
-                        return true;
-                    }
-                    throw new IllegalStateException(errorMessage);
-                    // break;
-            case NetdResponseCode.BandwidthControl:
-                    /*
-                     * Bandwidth control needs some attention
-                     * Format: "NNN limit alert <alertName> <ifaceName>"
-                     */
-                    if (cooked.length < 5 || !cooked[1].equals("limit")) {
-                        throw new IllegalStateException(errorMessage);
-                    }
-                    if (cooked[2].equals("alert")) {
-                        notifyLimitReached(cooked[3], cooked[4]);
-                        return true;
-                    }
-                    throw new IllegalStateException(errorMessage);
-                    // break;
-            case NetdResponseCode.InterfaceClassActivity:
-                    /*
-                     * An network interface class state changed (active/idle)
-                     * Format: "NNN IfaceClass <active/idle> <label>"
-                     */
-                    if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
-                        throw new IllegalStateException(errorMessage);
-                    }
-                    long timestampNanos = 0;
-                    int processUid = -1;
-                    if (cooked.length >= 5) {
-                        try {
-                            timestampNanos = Long.parseLong(cooked[4]);
-                            if (cooked.length == 6) {
-                                processUid = Integer.parseInt(cooked[5]);
-                            }
-                        } catch(NumberFormatException ne) {}
-                    } else {
-                        timestampNanos = SystemClock.elapsedRealtimeNanos();
-                    }
-                    boolean isActive = cooked[2].equals("active");
-                    notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
-                            isActive, timestampNanos, processUid, false);
-                    return true;
-                    // break;
-            case NetdResponseCode.InterfaceAddressChange:
-                    /*
-                     * A network address change occurred
-                     * Format: "NNN Address updated <addr> <iface> <flags> <scope>"
-                     *         "NNN Address removed <addr> <iface> <flags> <scope>"
-                     */
-                    if (cooked.length < 7 || !cooked[1].equals("Address")) {
-                        throw new IllegalStateException(errorMessage);
-                    }
-
-                    String iface = cooked[4];
-                    LinkAddress address;
-                    try {
-                        int flags = Integer.parseInt(cooked[5]);
-                        int scope = Integer.parseInt(cooked[6]);
-                        address = new LinkAddress(cooked[3], flags, scope);
-                    } catch(NumberFormatException e) {     // Non-numeric lifetime or scope.
-                        throw new IllegalStateException(errorMessage, e);
-                    } catch(IllegalArgumentException e) {  // Malformed/invalid IP address.
-                        throw new IllegalStateException(errorMessage, e);
-                    }
-
-                    if (cooked[2].equals("updated")) {
-                        notifyAddressUpdated(iface, address);
-                    } else {
-                        notifyAddressRemoved(iface, address);
-                    }
-                    return true;
-                    // break;
-            case NetdResponseCode.InterfaceDnsServerInfo:
-                    /*
-                     * Information about available DNS servers has been received.
-                     * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"
-                     */
-                    long lifetime;  // Actually a 32-bit unsigned integer.
-
-                    if (cooked.length == 6 &&
-                        cooked[1].equals("DnsInfo") &&
-                        cooked[2].equals("servers")) {
-                        try {
-                            lifetime = Long.parseLong(cooked[4]);
-                        } catch (NumberFormatException e) {
-                            throw new IllegalStateException(errorMessage);
-                        }
-                        String[] servers = cooked[5].split(",");
-                        notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
-                    }
-                    return true;
-                    // break;
-            case NetdResponseCode.RouteChange:
-                    /*
-                     * A route has been updated or removed.
-                     * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
-                     */
-                    if (!cooked[1].equals("Route") || cooked.length < 6) {
-                        throw new IllegalStateException(errorMessage);
-                    }
-
-                    String via = null;
-                    String dev = null;
-                    boolean valid = true;
-                    for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
-                        if (cooked[i].equals("dev")) {
-                            if (dev == null) {
-                                dev = cooked[i+1];
-                            } else {
-                                valid = false;  // Duplicate interface.
-                            }
-                        } else if (cooked[i].equals("via")) {
-                            if (via == null) {
-                                via = cooked[i+1];
-                            } else {
-                                valid = false;  // Duplicate gateway.
-                            }
-                        } else {
-                            valid = false;      // Unknown syntax.
-                        }
-                    }
-                    if (valid) {
-                        try {
-                            // InetAddress.parseNumericAddress(null) inexplicably returns ::1.
-                            InetAddress gateway = null;
-                            if (via != null) gateway = InetAddress.parseNumericAddress(via);
-                            RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
-                            notifyRouteChange(cooked[2].equals("updated"), route);
-                            return true;
-                        } catch (IllegalArgumentException e) {}
-                    }
-                    throw new IllegalStateException(errorMessage);
-                    // break;
-            case NetdResponseCode.StrictCleartext:
-                final int uid = Integer.parseInt(cooked[1]);
-                final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
-                try {
-                    ActivityManager.getService().notifyCleartextNetwork(uid, firstPacket);
-                } catch (RemoteException ignored) {
-                }
-                break;
-            default: break;
-            }
-            return false;
-        }
-    }
-
-
-    //
     // INetworkManagementService members
     //
     @Override
@@ -1439,42 +1154,6 @@
     }
 
     @Override
-    public String[] listTtys() {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            return NativeDaemonEvent.filterMessageList(
-                    mConnector.executeForList("list_ttys"), TtyListResult);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-    }
-
-    @Override
-    public void attachPppd(
-            String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            mConnector.execute("pppd", "attach", tty,
-                    NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
-                    NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
-                    NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
-                    NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-    }
-
-    @Override
-    public void detachPppd(String tty) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            mConnector.execute("pppd", "detach", tty);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-    }
-
-    @Override
     public void addIdleTimer(String iface, int timeout, final int type) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
@@ -2295,22 +1974,10 @@
         }
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public void monitor() {
-        if (mConnector != null) {
-            mConnector.monitor();
-        }
-    }
-
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
-        pw.println("NetworkManagementService NativeDaemonConnector Log:");
-        mConnector.dump(fd, pw, args);
-        pw.println();
-
         pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
                 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
         pw.print("mNetworkActive="); pw.println(mNetworkActive);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 19b0bf7..077920c 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -21,6 +21,9 @@
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
 import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
@@ -74,6 +77,7 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
@@ -208,6 +212,13 @@
     private static final boolean ENABLE_LEGACY_GREYLIST = SystemProperties
             .getBoolean(StorageManager.PROP_LEGACY_GREYLIST, true);
 
+    /**
+     * If {@code 1}, enables the isolated storage feature. If {@code -1},
+     * disables the isolated storage feature. If {@code 0}, uses the default
+     * value from the build system.
+     */
+    private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
+
     public static class Lifecycle extends SystemService {
         private StorageManagerService mStorageManagerService;
 
@@ -294,6 +305,19 @@
     private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
     private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
 
+    private static final String[] LEGACY_STORAGE_PERMISSIONS = {
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE
+    };
+
+    private static final String[] ALL_STORAGE_PERMISSIONS = {
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE,
+            Manifest.permission.READ_MEDIA_AUDIO,
+            Manifest.permission.READ_MEDIA_VIDEO,
+            Manifest.permission.READ_MEDIA_IMAGES
+    };
+
     private final AtomicFile mSettingsFile;
 
     /**
@@ -797,7 +821,7 @@
                 }
             });
         // For now, simply clone property when it changes
-        DeviceConfig.addOnPropertyChangedListener(DeviceConfig.Storage.NAMESPACE,
+        DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_STORAGE,
                 mContext.getMainExecutor(), (namespace, name, value) -> {
                     refreshIsolatedStorageSettings();
                 });
@@ -837,8 +861,7 @@
         // Always copy value from newer DeviceConfig location
         Settings.Global.putString(mResolver,
                 Settings.Global.ISOLATED_STORAGE_REMOTE,
-                DeviceConfig.getProperty(DeviceConfig.Storage.NAMESPACE,
-                        DeviceConfig.Storage.ISOLATED_STORAGE_ENABLED));
+                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE, ISOLATED_STORAGE_ENABLED));
 
         final int local = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
@@ -1668,16 +1691,18 @@
 
         synchronized (mLock) {
             final boolean thisIsolatedStorage = StorageManager.hasIsolatedStorage();
-            if (mLastIsolatedStorage == thisIsolatedStorage) {
-                // Nothing changed since last boot; keep rolling forward
-                return;
-            } else if (thisIsolatedStorage) {
-                // This boot enables isolated storage; apply legacy behavior
-                applyLegacyStorage();
+            if (mLastIsolatedStorage != thisIsolatedStorage) {
+                if (thisIsolatedStorage) {
+                    // This boot enables isolated storage; apply legacy behavior
+                    applyLegacyStorage();
+                }
+
+                // Always remember the new state we just booted with
+                writeSettingsLocked();
             }
 
-            // Always remember the new state we just booted with
-            writeSettingsLocked();
+            // Execute special logic to recover certain devices
+            recoverFrom128872367();
         }
     }
 
@@ -1685,23 +1710,27 @@
      * If we're enabling isolated storage, we need to remember which existing
      * apps have already been using shared storage, and grant them legacy access
      * to keep them running smoothly.
+     *
+     * @see com.android.server.pm.permission.PermissionManagerService
+     *      #applyLegacyStoragePermissionModel
      */
     private void applyLegacyStorage() {
         final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
         final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
         for (int userId : um.getUserIds()) {
+            final UserHandle user = UserHandle.of(userId);
             final PackageManager pm;
             try {
-                pm = mContext.createPackageContextAsUser(mContext.getPackageName(),
-                        0, UserHandle.of(userId)).getPackageManager();
+                pm = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
+                        user).getPackageManager();
             } catch (PackageManager.NameNotFoundException e) {
                 throw new RuntimeException(e);
             }
 
-            final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(new String[] {
-                    android.Manifest.permission.READ_EXTERNAL_STORAGE,
-                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE
-            }, MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
+            final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(
+                    LEGACY_STORAGE_PERMISSIONS,
+                    MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
+                            | GET_PERMISSIONS);
             for (PackageInfo pkg : pkgs) {
                 final int uid = pkg.applicationInfo.uid;
                 final String packageName = pkg.applicationInfo.packageName;
@@ -1714,8 +1743,28 @@
                 Log.d(TAG, "Found " + uid + " " + packageName
                         + " with granted storage access, last accessed " + lastAccess);
                 if (lastAccess > 0) {
-                    appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE,
-                            uid, packageName, AppOpsManager.MODE_ALLOWED);
+                    appOps.setUidMode(AppOpsManager.OP_LEGACY_STORAGE, uid,
+                            AppOpsManager.MODE_ALLOWED);
+
+                    // Grandfather pre-Q app by granting all permissions and fixing them. The user
+                    // needs to uninstall the app to revoke the permissions.
+                    // TODO: Deal with shard Uids
+                    if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
+                        for (String perm : ALL_STORAGE_PERMISSIONS) {
+                            if (ArrayUtils.contains(pkg.requestedPermissions, perm)) {
+                                pm.grantRuntimePermission(packageName, perm, user);
+
+                                int flags = FLAG_PERMISSION_SYSTEM_FIXED;
+                                if (!ArrayUtils.contains(LEGACY_STORAGE_PERMISSIONS, perm)) {
+                                    flags |= FLAG_PERMISSION_HIDDEN;
+                                }
+
+                                pm.updatePermissionFlags(perm, packageName,
+                                        FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_HIDDEN,
+                                        flags, user);
+                            }
+                        }
+                    }
                 }
             }
         }
@@ -1734,6 +1783,69 @@
         return maxTime;
     }
 
+    /**
+     * In b/128872367 we lost all app-ops on devices in the wild. This logic
+     * attempts to detect and recover from this by granting
+     * {@link AppOpsManager#OP_LEGACY_STORAGE} to any apps installed before
+     * isolated storage was enabled.
+     */
+    private void recoverFrom128872367() {
+        // We're interested in packages that were installed or updated between
+        // 1/1/2014 and 12/17/2018
+        final long START_TIMESTAMP = 1388534400000L;
+        final long END_TIMESTAMP = 1545004800000L;
+
+        final PackageManager pm = mContext.getPackageManager();
+        final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
+        final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
+
+        boolean activeDuringWindow = false;
+        List<PackageInfo> pendingHolders = new ArrayList<>();
+
+        for (int userId : um.getUserIds()) {
+            final List<PackageInfo> pkgs = pm.getInstalledPackagesAsUser(MATCH_UNINSTALLED_PACKAGES
+                    | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
+            for (PackageInfo pkg : pkgs) {
+                // Determine if any apps on this device had been installed or
+                // updated during the period where the feature was disabled
+                activeDuringWindow |= (pkg.firstInstallTime > START_TIMESTAMP
+                        && pkg.firstInstallTime < END_TIMESTAMP);
+                activeDuringWindow |= (pkg.lastUpdateTime > START_TIMESTAMP
+                        && pkg.lastUpdateTime < END_TIMESTAMP);
+
+                // This app should hold legacy op if they were installed before
+                // the cutoff; we only check the end boundary here so that
+                // include system apps, which are always installed on 1/1/2009.
+                final boolean shouldHold = (pkg.firstInstallTime < END_TIMESTAMP);
+                final boolean doesHold = (appOps.checkOpNoThrow(OP_LEGACY_STORAGE,
+                        pkg.applicationInfo.uid,
+                        pkg.applicationInfo.packageName) == MODE_ALLOWED);
+
+                if (doesHold) {
+                    Slog.d(TAG, "Found " + pkg + " holding legacy op; skipping recovery");
+                    return;
+                } else if (shouldHold) {
+                    Slog.d(TAG, "Found " + pkg + " that should hold legacy op");
+                    pendingHolders.add(pkg);
+                }
+            }
+        }
+
+        if (!activeDuringWindow) {
+            Slog.d(TAG, "No packages were active during the time window; skipping grants");
+            return;
+        }
+
+        // If we made it this far, nobody actually holds the legacy op, which
+        // means we probably lost the database, and we should grant the op to
+        // all the apps we identified.
+        for (PackageInfo pkg : pendingHolders) {
+            appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE,
+                    pkg.applicationInfo.uid,
+                    pkg.applicationInfo.packageName, AppOpsManager.MODE_ALLOWED);
+        }
+    }
+
     private void systemReady() {
         LocalServices.getService(ActivityTaskManagerInternal.class)
                 .registerScreenObserver(this);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8225476..97cc756 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1273,11 +1273,13 @@
 
     static final class ProcessChangeItem {
         static final int CHANGE_ACTIVITIES = 1<<0;
+        static final int CHANGE_FOREGROUND_SERVICES = 1<<1;
         int changes;
         int uid;
         int pid;
         int processState;
         boolean foregroundActivities;
+        int foregroundServiceTypes;
     }
 
     static final class UidObserverRegistration {
@@ -2935,7 +2937,8 @@
             }
         }
         if (mContentCaptureService != null && (event == Event.ACTIVITY_PAUSED
-                || event == Event.ACTIVITY_RESUMED || event == Event.ACTIVITY_STOPPED)) {
+                || event == Event.ACTIVITY_RESUMED || event == Event.ACTIVITY_STOPPED
+                || event == Event.ACTIVITY_DESTROYED)) {
             mContentCaptureService.notifyActivityEvent(userId, activity, event);
         }
     }
@@ -3079,6 +3082,13 @@
                             observer.onForegroundActivitiesChanged(item.pid, item.uid,
                                     item.foregroundActivities);
                         }
+                        if ((item.changes & ProcessChangeItem.CHANGE_FOREGROUND_SERVICES) != 0) {
+                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                                    "FOREGROUND SERVICES CHANGED pid=" + item.pid + " uid="
+                                            + item.uid + ": " + item.foregroundServiceTypes);
+                            observer.onForegroundServicesChanged(item.pid, item.uid,
+                                    item.foregroundServiceTypes);
+                        }
                     }
                 } catch (RemoteException e) {
                 }
@@ -3093,6 +3103,47 @@
         }
     }
 
+    @GuardedBy("this")
+    ProcessChangeItem enqueueProcessChangeItemLocked(int uid, int pid) {
+        int i = mPendingProcessChanges.size()-1;
+        ActivityManagerService.ProcessChangeItem item = null;
+        while (i >= 0) {
+            item = mPendingProcessChanges.get(i);
+            if (item.pid == pid) {
+                if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                        "Re-using existing item: " + item);
+                break;
+            }
+            i--;
+        }
+
+        if (i < 0) {
+            // No existing item in pending changes; need a new one.
+            final int NA = mAvailProcessChanges.size();
+            if (NA > 0) {
+                item = mAvailProcessChanges.remove(NA-1);
+                if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                        "Retrieving available item: " + item);
+            } else {
+                item = new ActivityManagerService.ProcessChangeItem();
+                if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                        "Allocating new item: " + item);
+            }
+            item.changes = 0;
+            item.pid = pid;
+            item.uid = uid;
+            if (mPendingProcessChanges.size() == 0) {
+                if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                        "*** Enqueueing dispatch processes changed!");
+                mUiHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED_UI_MSG)
+                        .sendToTarget();
+            }
+            mPendingProcessChanges.add(item);
+        }
+
+        return item;
+    }
+
     private void dispatchProcessDied(int pid, int uid) {
         int i = mProcessObservers.beginBroadcast();
         while (i > 0) {
@@ -16275,11 +16326,12 @@
     @GuardedBy("this")
     final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
             int fgServiceTypes, boolean oomAdj) {
+        proc.setHasForegroundServices(isForeground, fgServiceTypes);
+
         final boolean hasFgServiceLocationType =
                 (fgServiceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION) != 0;
         if (isForeground != proc.hasForegroundServices()
                 || proc.hasLocationForegroundServices() != hasFgServiceLocationType) {
-            proc.setHasForegroundServices(isForeground, fgServiceTypes);
             ArrayList<ProcessRecord> curProcs = mForegroundPackages.get(proc.info.packageName,
                     proc.info.uid);
             if (isForeground) {
@@ -16308,6 +16360,13 @@
                 updateOomAdjLocked();
             }
         }
+
+        if (proc.getForegroundServiceTypes() != fgServiceTypes) {
+            proc.setReportedForegroundServiceTypes(fgServiceTypes);
+            ProcessChangeItem item = enqueueProcessChangeItemLocked(proc.info.uid, proc.pid);
+            item.changes = ProcessChangeItem.CHANGE_FOREGROUND_SERVICES;
+            item.foregroundServiceTypes = fgServiceTypes;
+        }
     }
 
     // TODO(b/111541062): This method is only used for updating OOM adjustments. We need to update
@@ -18101,6 +18160,34 @@
         public void prepareForPossibleShutdown() {
             ActivityManagerService.this.prepareForPossibleShutdown();
         }
+
+        @Override
+        public boolean hasRunningForegroundService(int uid, int foregroundServicetype) {
+            synchronized (ActivityManagerService.this) {
+                for (int i = 0; i < mProcessList.mLruProcesses.size(); i++) {
+                    final ProcessRecord pr = mProcessList.mLruProcesses.get(i);
+                    if (pr.uid != uid) {
+                        continue;
+                    }
+
+                    if ((pr.getForegroundServiceTypes() & foregroundServicetype) != 0) {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        @Override
+        public void registerProcessObserver(IProcessObserver processObserver) {
+            ActivityManagerService.this.registerProcessObserver(processObserver);
+        }
+
+        @Override
+        public void unregisterProcessObserver(IProcessObserver processObserver) {
+            ActivityManagerService.this.unregisterProcessObserver(processObserver);
+        }
     }
 
     long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
index 438538f..9216343 100644
--- a/services/core/java/com/android/server/am/AppCompactor.java
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -230,11 +230,8 @@
      */
     @GuardedBy("mPhenotypeFlagLock")
     private void updateUseCompaction() {
-        String useCompactionFlag =
-                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
-                    KEY_USE_COMPACTION);
-        mUseCompaction = TextUtils.isEmpty(useCompactionFlag)
-                ? DEFAULT_USE_COMPACTION : Boolean.parseBoolean(useCompactionFlag);
+        mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                    KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION);
         if (mUseCompaction && !mCompactionThread.isAlive()) {
             mCompactionThread.start();
             mCompactionHandler = new MemCompactionHandler();
@@ -243,28 +240,11 @@
 
     @GuardedBy("mPhenotypeFlagLock")
     private void updateCompactionActions() {
-        String compactAction1Flag =
-                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
-                        KEY_COMPACT_ACTION_1);
-        String compactAction2Flag =
-                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
-                        KEY_COMPACT_ACTION_2);
+        int compactAction1 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_COMPACT_ACTION_1, DEFAULT_COMPACT_ACTION_1);
 
-        int compactAction1 = DEFAULT_COMPACT_ACTION_1;
-        try {
-            compactAction1 = TextUtils.isEmpty(compactAction1Flag)
-                    ? DEFAULT_COMPACT_ACTION_1 : Integer.parseInt(compactAction1Flag);
-        } catch (NumberFormatException e) {
-          // Do nothing, leave default.
-        }
-
-        int compactAction2 = DEFAULT_COMPACT_ACTION_2;
-        try {
-            compactAction2 = TextUtils.isEmpty(compactAction2Flag)
-                    ? DEFAULT_COMPACT_ACTION_2 : Integer.parseInt(compactAction2Flag);
-        } catch (NumberFormatException e) {
-            // Do nothing, leave default.
-        }
+        int compactAction2 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_COMPACT_ACTION_2, DEFAULT_COMPACT_ACTION_2);
 
         mCompactActionSome = compactActionIntToString(compactAction1);
         mCompactActionFull = compactActionIntToString(compactAction2);
@@ -312,14 +292,8 @@
 
     @GuardedBy("mPhenotypeFlagLock")
     private void updateStatsdSampleRate() {
-        String sampleRateFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
-                KEY_COMPACT_STATSD_SAMPLE_RATE);
-        try {
-            mStatsdSampleRate = TextUtils.isEmpty(sampleRateFlag)
-                    ? DEFAULT_STATSD_SAMPLE_RATE : Float.parseFloat(sampleRateFlag);
-        } catch (NumberFormatException e) {
-            mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
-        }
+        mStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_COMPACT_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE);
         mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
     }
 
diff --git a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
index c2f1890..1c916e9 100644
--- a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
+++ b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
@@ -17,7 +17,7 @@
 package com.android.server.am;
 
 import android.os.BatteryStats;
-import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED;
+import static android.os.BatteryStats.STATS_SINCE_CHARGED;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.health.HealthKeys;
@@ -63,20 +63,20 @@
 
         // MEASUREMENT_REALTIME_BATTERY_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_BATTERY_MS,
-                bs.computeBatteryRealtime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
+                bs.computeBatteryRealtime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);
 
         // MEASUREMENT_UPTIME_BATTERY_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_BATTERY_MS,
-                bs.computeBatteryUptime(mNowUptimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
+                bs.computeBatteryUptime(mNowUptimeMs*1000, STATS_SINCE_CHARGED)/1000);
 
         // MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS,
                 bs.computeBatteryScreenOffRealtime(
-                    mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
+                    mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);
 
         // MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS,
-                bs.computeBatteryScreenOffUptime(mNowUptimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
+                bs.computeBatteryScreenOffUptime(mNowUptimeMs*1000, STATS_SINCE_CHARGED)/1000);
 
         //
         // Now on to the real per-uid stats...
@@ -161,75 +161,75 @@
         if (controller != null) {
             // MEASUREMENT_WIFI_IDLE_MS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_IDLE_MS,
-                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
             // MEASUREMENT_WIFI_RX_MS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_MS,
-                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
             // MEASUREMENT_WIFI_TX_MS
             sum = 0;
             for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
-                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+                sum += counter.getCountLocked(STATS_SINCE_CHARGED);
             }
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_MS, sum);
             // MEASUREMENT_WIFI_POWER_MAMS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_POWER_MAMS,
-                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED));
         }
 
         controller = uid.getBluetoothControllerActivity();
         if (controller != null) {
             // MEASUREMENT_BLUETOOTH_IDLE_MS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_IDLE_MS,
-                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
             // MEASUREMENT_BLUETOOTH_RX_MS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_MS,
-                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
             // MEASUREMENT_BLUETOOTH_TX_MS
             sum = 0;
             for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
-                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+                sum += counter.getCountLocked(STATS_SINCE_CHARGED);
             }
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_MS, sum);
             // MEASUREMENT_BLUETOOTH_POWER_MAMS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_POWER_MAMS,
-                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED));
         }
 
         controller = uid.getModemControllerActivity();
         if (controller != null) {
             // MEASUREMENT_MOBILE_IDLE_MS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_IDLE_MS,
-                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
             // MEASUREMENT_MOBILE_RX_MS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_MS,
-                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED));
             // MEASUREMENT_MOBILE_TX_MS
             sum = 0;
             for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
-                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+                sum += counter.getCountLocked(STATS_SINCE_CHARGED);
             }
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_MS, sum);
             // MEASUREMENT_MOBILE_POWER_MAMS
             uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_POWER_MAMS,
-                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED));
         }
 
         // MEASUREMENT_WIFI_RUNNING_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RUNNING_MS,
-                uid.getWifiRunningTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
+                uid.getWifiRunningTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);
 
         // MEASUREMENT_WIFI_FULL_LOCK_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_FULL_LOCK_MS,
-                uid.getFullWifiLockTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
+                uid.getFullWifiLockTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);
 
         // TIMER_WIFI_SCAN
         uidWriter.addTimer(UidHealthStats.TIMER_WIFI_SCAN,
-                uid.getWifiScanCount(STATS_SINCE_UNPLUGGED),
-                uid.getWifiScanTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
+                uid.getWifiScanCount(STATS_SINCE_CHARGED),
+                uid.getWifiScanTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);
 
         // MEASUREMENT_WIFI_MULTICAST_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_MULTICAST_MS,
-                uid.getWifiMulticastTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
+                uid.getWifiMulticastTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000);
 
         // TIMER_AUDIO
         addTimer(uidWriter, UidHealthStats.TIMER_AUDIO, uid.getAudioTurnedOnTimer());
@@ -280,90 +280,90 @@
         // MEASUREMENT_OTHER_USER_ACTIVITY_COUNT
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_OTHER_USER_ACTIVITY_COUNT,
                 uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_OTHER,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT,
                 uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_BUTTON,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT,
                 uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_TOUCH,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_MOBILE_RX_BYTES
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_BYTES,
                 uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_RX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_MOBILE_TX_BYTES
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_BYTES,
                 uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_TX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_WIFI_RX_BYTES
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_BYTES,
                 uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_WIFI_TX_BYTES
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_BYTES,
                 uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_BLUETOOTH_RX_BYTES
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_BYTES,
                 uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_BLUETOOTH_TX_BYTES
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_BYTES,
                 uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_MOBILE_RX_PACKETS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_PACKETS,
                 uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_RX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_MOBILE_TX_PACKETS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_PACKETS,
                 uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_TX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_WIFI_RX_PACKETS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_PACKETS,
                 uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_WIFI_TX_PACKETS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_PACKETS,
                 uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_BLUETOOTH_RX_PACKETS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_PACKETS,
                 uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_RX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // MEASUREMENT_BLUETOOTH_TX_PACKETS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_PACKETS,
                 uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_TX_DATA,
-                    STATS_SINCE_UNPLUGGED));
+                    STATS_SINCE_CHARGED));
 
         // TIMER_MOBILE_RADIO_ACTIVE
         uidWriter.addTimer(UidHealthStats.TIMER_MOBILE_RADIO_ACTIVE,
-                uid.getMobileRadioActiveCount(STATS_SINCE_UNPLUGGED),
-                uid.getMobileRadioActiveTime(STATS_SINCE_UNPLUGGED));
+                uid.getMobileRadioActiveCount(STATS_SINCE_CHARGED),
+                uid.getMobileRadioActiveTime(STATS_SINCE_CHARGED));
 
         // MEASUREMENT_USER_CPU_TIME_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_MS,
-                uid.getUserCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000);
+                uid.getUserCpuTimeUs(STATS_SINCE_CHARGED)/1000);
 
         // MEASUREMENT_SYSTEM_CPU_TIME_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_MS,
-                uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000);
+                uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED)/1000);
 
         // MEASUREMENT_CPU_POWER_MAMS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS, 0);
@@ -393,27 +393,27 @@
     public void writeProc(HealthStatsWriter procWriter, BatteryStats.Uid.Proc proc) {
         // MEASUREMENT_USER_TIME_MS
         procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_USER_TIME_MS,
-                proc.getUserTime(STATS_SINCE_UNPLUGGED));
+                proc.getUserTime(STATS_SINCE_CHARGED));
 
         // MEASUREMENT_SYSTEM_TIME_MS
         procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_SYSTEM_TIME_MS,
-                proc.getSystemTime(STATS_SINCE_UNPLUGGED));
+                proc.getSystemTime(STATS_SINCE_CHARGED));
 
         // MEASUREMENT_STARTS_COUNT
         procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_STARTS_COUNT,
-                proc.getStarts(STATS_SINCE_UNPLUGGED));
+                proc.getStarts(STATS_SINCE_CHARGED));
 
         // MEASUREMENT_CRASHES_COUNT
         procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_CRASHES_COUNT,
-                proc.getNumCrashes(STATS_SINCE_UNPLUGGED));
+                proc.getNumCrashes(STATS_SINCE_CHARGED));
 
         // MEASUREMENT_ANR_COUNT
         procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_ANR_COUNT,
-                proc.getNumAnrs(STATS_SINCE_UNPLUGGED));
+                proc.getNumAnrs(STATS_SINCE_CHARGED));
 
         // MEASUREMENT_FOREGROUND_MS
         procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_FOREGROUND_MS,
-                proc.getForegroundTime(STATS_SINCE_UNPLUGGED));
+                proc.getForegroundTime(STATS_SINCE_CHARGED));
     }
 
     /**
@@ -434,7 +434,7 @@
             final BatteryStats.Counter counter = entry.getValue();
             if (counter != null) {
                 pkgWriter.addMeasurements(PackageHealthStats.MEASUREMENTS_WAKEUP_ALARMS_COUNT,
-                        entry.getKey(), counter.getCountLocked(STATS_SINCE_UNPLUGGED));
+                        entry.getKey(), counter.getCountLocked(STATS_SINCE_CHARGED));
             }
         }
     }
@@ -445,11 +445,11 @@
     public void writeServ(HealthStatsWriter servWriter, BatteryStats.Uid.Pkg.Serv serv) {
         // MEASUREMENT_START_SERVICE_COUNT
         servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_START_SERVICE_COUNT,
-                serv.getStarts(STATS_SINCE_UNPLUGGED));
+                serv.getStarts(STATS_SINCE_CHARGED));
 
         // MEASUREMENT_LAUNCH_COUNT
         servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_LAUNCH_COUNT,
-                serv.getLaunches(STATS_SINCE_UNPLUGGED));
+                serv.getLaunches(STATS_SINCE_CHARGED));
     }
 
     /**
@@ -457,8 +457,8 @@
      */
     private void addTimer(HealthStatsWriter writer, int key, BatteryStats.Timer timer) {
         if (timer != null) {
-            writer.addTimer(key, timer.getCountLocked(STATS_SINCE_UNPLUGGED),
-                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED) / 1000);
+            writer.addTimer(key, timer.getCountLocked(STATS_SINCE_CHARGED),
+                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_CHARGED) / 1000);
         }
     }
 
@@ -468,8 +468,8 @@
     private void addTimers(HealthStatsWriter writer, int key, String name,
             BatteryStats.Timer timer) {
         if (timer != null) {
-            writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_UNPLUGGED),
-                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED) / 1000));
+            writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_CHARGED),
+                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_CHARGED) / 1000));
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 9056f76..aa03de1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -38,7 +38,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS;
 import static com.android.server.am.ActivityManagerService.DISPATCH_OOM_ADJ_OBSERVER_MSG;
-import static com.android.server.am.ActivityManagerService.DISPATCH_PROCESSES_CHANGED_UI_MSG;
 import static com.android.server.am.ActivityManagerService.IDLE_UIDS_MSG;
 import static com.android.server.am.ActivityManagerService.TAG_BACKUP;
 import static com.android.server.am.ActivityManagerService.TAG_LRU;
@@ -1921,41 +1920,9 @@
         if (changes != 0) {
             if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
                     "Changes in " + app + ": " + changes);
-            int i = mService.mPendingProcessChanges.size()-1;
-            ActivityManagerService.ProcessChangeItem item = null;
-            while (i >= 0) {
-                item = mService.mPendingProcessChanges.get(i);
-                if (item.pid == app.pid) {
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
-                            "Re-using existing item: " + item);
-                    break;
-                }
-                i--;
-            }
-            if (i < 0) {
-                // No existing item in pending changes; need a new one.
-                final int NA = mService.mAvailProcessChanges.size();
-                if (NA > 0) {
-                    item = mService.mAvailProcessChanges.remove(NA-1);
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
-                            "Retrieving available item: " + item);
-                } else {
-                    item = new ActivityManagerService.ProcessChangeItem();
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
-                            "Allocating new item: " + item);
-                }
-                item.changes = 0;
-                item.pid = app.pid;
-                item.uid = app.info.uid;
-                if (mService.mPendingProcessChanges.size() == 0) {
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
-                            "*** Enqueueing dispatch processes changed!");
-                    mService.mUiHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED_UI_MSG)
-                            .sendToTarget();
-                }
-                mService.mPendingProcessChanges.add(item);
-            }
-            item.changes |= changes;
+            ActivityManagerService.ProcessChangeItem item =
+                    mService.enqueueProcessChangeItemLocked(app.pid, app.info.uid);
+            item.changes = changes;
             item.foregroundActivities = app.repForegroundActivities;
             if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
                     "Item " + Integer.toHexString(System.identityHashCode(item))
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 51b1ae1..17b244c 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -174,6 +174,7 @@
     boolean hasStartedServices; // Are there any started services running in this process?
     private boolean mHasForegroundServices; // Running any services that are foreground?
     private int mFgServiceTypes; // Type of foreground service, if there is a foreground service.
+    private int mRepFgServiceTypes; // Last reported foreground service types.
     private boolean mHasForegroundActivities; // Running any activities that are foreground?
     boolean repForegroundActivities; // Last reported foreground activities.
     boolean systemNoUi;         // This is a system process, but not currently showing UI.
@@ -1079,6 +1080,18 @@
                 && (mFgServiceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION) != 0;
     }
 
+    int getForegroundServiceTypes() {
+        return mHasForegroundServices ? mFgServiceTypes : 0;
+    }
+
+    int getReportedForegroundServiceTypes() {
+        return mRepFgServiceTypes;
+    }
+
+    void setReportedForegroundServiceTypes(int foregroundServiceTypes) {
+        mRepFgServiceTypes = foregroundServiceTypes;
+    }
+
     void setHasForegroundActivities(boolean hasForegroundActivities) {
         mHasForegroundActivities = hasForegroundActivities;
         mWindowProcessController.setHasForegroundActivities(hasForegroundActivities);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 9c26526..10b67c1 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1132,7 +1132,7 @@
                 .build();
         Preconditions.checkNotNull(callback, "callback cannot be null");
 
-        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
+        mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
                 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
 
         final String[] opNamesArray = (opNames != null)
@@ -1144,6 +1144,14 @@
     }
 
     @Override
+    public void reloadNonHistoricalState() {
+        mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
+                Binder.getCallingPid(), Binder.getCallingUid(), "reloadNonHistoricalState");
+        writeState();
+        readState();
+    }
+
+    @Override
     public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) {
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
@@ -2998,6 +3006,7 @@
 
                             final LongSparseArray keys = op.collectKeys();
                             if (keys == null || keys.size() <= 0) {
+                                out.endTag(null, "op");
                                 continue;
                             }
 
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 4e0380d..31ba0f2 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -19,6 +19,7 @@
 import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
@@ -113,6 +114,11 @@
         cancelAndUnbindLocked(peekUserStateLocked(userId));
     }
 
+    /** Returns {@code true} if attention service is configured on this device. */
+    public static boolean isServiceConfigured(Context context) {
+        return !TextUtils.isEmpty(getServiceConfig(context));
+    }
+
     /** Resolves and sets up the attention service if it had not been done yet. */
     private boolean isServiceAvailable() {
         if (mComponentName == null) {
@@ -285,6 +291,10 @@
         return mUserStates.get(userId);
     }
 
+    private static String getServiceConfig(Context context) {
+        return context.getString(R.string.config_defaultAttentionService);
+    }
+
     /**
      * Provides attention service component name at runtime, making sure it's provided by the
      * system.
@@ -293,9 +303,7 @@
         final String flag = DeviceConfig.getProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 COMPONENT_NAME);
 
-        final String componentNameString = flag != null ? flag : context.getString(
-                R.string.config_defaultAttentionService);
-
+        final String componentNameString = flag != null ? flag : getServiceConfig(context);
         if (TextUtils.isEmpty(componentNameString)) {
             return null;
         }
@@ -553,8 +561,8 @@
         }
     }
 
-    private void cancel(UserState userState, @AttentionFailureCodes int failureCode) {
-        if (userState != null && userState.mService != null) {
+    private void cancel(@NonNull UserState userState, @AttentionFailureCodes int failureCode) {
+        if (userState.mService != null) {
             try {
                 userState.mService.cancelAttentionCheck(
                         userState.mCurrentAttentionCheckRequestCode);
@@ -571,6 +579,9 @@
     @GuardedBy("mLock")
     private void cancelAndUnbindLocked(UserState userState) {
         synchronized (mLock) {
+            if (userState == null) {
+                return;
+            }
             cancel(userState, AttentionService.ATTENTION_FAILURE_UNKNOWN);
 
             mContext.unbindService(userState.mConnection);
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index f313e1d..516844d 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -628,6 +628,9 @@
                             null /* description */);
                     // Then give it the bundle to do magic behavior..
                     intent.putExtra(KeyguardManager.EXTRA_BIOMETRIC_PROMPT_BUNDLE, bundle);
+                    // Create a new task with this activity located at the root.
+                    intent.setFlags(
+                            Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
                     getContext().startActivityAsUser(intent, UserHandle.CURRENT);
                 });
                 return;
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 35d6860..0e3d82c 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -42,7 +42,6 @@
 import android.net.SocketKeepalive.InvalidPacketException;
 import android.net.SocketKeepalive.InvalidSocketException;
 import android.net.TcpKeepalivePacketData;
-import android.net.TcpKeepalivePacketData.TcpSocketInfo;
 import android.net.util.IpUtils;
 import android.os.Binder;
 import android.os.Handler;
@@ -492,19 +491,14 @@
             return;
         }
 
-        TcpKeepalivePacketData packet = null;
+        final TcpKeepalivePacketData packet;
         try {
-            TcpSocketInfo tsi = TcpKeepaliveController.switchToRepairMode(fd);
-            packet = TcpKeepalivePacketData.tcpKeepalivePacket(tsi);
+            packet = TcpKeepaliveController.getTcpKeepalivePacket(fd);
         } catch (InvalidPacketException | InvalidSocketException e) {
-            try {
-                TcpKeepaliveController.switchOutOfRepairMode(fd);
-            } catch (ErrnoException e1) {
-                Log.e(TAG, "Couldn't move fd out of repair mode after failure to start keepalive");
-            }
             notifyErrorCallback(cb, e.error);
             return;
         }
+
         KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
                 KeepaliveInfo.TYPE_TCP, fd);
         Log.d(TAG, "Created keepalive: " + ki.toString());
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index 3e21b5b..f4d9006 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -28,8 +28,10 @@
 
 import android.annotation.NonNull;
 import android.net.NetworkUtils;
+import android.net.SocketKeepalive.InvalidPacketException;
 import android.net.SocketKeepalive.InvalidSocketException;
-import android.net.TcpKeepalivePacketData.TcpSocketInfo;
+import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
 import android.net.TcpRepairWindow;
 import android.os.Handler;
 import android.os.MessageQueue;
@@ -44,7 +46,6 @@
 import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo;
 
 import java.io.FileDescriptor;
-import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.net.SocketException;
@@ -103,26 +104,30 @@
         mFdHandlerQueue = connectivityServiceHandler.getLooper().getQueue();
     }
 
+    /** Build tcp keepalive packet. */
+    public static TcpKeepalivePacketData getTcpKeepalivePacket(@NonNull FileDescriptor fd)
+            throws InvalidPacketException, InvalidSocketException {
+        try {
+            final TcpKeepalivePacketDataParcelable tcpDetails = switchToRepairMode(fd);
+            return TcpKeepalivePacketData.tcpKeepalivePacket(tcpDetails);
+        } catch (InvalidPacketException | InvalidSocketException e) {
+            switchOutOfRepairMode(fd);
+            throw e;
+        }
+    }
     /**
-     * Switch the tcp socket to repair mode and query tcp socket information.
+     * Switch the tcp socket to repair mode and query detail tcp information.
      *
-     * @param fd the fd of socket on which to use keepalive offload
-     * @return a {@link TcpKeepalivePacketData#TcpSocketInfo} object for current
+     * @param fd the fd of socket on which to use keepalive offload.
+     * @return a {@link TcpKeepalivePacketData#TcpKeepalivePacketDataParcelable} object for current
      * tcp/ip information.
      */
-    // TODO : make this private. It's far too confusing that this gets called from outside
-    // at a time that nobody can understand.
-    public static TcpSocketInfo switchToRepairMode(FileDescriptor fd)
+    private static TcpKeepalivePacketDataParcelable switchToRepairMode(FileDescriptor fd)
             throws InvalidSocketException {
         if (DBG) Log.i(TAG, "switchToRepairMode to start tcp keepalive : " + fd);
+        final TcpKeepalivePacketDataParcelable tcpDetails = new TcpKeepalivePacketDataParcelable();
         final SocketAddress srcSockAddr;
         final SocketAddress dstSockAddr;
-        final InetAddress srcAddress;
-        final InetAddress dstAddress;
-        final int srcPort;
-        final int dstPort;
-        int seq;
-        final int ack;
         final TcpRepairWindow trw;
 
         // Query source address and port.
@@ -133,8 +138,8 @@
             throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
         }
         if (srcSockAddr instanceof InetSocketAddress) {
-            srcAddress = getAddress((InetSocketAddress) srcSockAddr);
-            srcPort = getPort((InetSocketAddress) srcSockAddr);
+            tcpDetails.srcAddress = getAddress((InetSocketAddress) srcSockAddr);
+            tcpDetails.srcPort = getPort((InetSocketAddress) srcSockAddr);
         } else {
             Log.e(TAG, "Invalid or mismatched SocketAddress");
             throw new InvalidSocketException(ERROR_INVALID_SOCKET);
@@ -147,8 +152,8 @@
             throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
         }
         if (dstSockAddr instanceof InetSocketAddress) {
-            dstAddress = getAddress((InetSocketAddress) dstSockAddr);
-            dstPort = getPort((InetSocketAddress) dstSockAddr);
+            tcpDetails.dstAddress = getAddress((InetSocketAddress) dstSockAddr);
+            tcpDetails.dstPort = getPort((InetSocketAddress) dstSockAddr);
         } else {
             Log.e(TAG, "Invalid or mismatched peer SocketAddress");
             throw new InvalidSocketException(ERROR_INVALID_SOCKET);
@@ -157,28 +162,37 @@
         // Query sequence and ack number
         dropAllIncomingPackets(fd, true);
         try {
-            // Enter tcp repair mode.
+            // Switch to tcp repair mode.
             Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_ON);
+
             // Check if socket is idle.
             if (!isSocketIdle(fd)) {
+                Log.e(TAG, "Socket is not idle");
                 throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE);
             }
             // Query write sequence number from SEND_QUEUE.
             Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_SEND_QUEUE);
-            seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
+            tcpDetails.seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
             // Query read sequence number from RECV_QUEUE.
             Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_RECV_QUEUE);
-            ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
+            tcpDetails.ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
             // Switch to NO_QUEUE to prevent illegal socket read/write in repair mode.
             Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_NO_QUEUE);
             // Finally, check if socket is still idle. TODO : this check needs to move to
             // after starting polling to prevent a race.
-            if (!isSocketIdle(fd)) {
+            if (!isReceiveQueueEmpty(fd)) {
+                Log.e(TAG, "Fatal: receive queue of this socket is not empty");
                 throw new InvalidSocketException(ERROR_INVALID_SOCKET);
             }
+            if (!isSendQueueEmpty(fd)) {
+                Log.e(TAG, "Socket is not idle");
+                throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE);
+            }
 
             // Query tcp window size.
             trw = NetworkUtils.getTcpRepairWindow(fd);
+            tcpDetails.rcvWnd = trw.rcvWnd;
+            tcpDetails.rcvWndScale = trw.rcvWndScale;
         } catch (ErrnoException e) {
             Log.e(TAG, "Exception reading TCP state from socket", e);
             if (e.errno == ENOPROTOOPT) {
@@ -194,10 +208,9 @@
 
         // Keepalive sequence number is last sequence number - 1. If it couldn't be retrieved,
         // then it must be set to -1, so decrement in all cases.
-        seq = seq - 1;
+        tcpDetails.seq = tcpDetails.seq - 1;
 
-        return new TcpSocketInfo(srcAddress, srcPort, dstAddress, dstPort, seq, ack, trw.rcvWnd,
-                trw.rcvWndScale);
+        return tcpDetails;
     }
 
     /**
@@ -205,10 +218,13 @@
      *
      * @param fd the fd of socket to switch back to normal.
      */
-    // TODO : make this private.
-    public static void switchOutOfRepairMode(@NonNull final FileDescriptor fd)
-            throws ErrnoException {
-        Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF);
+    private static void switchOutOfRepairMode(@NonNull final FileDescriptor fd) {
+        try {
+            Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF);
+        } catch (ErrnoException e) {
+            Log.e(TAG, "Cannot switch socket out of repair mode", e);
+            // Well, there is not much to do here to recover
+        }
     }
 
     /**
@@ -262,17 +278,12 @@
             mListeners.remove(slot);
         }
         mFdHandlerQueue.removeOnFileDescriptorEventListener(fd);
-        try {
-            if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd);
-            switchOutOfRepairMode(fd);
-        } catch (ErrnoException e) {
-            Log.e(TAG, "Cannot switch socket out of repair mode", e);
-            // Well, there is not much to do here to recover
-        }
+        if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd);
+        switchOutOfRepairMode(fd);
     }
 
-    private static InetAddress getAddress(InetSocketAddress inetAddr) {
-        return inetAddr.getAddress();
+    private static byte [] getAddress(InetSocketAddress inetAddr) {
+        return inetAddr.getAddress().getAddress();
     }
 
     private static int getPort(InetSocketAddress inetAddr) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index b79ead0..e2ea42e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -34,6 +34,7 @@
 import android.hardware.display.BrightnessConfiguration;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
@@ -51,6 +52,8 @@
 import android.view.Display;
 
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.LocalServices;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
@@ -731,6 +734,7 @@
     private void updatePowerState() {
         // Update the power state request.
         final boolean mustNotify;
+        final int previousPolicy;
         boolean mustInitialize = false;
 
         synchronized (mLock) {
@@ -745,12 +749,18 @@
                 mPendingWaitForNegativeProximityLocked = false;
                 mPendingRequestChangedLocked = false;
                 mustInitialize = true;
+                // Assume we're on and bright until told otherwise, since that's the state we turn
+                // on in.
+                previousPolicy = DisplayPowerRequest.POLICY_BRIGHT;
             } else if (mPendingRequestChangedLocked) {
+                previousPolicy = mPowerRequest.policy;
                 mPowerRequest.copyFrom(mPendingRequestLocked);
                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
                 mPendingWaitForNegativeProximityLocked = false;
                 mPendingRequestChangedLocked = false;
                 mDisplayReadyLocked = false;
+            } else {
+                previousPolicy = mPowerRequest.policy;
             }
 
             mustNotify = !mDisplayReadyLocked;
@@ -1103,6 +1113,10 @@
 
         // Record if dozing for future comparison.
         mDozing = state != Display.STATE_ON;
+
+        if (previousPolicy != mPowerRequest.policy) {
+            logDisplayPolicyChanged(mPowerRequest.policy);
+        }
     }
 
     @Override
@@ -1523,6 +1537,13 @@
         mHandler.post(mOnStateChangedRunnable);
     }
 
+    private void logDisplayPolicyChanged(int newPolicy) {
+        LogMaker log = new LogMaker(MetricsEvent.DISPLAY_POLICY);
+        log.setType(MetricsEvent.TYPE_UPDATE);
+        log.setSubtype(newPolicy);
+        MetricsLogger.action(log);
+    }
+
     private void handleSettingsChange(boolean userSwitch) {
         mPendingScreenBrightnessSetting = getScreenBrightnessSetting();
         if (userSwitch) {
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 45567e5..ed420b7 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -1417,7 +1417,7 @@
                 mCurrentColorTemperature = cct;
 
                 // Adapt the display's nominal white point to match the requested CCT value
-                mCurrentColorTemperatureXYZ = ColorSpace.cctToIlluminantdXyz(cct);
+                mCurrentColorTemperatureXYZ = ColorSpace.cctToXyz(cct);
 
                 mChromaticAdaptationMatrix =
                         ColorSpace.chromaticAdaptation(ColorSpace.Adaptation.BRADFORD,
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index 3c27bf2..430203d 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -332,21 +332,31 @@
      * with the test results.
      *
      * @throws SecurityException if caller is not allowed to manage this service's settings.
+     *
+     * @return whether the enabled state changed.
      */
-    public final void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
+    public final boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
         Slog.i(mTag, "setDefaultServiceEnabled() for userId " + userId + ": " + enabled);
         enforceCallingPermissionForManagement();
 
         synchronized (mLock) {
+            final boolean changed = mServiceNameResolver.setDefaultServiceEnabled(userId, enabled);
+            if (!changed) {
+                if (verbose) {
+                    Slog.v(mTag, "setDefaultServiceEnabled(" + userId + "): already " + enabled);
+                }
+                return false;
+            }
+
             final S oldService = peekServiceForUserLocked(userId);
             if (oldService != null) {
                 oldService.removeSelfFromCacheLocked();
             }
-            mServiceNameResolver.setDefaultServiceEnabled(userId, enabled);
 
             // Must update the service on cache so its initialization code is triggered
             updateCachedServiceLocked(userId);
         }
+        return true;
     }
 
     /**
diff --git a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
index cd9ebcd..ac07e9d 100644
--- a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
@@ -327,6 +327,10 @@
     @GuardedBy("mLock")
     protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
         pw.print(prefix); pw.print("User: "); pw.println(mUserId);
+        if (mServiceInfo != null) {
+            pw.print(prefix); pw.print("Service Label: "); pw.println(getServiceLabelLocked());
+            pw.print(prefix); pw.print("Target SDK: "); pw.println(getTargedSdkLocked());
+        }
         if (mMaster.mServiceNameResolver != null) {
             pw.print(prefix); pw.print("Name resolver: ");
             mMaster.mServiceNameResolver.dumpShort(pw, mUserId); pw.println();
diff --git a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
index 1b23794..d204813 100644
--- a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
+++ b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
@@ -174,23 +174,35 @@
     }
 
     @Override
-    public void setDefaultServiceEnabled(int userId, boolean enabled) {
+    public boolean setDefaultServiceEnabled(int userId, boolean enabled) {
         synchronized (mLock) {
+            final boolean currentlyEnabled = isDefaultServiceEnabledLocked(userId);
+            if (currentlyEnabled == enabled) {
+                Slog.i(TAG, "setDefaultServiceEnabled(" + userId + "): already " + enabled);
+                return false;
+            }
             if (enabled) {
+                Slog.i(TAG, "disabling default service for user " + userId);
                 mDefaultServicesDisabled.removeAt(userId);
             } else {
+                Slog.i(TAG, "enabling default service for user " + userId);
                 mDefaultServicesDisabled.put(userId, true);
             }
         }
+        return true;
     }
 
     @Override
     public boolean isDefaultServiceEnabled(int userId) {
         synchronized (mLock) {
-            return !mDefaultServicesDisabled.get(userId);
+            return isDefaultServiceEnabledLocked(userId);
         }
     }
 
+    private boolean isDefaultServiceEnabledLocked(int userId) {
+        return !mDefaultServicesDisabled.get(userId);
+    }
+
     @Override
     public String toString() {
         return "FrameworkResourcesServiceNamer[temps=" + mTemporaryServiceNames + "]";
diff --git a/services/core/java/com/android/server/infra/ServiceNameResolver.java b/services/core/java/com/android/server/infra/ServiceNameResolver.java
index 5b60413..8c348ebb 100644
--- a/services/core/java/com/android/server/infra/ServiceNameResolver.java
+++ b/services/core/java/com/android/server/infra/ServiceNameResolver.java
@@ -115,11 +115,13 @@
      *
      * @param userId user handle
      * @param enabled whether the default service should be used when the temporary service is not
-     * set
+     * set. If the service enabled state is already that value, the command is ignored and this
+     * method return {@code false}.
      *
+     * @return whether the enabled state changed.
      * @throws UnsupportedOperationException if not implemented.
      */
-    default void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
+    default boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
         throw new UnsupportedOperationException("changing default service not supported");
     }
 
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 14b7301..d5883bb 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 
+import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -2496,8 +2497,13 @@
 
         // The expensive check: validate that the defined package+service is
         // still present & viable.
+        return isComponentUsable(job);
+    }
+
+    private boolean isComponentUsable(@NonNull JobStatus job) {
         final ServiceInfo service;
         try {
+            // TODO: cache result until we're notified that something in the package changed.
             service = AppGlobals.getPackageManager().getServiceInfo(
                     job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                     job.getUserId());
@@ -2507,7 +2513,7 @@
 
         if (service == null) {
             if (DEBUG) {
-                Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+                Slog.v(TAG, "isComponentUsable: " + job.toShortString()
                         + " component not present");
             }
             return false;
@@ -2515,10 +2521,8 @@
 
         // Everything else checked out so far, so this is the final yes/no check
         final boolean appIsBad = mActivityManagerInternal.isAppBad(service.applicationInfo);
-        if (DEBUG) {
-            if (appIsBad) {
-                Slog.i(TAG, "App is bad for " + job.toShortString() + " so not runnable");
-            }
+        if (DEBUG && appIsBad) {
+            Slog.i(TAG, "App is bad for " + job.toShortString() + " so not runnable");
         }
         return !appIsBad;
     }
@@ -2552,30 +2556,18 @@
             return false;
         }
 
+        if (isJobThermalConstrainedLocked(job)) {
+            return false;
+        }
+
         // Job pending/active doesn't affect the readiness of a job.
 
-        // Skipping the hearbeat check as this will only come into play when using the rolling
+        // Skipping the heartbeat check as this will only come into play when using the rolling
         // window quota management system.
 
-        // The expensive check last: validate that the defined package+service is
+        // The expensive check: validate that the defined package+service is
         // still present & viable.
-        final boolean componentPresent;
-        try {
-            // TODO: cache result until we're notified that something in the package changed.
-            componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
-                    job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
-                    job.getUserId()) != null);
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        }
-
-        if (DEBUG) {
-            Slog.v(TAG, "areComponentsInPlaceLocked: " + job.toShortString()
-                    + " componentPresent=" + componentPresent);
-        }
-
-        // Everything else checked out so far, so this is the final yes/no check
-        return componentPresent;
+        return isComponentUsable(job);
     }
 
     /**
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 270fbc6..3872523 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -17,9 +17,14 @@
 package com.android.server.media.projection;
 
 import android.Manifest;
+import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
+import android.app.IProcessObserver;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
 import android.hardware.display.DisplayManager;
 import android.media.MediaRouter;
 import android.media.projection.IMediaProjection;
@@ -29,6 +34,8 @@
 import android.media.projection.MediaProjectionInfo;
 import android.media.projection.MediaProjectionManager;
 import android.os.Binder;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -38,6 +45,7 @@
 import android.util.Slog;
 
 import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.Watchdog;
 
@@ -63,6 +71,8 @@
 
     private final Context mContext;
     private final AppOpsManager mAppOps;
+    private final ActivityManagerInternal mActivityManagerInternal;
+    private final PackageManager mPackageManager;
 
     private final MediaRouter mMediaRouter;
     private final MediaRouterCallback mMediaRouterCallback;
@@ -77,6 +87,8 @@
         mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>();
         mCallbackDelegate = new CallbackDelegate();
         mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+        mPackageManager = mContext.getPackageManager();
         mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
         mMediaRouterCallback = new MediaRouterCallback();
         Watchdog.getInstance().addMonitor(this);
@@ -88,6 +100,21 @@
                 false /*allowIsolated*/);
         mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback,
                 MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
+        mActivityManagerInternal.registerProcessObserver(new IProcessObserver.Stub() {
+            @Override
+            public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) {
+            }
+
+            @Override
+            public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {
+                MediaProjectionManagerService.this.handleForegroundServicesChanged(pid, uid,
+                        serviceTypes);
+            }
+
+            @Override
+            public void onProcessDied(int pid, int uid) {
+            }
+        });
     }
 
     @Override
@@ -105,6 +132,29 @@
         synchronized (mLock) { /* check for deadlock */ }
     }
 
+    /**
+     * Called when the set of active foreground service types for a given {@code uid / pid} changes.
+     * We will stop the active projection grant if its owner targets {@code Q} or higher and has no
+     * started foreground services of type {@code FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION}.
+     */
+    private void handleForegroundServicesChanged(int pid, int uid, int serviceTypes) {
+        synchronized (mLock) {
+            if (mProjectionGrant == null || mProjectionGrant.uid != uid) {
+                return;
+            }
+
+            if (mProjectionGrant.targetSdkVersion < VERSION_CODES.Q) {
+                return;
+            }
+
+            if ((serviceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION) != 0) {
+                return;
+            }
+
+            mProjectionGrant.stop();
+        }
+    }
+
     private void startProjectionLocked(final MediaProjection projection) {
         if (mProjectionGrant != null) {
             mProjectionGrant.stop();
@@ -229,10 +279,19 @@
             if (packageName == null || packageName.isEmpty()) {
                 throw new IllegalArgumentException("package name must not be empty");
             }
+
             long callingToken = Binder.clearCallingIdentity();
+
             MediaProjection projection;
             try {
-                projection = new MediaProjection(type, uid, packageName);
+                ApplicationInfo ai;
+                try {
+                    ai = mPackageManager.getApplicationInfo(packageName, 0);
+                } catch (NameNotFoundException e) {
+                    throw new IllegalArgumentException("No package matching :" + packageName);
+                }
+
+                projection = new MediaProjection(type, uid, packageName, ai.targetSdkVersion);
                 if (isPermanentGrant) {
                     mAppOps.setMode(AppOpsManager.OP_PROJECT_MEDIA,
                             projection.uid, projection.packageName, AppOpsManager.MODE_ALLOWED);
@@ -334,17 +393,19 @@
         public final int uid;
         public final String packageName;
         public final UserHandle userHandle;
+        public final int targetSdkVersion;
 
         private IMediaProjectionCallback mCallback;
         private IBinder mToken;
         private IBinder.DeathRecipient mDeathEater;
         private int mType;
 
-        public MediaProjection(int type, int uid, String packageName) {
+        MediaProjection(int type, int uid, String packageName, int targetSdkVersion) {
             mType = type;
             this.uid = uid;
             this.packageName = packageName;
             userHandle = new UserHandle(UserHandle.getUserId(uid));
+            this.targetSdkVersion = targetSdkVersion;
         }
 
         @Override // Binder call
@@ -400,6 +461,14 @@
                             + " attempted to start already started MediaProjection");
                     return;
                 }
+
+                if (targetSdkVersion >= Build.VERSION_CODES.Q
+                        && !mActivityManagerInternal.hasRunningForegroundService(
+                                uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) {
+                    throw new SecurityException("Media projections require a foreground service"
+                            + " of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION");
+                }
+
                 mCallback = callback;
                 registerCallback(mCallback);
                 try {
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 0c0c23a..0488d3a 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -347,6 +347,9 @@
                 }
             }
         }
+
+        writeExtraXmlTags(out);
+
         out.endTag(null, getConfig().xmlTag);
     }
 
@@ -355,6 +358,16 @@
      */
     protected void writeExtraAttributes(XmlSerializer out, int userId) throws IOException {}
 
+    /**
+     * Writes extra xml tags within the parent tag specified in {@link Config#xmlTag}.
+     */
+    protected void writeExtraXmlTags(XmlSerializer out) throws IOException {}
+
+    /**
+     * This is called to process tags other than {@link #TAG_MANAGED_SERVICES}.
+     */
+    protected void readExtraTag(String tag, XmlPullParser parser) throws IOException {}
+
     protected void migrateToXml() {
         loadAllowedComponentsFromSettings();
     }
@@ -391,6 +404,8 @@
                         }
                         mUseXml = true;
                     }
+                } else {
+                    readExtraTag(tag, parser);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4a215cf..ca3c826 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -294,6 +294,12 @@
 
     static final boolean ENABLE_BLOCKED_TOASTS = true;
 
+    static final String[] DEFAULT_ALLOWED_ADJUSTMENTS = new String[] {
+            Adjustment.KEY_IMPORTANCE,
+            Adjustment.KEY_CONTEXTUAL_ACTIONS,
+            Adjustment.KEY_TEXT_REPLIES,
+            Adjustment.KEY_USER_SENTIMENT};
+
     // When #matchesCallFilter is called from the ringer, wait at most
     // 3s to resolve the contacts. This timeout is required since
     // ContactsProvider might take a long time to start up.
@@ -2513,6 +2519,9 @@
                         android.Manifest.permission.INTERACT_ACROSS_USERS,
                         "canNotifyAsPackage for user " + userId);
             }
+            if (callingPkg.equals(targetPkg)) {
+                return true;
+            }
             try {
                 ApplicationInfo info =
                         mPackageManager.getApplicationInfo(targetPkg,
@@ -2582,10 +2591,21 @@
         }
 
         @Override
-        public NotificationChannel getNotificationChannel(String pkg, String channelId) {
-            checkCallerIsSystemOrSameApp(pkg);
-            return mPreferencesHelper.getNotificationChannel(
-                    pkg, Binder.getCallingUid(), channelId, false /* includeDeleted */);
+        public NotificationChannel getNotificationChannel(String callingPkg, int userId,
+                String targetPkg, String channelId) {
+            if (canNotifyAsPackage(callingPkg, targetPkg, userId)
+                    || isCallingUidSystem()) {
+                int targetUid = -1;
+                try {
+                    targetUid = mPackageManagerClient.getPackageUidAsUser(targetPkg, userId);
+                } catch (NameNotFoundException e) {
+                    /* ignore */
+                }
+                return mPreferencesHelper.getNotificationChannel(
+                        targetPkg, targetUid, channelId, false /* includeDeleted */);
+            }
+            throw new SecurityException("Pkg " + callingPkg
+                    + " cannot read channels for " + targetPkg + " in " + userId);
         }
 
         @Override
@@ -2720,10 +2740,21 @@
         }
 
         @Override
-        public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg) {
-            checkCallerIsSystemOrSameApp(pkg);
-            return mPreferencesHelper.getNotificationChannels(
-                    pkg, Binder.getCallingUid(), false /* includeDeleted */);
+        public ParceledListSlice<NotificationChannel> getNotificationChannels(
+                String callingPkg, String targetPkg, int userId) {
+            if (canNotifyAsPackage(callingPkg, targetPkg, userId)
+                || isCallingUidSystem()) {
+                int targetUid = -1;
+                try {
+                    targetUid = mPackageManagerClient.getPackageUidAsUser(targetPkg, userId);
+                } catch (NameNotFoundException e) {
+                    /* ignore */
+                }
+                return mPreferencesHelper.getNotificationChannels(
+                        targetPkg, targetUid, false /* includeDeleted */);
+            }
+            throw new SecurityException("Pkg " + callingPkg
+                    + " cannot read channels for " + targetPkg + " in " + userId);
         }
 
         @Override
@@ -2790,6 +2821,33 @@
             handleSavePolicyFile();
         }
 
+        @Override
+        public List<String> getAllowedAssistantCapabilities(String pkg) {
+            checkCallerIsSystemOrSameApp(pkg);
+
+            if (!isCallerSystemOrPhone()
+                    && !mAssistants.isPackageAllowed(pkg, UserHandle.getCallingUserId())) {
+                    throw new SecurityException("Not currently an assistant");
+            }
+
+            return mAssistants.getAllowedAssistantCapabilities();
+        }
+
+        @Override
+        public void allowAssistantCapability(String adjustmentType) {
+            checkCallerIsSystemOrShell();
+            mAssistants.allowAdjustmentType(adjustmentType);
+
+            handleSavePolicyFile();
+        }
+
+        @Override
+        public void disallowAssistantCapability(String adjustmentType) {
+            checkCallerIsSystemOrShell();
+            mAssistants.disallowAdjustmentType(adjustmentType);
+
+            handleSavePolicyFile();
+        }
 
         /**
          * System-only API for getting a list of current (i.e. not cleared) notifications.
@@ -7143,15 +7201,26 @@
         static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants";
 
         private static final String ATT_USER_SET = "user_set";
+        // TODO: STOPSHIP (b/127994217) switch to final value when onboarding flow is implemented
+        private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "allowed_adjustments_tmp";
+        private static final String ATT_TYPES = "types";
 
         private final Object mLock = new Object();
 
         @GuardedBy("mLock")
         private ArrayMap<Integer, Boolean> mUserSetMap = new ArrayMap<>();
+        private List<String> mAllowedAdjustments = new ArrayList<>();
 
         public NotificationAssistants(Context context, Object lock, UserProfiles up,
                 IPackageManager pm) {
             super(context, lock, up, pm);
+
+            // TODO: STOPSHIP (b/127994217) remove when the onboarding flow is implemented
+            // Add all default allowed adjustment types. Will be overwritten by values in xml,
+            // if they exist
+            for (int i = 0; i < DEFAULT_ALLOWED_ADJUSTMENTS.length; i++) {
+                mAllowedAdjustments.add(DEFAULT_ALLOWED_ADJUSTMENTS[i]);
+            }
         }
 
         @Override
@@ -7202,6 +7271,48 @@
             return android.Manifest.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE;
         }
 
+        @Override
+        protected void writeExtraXmlTags(XmlSerializer out) throws IOException {
+            synchronized (mLock) {
+                out.startTag(null, TAG_ALLOWED_ADJUSTMENT_TYPES);
+                out.attribute(null, ATT_TYPES, TextUtils.join(",", mAllowedAdjustments));
+                out.endTag(null, TAG_ALLOWED_ADJUSTMENT_TYPES);
+            }
+        }
+
+        @Override
+        protected void readExtraTag(String tag, XmlPullParser parser) throws IOException {
+            if (TAG_ALLOWED_ADJUSTMENT_TYPES.equals(tag)) {
+                final String types = XmlUtils.readStringAttribute(parser, ATT_TYPES);
+                if (!TextUtils.isEmpty(types)) {
+                    synchronized (mLock) {
+                        mAllowedAdjustments.clear();
+                        mAllowedAdjustments.addAll(Arrays.asList(types.split(",")));
+                    }
+                }
+            }
+        }
+
+        protected void allowAdjustmentType(String type) {
+            synchronized (mLock) {
+                mAllowedAdjustments.add(type);
+            }
+        }
+
+        protected void disallowAdjustmentType(String type) {
+            synchronized (mLock) {
+                mAllowedAdjustments.remove(type);
+            }
+        }
+
+        protected List<String> getAllowedAssistantCapabilities() {
+            synchronized (mLock) {
+                List<String> types = new ArrayList<>();
+                types.addAll(mAllowedAdjustments);
+                return types;
+            }
+        }
+
         protected void onNotificationsSeenLocked(ArrayList<NotificationRecord> records) {
             // There should be only one, but it's a list, so while we enforce
             // singularity elsewhere, we keep it general here, to avoid surprises.
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index d9ab132..de93120 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -438,6 +438,8 @@
         if (getAudioAttributes() != null) {
             getAudioAttributes().writeToProto(proto, NotificationRecordProto.AUDIO_ATTRIBUTES);
         }
+        proto.write(NotificationRecordProto.PACKAGE, sbn.getPackageName());
+        proto.write(NotificationRecordProto.DELEGATE_PACKAGE, sbn.getOpPkg());
 
         proto.end(token);
     }
@@ -458,6 +460,7 @@
         pw.println(prefix + this);
         prefix = prefix + "  ";
         pw.println(prefix + "uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
+        pw.println(prefix + "opPkg=" + sbn.getOpPkg());
         pw.println(prefix + "icon=" + iconStr);
         pw.println(prefix + "flags=0x" + Integer.toHexString(notification.flags));
         pw.println(prefix + "pri=" + notification.priority);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 181b7a2..ad17549 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -123,6 +123,8 @@
 
     /** Automatically destroy sessions older than this */
     private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS;
+    /** Automatically destroy staged sessions that have not changed state in this time */
+    private static final long MAX_TIME_SINCE_UPDATE_MILLIS = 7 * DateUtils.DAY_IN_MILLIS;
     /** Upper bound on number of active sessions for a UID */
     private static final long MAX_ACTIVE_SESSIONS = 1024;
     /** Upper bound on number of historical sessions for a UID */
@@ -357,11 +359,19 @@
                         }
 
                         final long age = System.currentTimeMillis() - session.createdMillis;
-
+                        final long timeSinceUpdate =
+                                System.currentTimeMillis() - session.updatedMillis;
                         final boolean valid;
-                        if (age >= MAX_AGE_MILLIS) {
-                            Slog.w(TAG, "Abandoning old session first created at "
-                                    + session.createdMillis);
+                        if (session.isStaged()) {
+                            if (timeSinceUpdate >= MAX_TIME_SINCE_UPDATE_MILLIS
+                                    && session.isStagedAndInTerminalState()) {
+                                valid = false;
+                            } else {
+                                valid = true;
+                            }
+                        } else if (age >= MAX_AGE_MILLIS) {
+                            Slog.w(TAG, "Abandoning old session created at "
+                                        + session.createdMillis);
                             valid = false;
                         } else {
                             valid = true;
@@ -1196,6 +1206,7 @@
         }
 
         public void onStagedSessionChanged(PackageInstallerSession session) {
+            session.markUpdated();
             writeSessionsAsync();
             if (mOkToSendBroadcasts) {
                 mPm.sendSessionUpdatedBroadcast(session.generateInfo(false),
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 6451b56..66b530f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -144,6 +144,7 @@
     private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName";
     private static final String ATTR_INSTALLER_UID = "installerUid";
     private static final String ATTR_CREATED_MILLIS = "createdMillis";
+    private static final String ATTR_UPDATED_MILLIS = "updatedMillis";
     private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
     private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
     private static final String ATTR_PREPARED = "prepared";
@@ -199,6 +200,10 @@
 
     private final Object mLock = new Object();
 
+    /** Timestamp of the last time this session changed state  */
+    @GuardedBy("mLock")
+    long updatedMillis;
+
     /** Uid of the creator of this session. */
     private final int mOriginalInstallerUid;
 
@@ -422,6 +427,7 @@
         mInstallerUid = installerUid;
         this.params = params;
         this.createdMillis = createdMillis;
+        this.updatedMillis = createdMillis;
         this.stageDir = stageDir;
         this.stageCid = stageCid;
         if (childSessionIds != null) {
@@ -521,6 +527,13 @@
         }
     }
 
+    /** Returns true if a staged session has reached a final state and can be forgotten about  */
+    public boolean isStagedAndInTerminalState() {
+        synchronized (mLock) {
+            return params.isStaged && (mStagedSessionApplied || mStagedSessionFailed);
+        }
+    }
+
     @GuardedBy("mLock")
     private void assertPreparedAndNotSealedLocked(String cookie) {
         assertPreparedAndNotCommittedOrDestroyedLocked(cookie);
@@ -1034,6 +1047,13 @@
         }
     }
 
+    /** Update the timestamp of when the staged session last changed state */
+    public void markUpdated() {
+        synchronized (mLock) {
+            this.updatedMillis = System.currentTimeMillis();
+        }
+    }
+
     @Override
     public void transfer(String packageName) {
         Preconditions.checkNotNull(packageName);
@@ -2114,7 +2134,7 @@
     private void destroyInternal() {
         synchronized (mLock) {
             mSealed = true;
-            if (!params.isStaged) {
+            if (!params.isStaged || isStagedAndInTerminalState()) {
                 mDestroyed = true;
             }
             // Force shut down all bridges
@@ -2224,6 +2244,7 @@
                     mInstallerPackageName);
             writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid);
             writeLongAttribute(out, ATTR_CREATED_MILLIS, createdMillis);
+            writeLongAttribute(out, ATTR_UPDATED_MILLIS, updatedMillis);
             if (stageDir != null) {
                 writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
                         stageDir.getAbsolutePath());
@@ -2326,6 +2347,7 @@
         final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID, pm.getPackageUid(
                 installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId));
         final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
+        long updatedMillis = readLongAttribute(in, ATTR_UPDATED_MILLIS);
         final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
         final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
         final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
diff --git a/services/core/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java
index a9126c0..031b5ce 100644
--- a/services/core/java/com/android/server/pm/PackageKeySetData.java
+++ b/services/core/java/com/android/server/pm/PackageKeySetData.java
@@ -107,10 +107,7 @@
     }
 
     protected void removeAllDefinedKeySets() {
-        final int aliasSize = mKeySetAliases.size();
-        for (int i = 0; i < aliasSize; i++) {
-            mKeySetAliases.removeAt(i);
-        }
+        mKeySetAliases.erase();
     }
 
     protected boolean isUsingDefinedKeySets() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a679601..ec2ff28 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -20173,21 +20173,20 @@
     }
 
     @Override
-    public String getContentCaptureServicePackageName() {
-        String contentCaptureServiceName =
-                mContext.getString(R.string.config_defaultContentCaptureService);
+    public String getSystemCaptionsServicePackageName() {
+        String flattenedSystemCaptionsServiceComponentName =
+                mContext.getString(R.string.config_defaultSystemCaptionsService);
 
-        if (TextUtils.isEmpty(contentCaptureServiceName)) {
+        if (TextUtils.isEmpty(flattenedSystemCaptionsServiceComponentName)) {
             return null;
         }
 
-        int separatorIndex = contentCaptureServiceName.indexOf("/");
-
-        if (separatorIndex < 0) {
+        ComponentName systemCaptionsServiceComponentName =
+                ComponentName.unflattenFromString(flattenedSystemCaptionsServiceComponentName);
+        if (systemCaptionsServiceComponentName == null) {
             return null;
         }
-
-        return contentCaptureServiceName.substring(0, separatorIndex);
+        return systemCaptionsServiceComponentName.getPackageName();
     }
 
     public String getIncidentReportApproverPackageName() {
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index eced165..9782648 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -99,6 +99,7 @@
     private static final String ATTR_ICON_RES_ID = "icon-res";
     private static final String ATTR_ICON_RES_NAME = "icon-resname";
     private static final String ATTR_BITMAP_PATH = "bitmap-path";
+    private static final String ATTR_LOCUS_ID = "locus-id";
 
     private static final String ATTR_PERSON_NAME = "name";
     private static final String ATTR_PERSON_URI = "uri";
@@ -1473,6 +1474,10 @@
         ShortcutService.writeAttr(out, ATTR_DISABLED_REASON, si.getDisabledReason());
         ShortcutService.writeAttr(out, ATTR_TIMESTAMP,
                 si.getLastChangedTimestamp());
+        final LocusId locusId = si.getLocusId();
+        if (locusId != null) {
+            ShortcutService.writeAttr(out, ATTR_LOCUS_ID, si.getLocusId().getId());
+        }
         if (forBackup) {
             // Don't write icon information.  Also drop the dynamic flag.
 
@@ -1612,6 +1617,7 @@
         int iconResId;
         String iconResName;
         String bitmapPath;
+        final String locusIdString;
         int backupVersionCode;
         ArraySet<String> categories = null;
         ArrayList<Person> persons = new ArrayList<>();
@@ -1638,6 +1644,7 @@
         iconResId = (int) ShortcutService.parseLongAttribute(parser, ATTR_ICON_RES_ID);
         iconResName = ShortcutService.parseStringAttribute(parser, ATTR_ICON_RES_NAME);
         bitmapPath = ShortcutService.parseStringAttribute(parser, ATTR_BITMAP_PATH);
+        locusIdString = ShortcutService.parseStringAttribute(parser, ATTR_LOCUS_ID);
 
         final int outerDepth = parser.getDepth();
         int type;
@@ -1703,7 +1710,7 @@
             flags |= ShortcutInfo.FLAG_SHADOW;
         }
 
-        LocusId locusId = null; // LocusId is not  set on XML.
+        final LocusId locusId = locusIdString == null ? null : new LocusId(locusIdString);
 
         return new ShortcutInfo(
                 userId, id, packageName, activityComponent, /* icon= */ null,
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index e9077a9..0a17e130 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -748,11 +748,11 @@
         grantSystemFixedPermissionsToSystemPackage("com.android.sharedstoragebackup", userId,
                 STORAGE_PERMISSIONS);
 
-        // Content Capture Service
-        String contentCaptureServicePackageName =
-                mContext.getPackageManager().getContentCaptureServicePackageName();
-        if (!TextUtils.isEmpty(contentCaptureServicePackageName)) {
-            grantPermissionsToSystemPackage(contentCaptureServicePackageName, userId,
+        // System Captions Service
+        String systemCaptionsServicePackageName =
+                mContext.getPackageManager().getSystemCaptionsServicePackageName();
+        if (!TextUtils.isEmpty(systemCaptionsServicePackageName)) {
+            grantPermissionsToSystemPackage(systemCaptionsServicePackageName, userId,
                     MICROPHONE_PERMISSIONS);
         }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 897b885..e36ac23 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -17,14 +17,20 @@
 package com.android.server.pm.permission;
 
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.Manifest.permission.READ_MEDIA_AUDIO;
+import static android.Manifest.permission.READ_MEDIA_IMAGES;
+import static android.Manifest.permission.READ_MEDIA_VIDEO;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_ERRORED;
 import static android.app.AppOpsManager.MODE_FOREGROUND;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.app.AppOpsManager.permissionToOp;
 import static android.app.AppOpsManager.permissionToOpCode;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
@@ -1149,6 +1155,8 @@
                     updatedUserIds);
             updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
                     permissionsState, pkg, updatedUserIds);
+            updatedUserIds = applyLegacyStoragePermissionModel(origPermissions, permissionsState,
+                    pkg, updatedUserIds);
 
             setAppOpsLocked(permissionsState, pkg);
         }
@@ -1468,6 +1476,179 @@
     }
 
     /**
+     * Pre-Q apps use READ/WRITE_EXTERNAL_STORAGE, post-Q apps use READ_MEDIA_AUDIO/VIDEO/IMAGES.
+     *
+     * <p>There is the special case of the grandfathered post-Q app that has all legacy and modern
+     * permissions system-fixed granted. The only way to remove these permissions is to uninstall
+     * the app.
+     *
+     * @param origPs The permission state of the package before the update
+     * @param ps The permissions state of the package
+     * @param pkg The package
+     * @param updatedUserIds The userIds we have already been updated before
+     *
+     * @return The userIds that have been updated
+     *
+     * @see com.android.server.StorageManagerService#applyLegacyStorage()
+     */
+    private @NonNull int[] applyLegacyStoragePermissionModel(@NonNull PermissionsState origPs,
+            @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
+            @NonNull int[] updatedUserIds) {
+        AppOpsManagerInternal appOpsManager = LocalServices.getService(AppOpsManagerInternal.class);
+        int[] users = UserManagerService.getInstance().getUserIds();
+
+        boolean isQApp = pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
+        boolean isPreMApp = pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M;
+        int appId = getAppId(pkg.applicationInfo.uid);
+
+        int numRequestedPerms = pkg.requestedPermissions.size();
+        for (int i = 0; i < numRequestedPerms; i++) {
+            String perm = pkg.requestedPermissions.get(i);
+
+            boolean isLegacyStoragePermission = false;
+            boolean isModernStoragePermission = false;
+            switch (perm) {
+                case READ_EXTERNAL_STORAGE:
+                case WRITE_EXTERNAL_STORAGE:
+                    isLegacyStoragePermission = true;
+                    break;
+                case READ_MEDIA_AUDIO:
+                case READ_MEDIA_VIDEO:
+                case READ_MEDIA_IMAGES:
+                    isModernStoragePermission = true;
+                    break;
+                default:
+                    // 'perm' is not a storage permission, skip it
+                    continue;
+            }
+
+            BasePermission bp = mSettings.getPermissionLocked(perm);
+
+            for (int userId : users) {
+                boolean useLegacyStoragePermissionModel;
+                if (isQApp) {
+                    useLegacyStoragePermissionModel = appOpsManager.checkOperationUnchecked(
+                            OP_LEGACY_STORAGE, getUid(userId, appId), pkg.packageName)
+                            == MODE_ALLOWED;
+                } else {
+                    useLegacyStoragePermissionModel = true;
+                }
+
+                int origCombinedLegacyFlags =
+                        origPs.getPermissionFlags(READ_EXTERNAL_STORAGE, userId)
+                        | origPs.getPermissionFlags(WRITE_EXTERNAL_STORAGE, userId);
+
+                int origCombinedModernFlags = origPs.getPermissionFlags(READ_MEDIA_AUDIO, userId)
+                        | origPs.getPermissionFlags(READ_MEDIA_VIDEO, userId)
+                        | origPs.getPermissionFlags(READ_MEDIA_IMAGES, userId);
+
+                boolean oldPermAreLegacyStorageModel =
+                        (origCombinedLegacyFlags & FLAG_PERMISSION_HIDDEN) == 0;
+                boolean oldPermAreModernStorageModel =
+                        (origCombinedModernFlags & FLAG_PERMISSION_HIDDEN) == 0;
+
+                if (oldPermAreLegacyStorageModel && oldPermAreModernStorageModel) {
+                    // This only happens after an platform upgrade from before Q
+                    oldPermAreModernStorageModel = false;
+                }
+
+                boolean shouldBeRestricted;
+                boolean shouldBeFixed;
+                boolean shouldBeGranted = false;
+                boolean shouldBeRevoked = false;
+                int userFlags = -1;
+                if (useLegacyStoragePermissionModel) {
+                    shouldBeRestricted = isModernStoragePermission;
+                    shouldBeFixed = isQApp || isModernStoragePermission;
+
+                    if (shouldBeFixed) {
+                        userFlags = 0;
+                        shouldBeGranted = true;
+                        shouldBeRevoked = false;
+                    } else if (oldPermAreModernStorageModel) {
+                        // Inherit grant state on permission model change
+                        userFlags = origCombinedModernFlags;
+
+                        shouldBeGranted = origPs.hasRuntimePermission(READ_MEDIA_AUDIO, userId)
+                                || origPs.hasRuntimePermission(READ_MEDIA_VIDEO, userId)
+                                || origPs.hasRuntimePermission(READ_MEDIA_IMAGES, userId);
+
+                        shouldBeRevoked = !shouldBeGranted;
+                    }
+                } else {
+                    shouldBeRestricted = isLegacyStoragePermission;
+                    shouldBeFixed = isLegacyStoragePermission;
+
+                    if (shouldBeFixed) {
+                        userFlags = 0;
+                        shouldBeGranted = true;
+                        shouldBeRevoked = false;
+                    } else if (oldPermAreLegacyStorageModel) {
+                        // Inherit grant state on permission model change
+                        userFlags = origCombinedLegacyFlags;
+
+                        shouldBeGranted = origPs.hasRuntimePermission(READ_EXTERNAL_STORAGE, userId)
+                                || origPs.hasRuntimePermission(WRITE_EXTERNAL_STORAGE, userId);
+
+                        if ((origCombinedLegacyFlags & FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0
+                                && !isPreMApp) {
+                            shouldBeGranted = false;
+                        }
+
+                        shouldBeRevoked = !shouldBeGranted;
+                    }
+                }
+
+                // Granted permissions can never be user fixed
+                if (shouldBeGranted & userFlags != -1) {
+                    userFlags &= ~FLAG_PERMISSION_USER_FIXED;
+                }
+
+                boolean changed = false;
+                synchronized (mLock) {
+                    if (shouldBeGranted) {
+                        if (isPreMApp) {
+                            setAppOpMode(perm, pkg, userId, MODE_ALLOWED);
+                        } else if (!ps.hasRuntimePermission(perm, userId)) {
+                            ps.grantRuntimePermission(bp, userId);
+                            changed = true;
+                        }
+                    }
+
+                    if (shouldBeRevoked) {
+                        if (isPreMApp) {
+                            setAppOpMode(perm, pkg, userId, MODE_IGNORED);
+                        } else if (ps.hasRuntimePermission(perm, userId)) {
+                            ps.revokeRuntimePermission(bp, userId);
+                            changed = true;
+                        }
+                    }
+
+                    if (shouldBeFixed) {
+                        changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm),
+                                userId, FLAG_PERMISSION_SYSTEM_FIXED, FLAG_PERMISSION_SYSTEM_FIXED);
+                    }
+
+                    if (userFlags != -1) {
+                        changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm),
+                                userId, USER_PERMISSION_FLAGS, userFlags);
+                    }
+
+                    changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm), userId,
+                            FLAG_PERMISSION_HIDDEN,
+                            shouldBeRestricted ? FLAG_PERMISSION_HIDDEN : 0);
+                }
+
+                if (changed) {
+                    updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+                }
+            }
+        }
+
+        return updatedUserIds;
+    }
+
+    /**
      * Fix app-op modes for runtime permissions.
      *
      * @param permsState The state of the permissions of the package
diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
index 2280d3f..c610ed0 100644
--- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
@@ -19,6 +19,9 @@
                 },
                 {
                     "include-filter": "android.permission.cts.PermissionFlagsTest"
+                },
+                {
+                    "include-filter": "android.permission.cts.DualStoragePermissionModelTest"
                 }
             ]
         },
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e7c9a08..1f89840 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -917,9 +917,6 @@
 
         mWindowManagerFuncs.onPowerKeyDown(interactive);
 
-        // Abort possibly stuck animations.
-        mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
-
         // Latch power key state to detect screenshot chord.
         if (interactive && !mScreenshotChordPowerKeyTriggered
                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
@@ -1026,6 +1023,11 @@
         cancelPendingPowerKeyAction();
 
         if (!handled) {
+            if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) == 0) {
+                // Abort possibly stuck animations only when power key up without long press case.
+                mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
+            }
+
             // Figure out how to handle the key now that it has been released.
             mPowerKeyPressCounter += 1;
 
@@ -3362,9 +3364,6 @@
      */
     void launchHomeFromHotKey(int displayId, final boolean awakenFromDreams,
             final boolean respectKeyguard) {
-        // Abort possibly stuck animations.
-        mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
-
         if (respectKeyguard) {
             if (isKeyguardShowingAndNotOccluded()) {
                 // don't launch home if keyguard showing
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index 406cbc1..701e5af 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -269,7 +269,7 @@
      */
     @VisibleForTesting
     boolean isAttentionServiceSupported() {
-        return mAttentionManager.isAttentionServiceSupported();
+        return mAttentionManager != null && mAttentionManager.isAttentionServiceSupported();
     }
 
     public void dump(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 1a82858..b81d969 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -486,6 +486,8 @@
                         log.setType(MetricsEvent.TYPE_OPEN);
                         log.setSubtype(why);
                         log.setLatency(interactiveChangeLatency);
+                        log.addTaggedData(
+                                MetricsEvent.FIELD_SCREEN_WAKE_REASON, mInteractiveChangeReason);
                         MetricsLogger.action(log);
                         EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency);
                         mPolicy.finishedWakingUp(why);
@@ -513,6 +515,8 @@
                         log.setType(MetricsEvent.TYPE_CLOSE);
                         log.setSubtype(why);
                         log.setLatency(interactiveChangeLatency);
+                        log.addTaggedData(
+                                MetricsEvent.FIELD_SCREEN_SLEEP_REASON, mInteractiveChangeReason);
                         MetricsLogger.action(log);
                         EventLogTags.writePowerScreenState(0, why, 0, 0, interactiveChangeLatency);
                         mPolicy.finishedGoingToSleep(why);
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index c3582ea..d632749 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.rollback;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.BroadcastReceiver;
@@ -24,6 +25,7 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ModuleInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
@@ -42,6 +44,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.util.IntArray;
 import android.util.Log;
@@ -220,9 +223,7 @@
 
     @Override
     public ParceledListSlice getAvailableRollbacks() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_ROLLBACKS,
-                "getAvailableRollbacks");
+        enforceManageRollbacks("getAvailableRollbacks");
 
         synchronized (mLock) {
             ensureRollbackDataLoadedLocked();
@@ -239,9 +240,7 @@
 
     @Override
     public ParceledListSlice<RollbackInfo> getRecentlyExecutedRollbacks() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_ROLLBACKS,
-                "getRecentlyExecutedRollbacks");
+        enforceManageRollbacks("getRecentlyCommittedRollbacks");
 
         synchronized (mLock) {
             ensureRollbackDataLoadedLocked();
@@ -259,9 +258,7 @@
     @Override
     public void commitRollback(int rollbackId, ParceledListSlice causePackages,
             String callerPackageName, IntentSender statusReceiver) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_ROLLBACKS,
-                "executeRollback");
+        enforceManageRollbacks("executeRollback");
 
         final int callingUid = Binder.getCallingUid();
         AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -459,11 +456,8 @@
 
                             Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
 
-                            // TODO: This call emits the warning "Calling a method in the
-                            // system process without a qualified user". Fix that.
-                            // TODO: Limit this to receivers holding the
-                            // MANAGE_ROLLBACKS permission?
-                            mContext.sendBroadcast(broadcast);
+                            mContext.sendBroadcastAsUser(broadcast, UserHandle.SYSTEM,
+                                    Manifest.permission.MANAGE_ROLLBACKS);
                         });
                     }
             );
@@ -484,7 +478,7 @@
     @Override
     public void reloadPersistedData() {
         mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_ROLLBACKS,
+                Manifest.permission.TEST_MANAGE_ROLLBACKS,
                 "reloadPersistedData");
 
         synchronized (mLock) {
@@ -499,7 +493,7 @@
     @Override
     public void expireRollbackForPackage(String packageName) {
         mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_ROLLBACKS,
+                Manifest.permission.TEST_MANAGE_ROLLBACKS,
                 "expireRollbackForPackage");
         synchronized (mLock) {
             ensureRollbackDataLoadedLocked();
@@ -894,12 +888,19 @@
         Log.i(TAG, "Enabling rollback for install of " + packageName
                 + ", session:" + session.sessionId);
 
+        String installerPackageName = session.getInstallerPackageName();
+        if (!enableRollbackAllowed(installerPackageName, packageName)) {
+            Log.e(TAG, "Installer " + installerPackageName
+                    + " is not allowed to enable rollback on " + packageName);
+            return false;
+        }
+
         VersionedPackage newVersion = new VersionedPackage(packageName, newPackage.versionCode);
         final boolean isApex = ((installFlags & PackageManager.INSTALL_APEX) != 0);
 
         // Get information about the currently installed package.
         PackageManager pm = mContext.getPackageManager();
-        PackageInfo pkgInfo = null;
+        final PackageInfo pkgInfo;
         try {
             pkgInfo = pm.getPackageInfo(packageName, isApex ? PackageManager.MATCH_APEX : 0);
         } catch (PackageManager.NameNotFoundException e) {
@@ -1086,6 +1087,44 @@
     }
 
     /**
+     * Returns true if the installer is allowed to enable rollback for the
+     * given named package, false otherwise.
+     */
+    private boolean enableRollbackAllowed(String installerPackageName, String packageName) {
+        if (installerPackageName == null) {
+            return false;
+        }
+
+        PackageManager pm = mContext.getPackageManager();
+        boolean manageRollbacksGranted = pm.checkPermission(
+                Manifest.permission.MANAGE_ROLLBACKS,
+                installerPackageName) == PackageManager.PERMISSION_GRANTED;
+
+        boolean testManageRollbacksGranted = pm.checkPermission(
+                Manifest.permission.TEST_MANAGE_ROLLBACKS,
+                installerPackageName) == PackageManager.PERMISSION_GRANTED;
+
+        // For now only allow rollbacks for modules or for testing.
+        return (isModule(packageName) && manageRollbacksGranted)
+            || testManageRollbacksGranted;
+    }
+
+    /**
+     * Returns true if the package name is the name of a module.
+     */
+    private boolean isModule(String packageName) {
+        PackageManager pm = mContext.getPackageManager();
+        final ModuleInfo moduleInfo;
+        try {
+            moduleInfo = pm.getModuleInfo(packageName, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+
+        return moduleInfo != null;
+    }
+
+    /**
      * Gets the version of the package currently installed.
      * Returns null if the package is not currently installed.
      */
@@ -1311,4 +1350,15 @@
             }
         }
     }
+
+    private void enforceManageRollbacks(@NonNull String message) {
+        if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
+                        Manifest.permission.MANAGE_ROLLBACKS))
+                && (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
+                        Manifest.permission.TEST_MANAGE_ROLLBACKS))) {
+            throw new SecurityException(message + " requires "
+                    + Manifest.permission.MANAGE_ROLLBACKS + " or "
+                    + Manifest.permission.TEST_MANAGE_ROLLBACKS);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index a33b454d..9d6efb4 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -1173,7 +1173,17 @@
     }
 
     private void releaseSelfIfNeeded() {
-        if (mStacks.isEmpty() && mRemoved) {
+        if (!mRemoved || mDisplayContent == null) {
+            return;
+        }
+
+        final ActivityStack stack = mStacks.size() == 1 ? mStacks.get(0) : null;
+        if (stack != null && stack.isActivityTypeHome() && stack.getAllTasks().isEmpty()) {
+            // Release this display if an empty home stack is the only thing left.
+            // Since it is the last stack, this display will be released along with the stack
+            // removal.
+            stack.remove();
+        } else if (mStacks.isEmpty()) {
             mDisplayContent.removeIfPossible();
             mDisplayContent = null;
             mRootActivityContainer.removeChild(this);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index ad98970..4c9b80b 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -3053,7 +3053,17 @@
         ActivityOptions.abort(options);
         if (DEBUG_STATES) Slog.d(TAG_STATES,
                 "resumeTopActivityInNextFocusableStack: " + reason + ", go home");
-        return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
+        if (isActivityTypeHome()) {
+            // resumeTopActivityUncheckedLocked has been prevented to run recursively. Post a
+            // runnable to resume home since we are currently in the process of resuming top
+            // activity in home stack.
+            // See {@link #mInResumeTopActivity}.
+            mService.mH.post(
+                    () -> mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId));
+            return true;
+        } else {
+            return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
+        }
     }
 
     /** Returns the position the input task should be placed in this stack. */
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index af05a27..e053ff3 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -484,6 +484,10 @@
         mListeners.add(listener);
     }
 
+    void unregisterListener(AppTransitionListener listener) {
+        mListeners.remove(listener);
+    }
+
     public void notifyAppTransitionFinishedLocked(IBinder token) {
         for (int i = 0; i < mListeners.size(); i++) {
             mListeners.get(i).onAppTransitionFinishedLocked(token);
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index f6326957..75e34fb 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -19,6 +19,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
@@ -638,6 +639,39 @@
         return transit;
     }
 
+    /**
+     * Identifies whether the current transition occurs within a single task or not. This is used
+     * to determine whether animations should be clipped to the task bounds instead of stack bounds.
+     */
+    @VisibleForTesting
+    boolean isTransitWithinTask(int transit, Task task) {
+        if (task == null
+                || !mDisplayContent.mChangingApps.isEmpty()) {
+            // if there is no task, then we can't constrain to the task.
+            // if anything is changing, it can animate outside its task.
+            return false;
+        }
+        if (!(transit == TRANSIT_ACTIVITY_OPEN
+                || transit == TRANSIT_ACTIVITY_CLOSE
+                || transit == TRANSIT_ACTIVITY_RELAUNCH)) {
+            // only activity-level transitions will be within-task.
+            return false;
+        }
+        // check that all components are in the task.
+        for (AppWindowToken activity : mDisplayContent.mOpeningApps) {
+            Task activityTask = activity.getTask();
+            if (activityTask != task) {
+                return false;
+            }
+        }
+        for (AppWindowToken activity : mDisplayContent.mClosingApps) {
+            if (activity.getTask() != task) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private boolean canBeWallpaperTarget(ArraySet<AppWindowToken> apps) {
         for (int i = apps.size() - 1; i >= 0; i--) {
             if (apps.valueAt(i).windowsCanBeWallpaperTarget()) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index ea3a7d5..955f2e9 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -666,7 +666,7 @@
             }
         }
 
-        if (isReallyAnimating()) {
+        if (isSelfAnimating()) {
             delayed = true;
         } else {
 
@@ -2436,6 +2436,12 @@
                 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
         final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
 
+        // Don't animate when the task runs recents animation.
+        final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
+        if (controller != null && controller.isAnimatingTask(getTask())) {
+            return false;
+        }
+
         // We animate always if it's not split screen primary, and only some special cases in split
         // screen primary because it causes issues with stack clipping when we run an un-minimize
         // animation at the same time.
@@ -2705,16 +2711,21 @@
         // If the animation needs to be cropped then an animation bounds layer is created as a child
         // of the pinned stack or animation layer. The leash is then reparented to this new layer.
         if (mNeedsAnimationBoundsLayer) {
-            final TaskStack stack = getStack();
-            if (stack == null) {
-                return;
+            mTmpRect.setEmpty();
+            final Task task = getTask();
+            if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
+                    getTransit(), task)) {
+                task.getBounds(mTmpRect);
+            } else {
+                final TaskStack stack = getStack();
+                if (stack == null) {
+                    return;
+                }
+                // Set clip rect to stack bounds.
+                stack.getBounds(mTmpRect);
             }
             mAnimationBoundsLayer = createAnimationBoundsLayer(t);
 
-            // Set clip rect to stack bounds.
-            mTmpRect.setEmpty();
-            stack.getBounds(mTmpRect);
-
             // Crop to stack bounds.
             t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b00cafd..bec72f5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -130,6 +130,7 @@
 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
+import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
 
 import android.animation.AnimationHandler;
 import android.annotation.CallSuper;
@@ -153,6 +154,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Process;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -165,6 +167,7 @@
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.Gravity;
+import android.view.ISystemGestureExclusionListener;
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.InputWindowHandle;
@@ -312,6 +315,10 @@
     private DisplayRotation mDisplayRotation;
     DisplayFrames mDisplayFrames;
 
+    private final RemoteCallbackList<ISystemGestureExclusionListener>
+            mSystemGestureExclusionListeners = new RemoteCallbackList<>();
+    private final Region mSystemGestureExclusion = new Region();
+
     /**
      * For default display it contains real metrics, empty for others.
      * @see WindowManagerService#createWatermarkInTransaction()
@@ -2818,6 +2825,14 @@
         mWallpaperController.dump(pw, "  ");
 
         pw.println();
+        pw.print("mSystemGestureExclusion=");
+        if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() > 0) {
+            pw.println(mSystemGestureExclusion);
+        } else {
+            pw.println("<no lstnrs>");
+        }
+
+        pw.println();
         pw.println(prefix + "Application tokens in top down Z order:");
         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
@@ -4951,6 +4966,100 @@
     }
 
     /**
+     * Updates the display's system gesture exclusion.
+     *
+     * @return true, if the exclusion changed.
+     */
+    boolean updateSystemGestureExclusion() {
+        if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 0) {
+            // No one's interested anyways.
+            return false;
+        }
+
+        final Region systemGestureExclusion = calculateSystemGestureExclusion();
+        try {
+            if (mSystemGestureExclusion.equals(systemGestureExclusion)) {
+                return false;
+            }
+            mSystemGestureExclusion.set(systemGestureExclusion);
+            for (int i = mSystemGestureExclusionListeners.beginBroadcast() - 1; i >= 0; --i) {
+                try {
+                    mSystemGestureExclusionListeners.getBroadcastItem(i)
+                            .onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to notify SystemGestureExclusionListener", e);
+                }
+            }
+            mSystemGestureExclusionListeners.finishBroadcast();
+            return true;
+        } finally {
+            systemGestureExclusion.recycle();
+        }
+    }
+
+    @VisibleForTesting
+    Region calculateSystemGestureExclusion() {
+        final Region global = Region.obtain();
+        final Region touchableRegion = Region.obtain();
+        final Region local = Region.obtain();
+
+        // Traverse all windows bottom up to assemble the gesture exclusion rects.
+        // For each window, we only take the rects that fall within its touchable region.
+        forAllWindows(w -> {
+            if (w.cantReceiveTouchInput() || !w.isVisible()
+                    || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0) {
+                return;
+            }
+            final boolean modal =
+                    (w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
+
+            // Only keep the exclusion zones from the windows behind where the current window
+            // isn't touchable.
+            w.getTouchableRegion(touchableRegion);
+            global.op(touchableRegion, Op.DIFFERENCE);
+
+            rectListToRegion(w.getSystemGestureExclusion(), local);
+
+            // Transform to display coordinates
+            local.scale(w.mGlobalScale);
+            final Rect frame = w.getWindowFrames().mFrame;
+            local.translate(frame.left, frame.top);
+
+            // A window can only exclude system gestures where it is actually touchable
+            local.op(touchableRegion, Op.INTERSECT);
+
+            global.op(local, Op.UNION);
+        }, false /* topToBottom */);
+        local.recycle();
+        touchableRegion.recycle();
+        return global;
+    }
+
+    void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
+        mSystemGestureExclusionListeners.register(listener);
+        final boolean changed;
+        if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 1) {
+            changed = updateSystemGestureExclusion();
+        } else {
+            changed = false;
+        }
+
+        if (!changed) {
+            // If updateSystemGestureExclusion changed the exclusion, it will already have
+            // notified the listener. Otherwise, we'll do it here.
+            try {
+                listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to notify SystemGestureExclusionListener during register", e);
+            }
+        }
+    }
+
+    void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
+        mSystemGestureExclusionListeners.unregister(listener);
+    }
+
+    /**
      * Create a portal window handle for input. This window transports any touch to the display
      * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
      *
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index cb9cbd6..f1560d9 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -31,6 +31,7 @@
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
 
 import android.app.ActivityOptions;
 import android.app.AppOpsManager;
@@ -59,7 +60,7 @@
 class RecentsAnimation implements RecentsAnimationCallbacks,
         ActivityDisplay.OnStackOrderChangedListener {
     private static final String TAG = RecentsAnimation.class.getSimpleName();
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = DEBUG_RECENTS_ANIMATIONS;
 
     private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mStackSupervisor;
@@ -395,11 +396,23 @@
             // The stack is not visible, so ignore this change
             return;
         }
+        final RecentsAnimationController controller =
+                mWindowManager.getRecentsAnimationController();
 
-        // If the activity display stack order changes, cancel any running recents animation in
-        // place
-        mWindowManager.cancelRecentsAnimationSynchronously(REORDER_KEEP_IN_PLACE,
-                "stackOrderChanged");
+        // Cancel running recents animation and screenshot previous task when the next
+        // transition starts in below cases:
+        // 1) The next launching task is not in recents animation task.
+        // 2) The next task is home activity. (i.e. pressing home key to back home in recents).
+        if ((!controller.isAnimatingTask(stack.getTaskStack().getTopChild())
+                || controller.isTargetApp(stack.getTopActivity().mAppWindowToken))
+                && controller.shouldCancelWithDeferredScreenshot()) {
+            controller.cancelOnNextTransitionStart();
+        } else {
+            // Just cancel directly to unleash from launcher when the next launching task is the
+            // current top task.
+            mWindowManager.cancelRecentsAnimationSynchronously(REORDER_KEEP_IN_PLACE,
+                    "stackOrderChanged");
+        }
     }
 
     /**
@@ -407,7 +420,7 @@
      */
     private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
         try {
-            recentsAnimationRunner.onAnimationCanceled();
+            recentsAnimationRunner.onAnimationCanceled(false /* deferredWithScreenshot */);
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to cancel recents animation before start", e);
         }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 105ff06..26df832 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -29,6 +29,7 @@
 import static com.android.server.wm.AnimationAdapterProto.REMOTE;
 import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
+import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
 
 import android.annotation.IntDef;
 import android.app.ActivityManager.TaskSnapshot;
@@ -92,6 +93,8 @@
     private final Runnable mFailsafeRunnable = () ->
             cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "failSafeRunnable");
 
+    final Object mLock = new Object();
+
     // The recents component app token that is shown behind the visibile tasks
     private AppWindowToken mTargetAppToken;
     private int mTargetActivityType;
@@ -117,6 +120,27 @@
 
     private boolean mLinkedToDeathOfRunner;
 
+    private boolean mCancelWithDeferredScreenshot;
+
+    private boolean mCancelOnNextTransitionStart;
+
+    /**
+     * Animates the screenshot of task that used to be controlled by RecentsAnimation.
+     * @see {@link #cancelOnNextTransitionStart}
+     */
+    SurfaceAnimator mRecentScreenshotAnimator;
+
+    final AppTransitionListener mAppTransitionListener = new AppTransitionListener() {
+        @Override
+        public int onAppTransitionStartingLocked(int transit, long duration,
+                long statusBarAnimationStartTime, long statusBarAnimationDuration) {
+            onTransitionStart();
+            mService.mRoot.getDisplayContent(mDisplayId).mAppTransition
+                    .unregisterListener(this);
+            return 0;
+        }
+    };
+
     public interface RecentsAnimationCallbacks {
         void onAnimationFinished(@ReorderMode int reorderMode, boolean runSychronously);
     }
@@ -245,6 +269,23 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        @Override
+        public void setCancelWithDeferredScreenshot(boolean screenshot) {
+            synchronized (mLock) {
+                setCancelWithDeferredScreenshotLocked(screenshot);
+            }
+        }
+
+        @Override
+        public void cleanupScreenshot() {
+            synchronized (mLock) {
+                if (mRecentScreenshotAnimator != null) {
+                    mRecentScreenshotAnimator.cancelAnimation();
+                    mRecentScreenshotAnimator = null;
+                }
+            }
+        }
     };
 
     /**
@@ -273,6 +314,7 @@
     @VisibleForTesting
     void initialize(DisplayContent dc, int targetActivityType, SparseBooleanArray recentTaskIds) {
         mTargetActivityType = targetActivityType;
+        dc.mAppTransition.registerListenerLocked(mAppTransitionListener);
 
         // Make leashes for each of the visible/target tasks and add it to the recents animation to
         // be started
@@ -416,15 +458,20 @@
     }
 
     void cancelAnimation(@ReorderMode int reorderMode, String reason) {
-        cancelAnimation(reorderMode, false /* runSynchronously */, reason);
+        cancelAnimation(reorderMode, false /* runSynchronously */, false /*screenshot */, reason);
     }
 
     void cancelAnimationSynchronously(@ReorderMode int reorderMode, String reason) {
-        cancelAnimation(reorderMode, true /* runSynchronously */, reason);
+        cancelAnimation(reorderMode, true /* runSynchronously */, false /* screenshot */, reason);
+    }
+
+    void cancelAnimationWithScreenShot() {
+        cancelAnimation(REORDER_KEEP_IN_PLACE, true /* sync */, true /* screenshot */,
+                "stackOrderChanged");
     }
 
     private void cancelAnimation(@ReorderMode int reorderMode, boolean runSynchronously,
-            String reason) {
+            boolean screenshot, String reason) {
         if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason
                 + " runSynchronously=" + runSynchronously);
         synchronized (mService.getWindowManagerLock()) {
@@ -435,14 +482,67 @@
             mService.mH.removeCallbacks(mFailsafeRunnable);
             mCanceled = true;
             try {
-                mRunner.onAnimationCanceled();
+                if (screenshot) {
+                    // Screen shot previous task when next task starts transition.
+                    final Task task = mPendingAnimations.get(0).mTask;
+                    screenshotRecentTask(task, reorderMode, runSynchronously);
+                    mRunner.onAnimationCanceled(true /* deferredWithScreenshot */);
+                    return;
+                }
+                mRunner.onAnimationCanceled(false /* deferredWithScreenshot */);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to cancel recents animation", e);
             }
+            // Clean up and return to the previous app
+            mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
+        }
+    }
+
+    /**
+     * Cancel recents animation when the next app transition starts.
+     * <p>
+     * When we cancel the recents animation due to a stack order change, we can't just cancel it
+     * immediately as it would lead to a flicker in Launcher if we just remove the task from the
+     * leash. Instead we screenshot the previous task and replace the child of the leash with the
+     * screenshot, so that Launcher can still control the leash lifecycle & make the next app
+     * transition animate smoothly without flickering.
+     */
+    void cancelOnNextTransitionStart() {
+        mCancelOnNextTransitionStart = true;
+    }
+
+    void setCancelWithDeferredScreenshotLocked(boolean screenshot) {
+        mCancelWithDeferredScreenshot = screenshot;
+    }
+
+    boolean shouldCancelWithDeferredScreenshot() {
+        return mCancelWithDeferredScreenshot;
+    }
+
+    void onTransitionStart() {
+        if (mCanceled) {
+            return;
         }
 
-        // Clean up and return to the previous app
-        mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
+        if (mCancelOnNextTransitionStart) {
+            mCancelOnNextTransitionStart = false;
+            cancelAnimationWithScreenShot();
+        }
+    }
+
+    void screenshotRecentTask(Task task, @ReorderMode int reorderMode, boolean runSynchronously) {
+        final TaskScreenshotAnimatable animatable = TaskScreenshotAnimatable.create(task);
+        if (animatable != null) {
+            mRecentScreenshotAnimator = new SurfaceAnimator(
+                    animatable,
+                    () -> {
+                        if (DEBUG_RECENTS_ANIMATIONS) {
+                            Slog.d(TAG, "mRecentScreenshotAnimator finish");
+                        }
+                        mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
+                    }, mService);
+            mRecentScreenshotAnimator.transferAnimation(task.mSurfaceAnimator);
+        }
     }
 
     void cleanupAnimation(@ReorderMode int reorderMode) {
@@ -465,6 +565,12 @@
         mRunner = null;
         mCanceled = true;
 
+        // Make sure previous animator has cleaned-up.
+        if (mRecentScreenshotAnimator != null) {
+            mRecentScreenshotAnimator.cancelAnimation();
+            mRecentScreenshotAnimator = null;
+        }
+
         // Update the input windows after the animation is complete
         final InputMonitor inputMonitor =
                 mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 8f4e842..ed5f665 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -682,6 +682,7 @@
         // Finally update all input windows now that the window changes have stabilized.
         forAllDisplays(dc -> {
             dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
+            dc.updateSystemGestureExclusion();
         });
 
         mWmService.setHoldScreenLocked(mHoldScreen);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index dc8c7b7..9b634f9 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -57,6 +57,7 @@
 
 import java.io.PrintWriter;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.function.BiConsumer;
 
@@ -314,6 +315,16 @@
         }
     }
 
+    @Override
+    public void reportSystemGestureExclusionChanged(IWindow window, List<Rect> exclusionRects) {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            mService.reportSystemGestureExclusionChanged(this, window, exclusionRects);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     private void actionOnWallpaper(IBinder window,
             BiConsumer<WallpaperController, WindowState> action) {
         final WindowState windowState = mService.windowForClientLocked(this, window, true);
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
new file mode 100644
index 0000000..e0d85e8
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -0,0 +1,124 @@
+/*
+ * 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.server.wm;
+
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
+
+import android.graphics.GraphicBuffer;
+import android.graphics.Rect;
+import android.util.Slog;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+/**
+ * Class used by {@link RecentsAnimationController} to create a surface control with taking
+ * screenshot of task when canceling recents animation.
+ *
+ * @see {@link RecentsAnimationController#cancelOnNextTransitionStart}
+ */
+class TaskScreenshotAnimatable implements SurfaceAnimator.Animatable {
+    private static final String TAG = "TaskScreenshotAnim";
+    private Task mTask;
+    private SurfaceControl mSurfaceControl;
+    private int mWidth;
+    private int mHeight;
+
+    public static TaskScreenshotAnimatable create(Task task) {
+        return new TaskScreenshotAnimatable(task, getBufferFromTask(task));
+    }
+
+    private static GraphicBuffer getBufferFromTask(Task task) {
+        if (task == null) {
+            return null;
+        }
+        final Rect tmpRect = task.getBounds();
+        tmpRect.offset(0, 0);
+        return SurfaceControl.captureLayers(
+                task.getSurfaceControl().getHandle(), tmpRect, 1f);
+    }
+
+    private TaskScreenshotAnimatable(Task task, GraphicBuffer buffer) {
+        mTask = task;
+        mWidth = (buffer != null) ? buffer.getWidth() : 1;
+        mHeight = (buffer != null) ? buffer.getHeight() : 1;
+        if (DEBUG_RECENTS_ANIMATIONS) {
+            Slog.d(TAG, "Creating TaskScreenshotAnimatable: task: " + task
+                    + "width: " + mWidth + "height: " + mHeight);
+        }
+        mSurfaceControl = new SurfaceControl.Builder(new SurfaceSession())
+                .setName("RecentTaskScreenshotSurface")
+                .setBufferSize(mWidth, mHeight)
+                .build();
+        if (buffer != null) {
+            final Surface surface = new Surface();
+            surface.copyFrom(mSurfaceControl);
+            surface.attachAndQueueBuffer(buffer);
+            surface.release();
+        }
+        getPendingTransaction().show(mSurfaceControl);
+    }
+
+    @Override
+    public SurfaceControl.Transaction getPendingTransaction() {
+        return mTask.mPendingTransaction;
+    }
+
+    @Override
+    public void commitPendingTransaction() {
+        mTask.commitPendingTransaction();
+    }
+
+    @Override
+    public void onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash) {
+        t.setLayer(leash, 1);
+    }
+
+    @Override
+    public void onAnimationLeashDestroyed(SurfaceControl.Transaction t) {
+        t.remove(mSurfaceControl);
+    }
+
+    @Override
+    public SurfaceControl.Builder makeAnimationLeash() {
+        return mTask.makeAnimationLeash();
+    }
+
+    @Override
+    public SurfaceControl getAnimationLeashParent() {
+        return mTask.getAnimationLeashParent();
+    }
+
+    @Override
+    public SurfaceControl getSurfaceControl() {
+        return mSurfaceControl;
+    }
+
+    @Override
+    public SurfaceControl getParentSurfaceControl() {
+        return mTask.mSurfaceAnimator.mLeash;
+    }
+
+    @Override
+    public int getSurfaceWidth() {
+        return mWidth;
+    }
+
+    @Override
+    public int getSurfaceHeight() {
+        return mHeight;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4a9d798f..7751560 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -202,6 +202,7 @@
 import android.view.IPinnedStackListener;
 import android.view.IRecentsAnimationRunner;
 import android.view.IRotationWatcher;
+import android.view.ISystemGestureExclusionListener;
 import android.view.IWallpaperVisibilityListener;
 import android.view.IWindow;
 import android.view.IWindowId;
@@ -274,6 +275,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.List;
 
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
@@ -3817,6 +3819,42 @@
     }
 
     @Override
+    public void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener,
+            int displayId) {
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                throw new IllegalArgumentException("Trying to register visibility event "
+                        + "for invalid display: " + displayId);
+            }
+            displayContent.registerSystemGestureExclusionListener(listener);
+        }
+    }
+
+    @Override
+    public void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener,
+            int displayId) {
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                throw new IllegalArgumentException("Trying to register visibility event "
+                        + "for invalid display: " + displayId);
+            }
+            displayContent.unregisterSystemGestureExclusionListener(listener);
+        }
+    }
+
+    void reportSystemGestureExclusionChanged(Session session, IWindow window,
+            List<Rect> exclusionRects) {
+        synchronized (mGlobalLock) {
+            final WindowState win = windowForClientLocked(session, window, true);
+            if (win.setSystemGestureExclusion(exclusionRects)) {
+                win.getDisplayContent().updateSystemGestureExclusion();
+            }
+        }
+    }
+
+    @Override
     public void registerDisplayFoldListener(IDisplayFoldListener listener) {
         mPolicy.registerDisplayFoldListener(listener);
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ee445d8..600178f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -205,6 +205,7 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.List;
 import java.util.function.Predicate;
 
 /** A window in the window manager. */
@@ -363,6 +364,13 @@
      */
     private final Rect mInsetFrame = new Rect();
 
+    /**
+     * List of rects where system gestures should be ignored.
+     *
+     * Coordinates are relative to the window's position.
+     */
+    private final List<Rect> mExclusionRects = new ArrayList<>();
+
     // If a window showing a wallpaper: the requested offset for the
     // wallpaper; if a wallpaper window: the currently applied offset.
     float mWallpaperX = -1;
@@ -612,6 +620,24 @@
         }
     }
 
+    List<Rect> getSystemGestureExclusion() {
+        return mExclusionRects;
+    }
+
+    /**
+     * Sets the system gesture exclusion rects.
+     *
+     * @return {@code true} if anything changed
+     */
+    boolean setSystemGestureExclusion(List<Rect> exclusionRects) {
+        if (mExclusionRects.equals(exclusionRects)) {
+            return false;
+        }
+        mExclusionRects.clear();
+        mExclusionRects.addAll(exclusionRects);
+        return true;
+    }
+
     interface PowerManagerWrapper {
         void wakeUp(long time, @WakeReason int reason, String details);
 
diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java
new file mode 100644
index 0000000..1458440
--- /dev/null
+++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java
@@ -0,0 +1,45 @@
+/*
+ * 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.server.wm.utils;
+
+import android.graphics.Rect;
+import android.graphics.Region;
+
+import java.util.List;
+
+/**
+ * Utility methods to handle Regions.
+ */
+public class RegionUtils {
+
+    private RegionUtils() {}
+
+
+    /**
+     * Converts a list of rects into a {@code Region}.
+     *
+     * @param rects the list of rects to convert
+     * @param outRegion the Region to set to the list of rects
+     */
+    public static void rectListToRegion(List<Rect> rects, Region outRegion) {
+        outRegion.setEmpty();
+        final int n = rects.size();
+        for (int i = 0; i < n; i++) {
+            outRegion.union(rects.get(i));
+        }
+    }
+}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 57377c6..3d84bd4 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -228,7 +228,7 @@
 
     virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
-    virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices);
+    virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices);
     virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier);
     virtual std::string getDeviceAlias(const InputDeviceIdentifier& identifier);
     virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env,
@@ -598,7 +598,7 @@
     }
 }
 
-void NativeInputManager::notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) {
+void NativeInputManager::notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) {
     ATRACE_CALL();
     JNIEnv* env = jniEnv();
 
@@ -608,7 +608,7 @@
     if (inputDevicesObjArray) {
         bool error = false;
         for (size_t i = 0; i < count; i++) {
-            jobject inputDeviceObj = android_view_InputDevice_create(env, inputDevices.itemAt(i));
+            jobject inputDeviceObj = android_view_InputDevice_create(env, inputDevices[i]);
             if (!inputDeviceObj) {
                 error = true;
                 break;
@@ -775,7 +775,7 @@
 
 void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray,
          int32_t displayId) {
-    Vector<sp<InputWindowHandle> > windowHandles;
+    std::vector<sp<InputWindowHandle> > windowHandles;
 
     if (windowHandleObjArray) {
         jsize length = env->GetArrayLength(windowHandleObjArray);
@@ -788,7 +788,7 @@
             sp<InputWindowHandle> windowHandle =
                     android_view_InputWindowHandle_getHandle(env, windowHandleObj);
             if (windowHandle != nullptr) {
-                windowHandles.push(windowHandle);
+                windowHandles.push_back(windowHandle);
             }
             env->DeleteLocalRef(windowHandleObj);
         }
@@ -800,7 +800,7 @@
     bool newPointerGesturesEnabled = true;
     size_t numWindows = windowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
+        const sp<InputWindowHandle>& windowHandle = windowHandles[i];
         const InputWindowInfo* windowInfo = windowHandle->getInfo();
         if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures
                 & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index a4955f0..a6e9fdd 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -119,7 +119,6 @@
 using android::hardware::gnss::V1_0::IAGnssRilCallback;
 using android::hardware::gnss::V1_0::IGnssBatching;
 using android::hardware::gnss::V1_0::IGnssBatchingCallback;
-using android::hardware::gnss::V1_0::IGnssDebug;
 using android::hardware::gnss::V1_0::IGnssGeofenceCallback;
 using android::hardware::gnss::V1_0::IGnssGeofencing;
 using android::hardware::gnss::V1_0::IGnssNavigationMessage;
@@ -143,9 +142,12 @@
 using IGnss_V1_0 = android::hardware::gnss::V1_0::IGnss;
 using IGnss_V1_1 = android::hardware::gnss::V1_1::IGnss;
 using IGnss_V2_0 = android::hardware::gnss::V2_0::IGnss;
+using IGnssCallback_V1_0 = android::hardware::gnss::V1_0::IGnssCallback;
 using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
 using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
 using IGnssConfiguration_V2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
+using IGnssDebug_V1_0 = android::hardware::gnss::V1_0::IGnssDebug;
+using IGnssDebug_V2_0 = android::hardware::gnss::V2_0::IGnssDebug;
 using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
 using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
 using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
@@ -191,7 +193,8 @@
 sp<IAGnss_V1_0> agnssIface = nullptr;
 sp<IAGnss_V2_0> agnssIface_V2_0 = nullptr;
 sp<IGnssBatching> gnssBatchingIface = nullptr;
-sp<IGnssDebug> gnssDebugIface = nullptr;
+sp<IGnssDebug_V1_0> gnssDebugIface = nullptr;
+sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr;
 sp<IGnssConfiguration_V1_0> gnssConfigurationIface = nullptr;
 sp<IGnssConfiguration_V1_1> gnssConfigurationIface_V1_1 = nullptr;
 sp<IGnssConfiguration_V2_0> gnssConfigurationIface_V2_0 = nullptr;
@@ -548,7 +551,9 @@
 struct GnssCallback : public IGnssCallback {
     Return<void> gnssLocationCb(const GnssLocation_V1_0& location) override;
     Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
-    Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
+    Return<void> gnssSvStatusCb(const IGnssCallback_V1_0::GnssSvStatus& svStatus) override {
+        return gnssSvStatusCbImpl(svStatus);
+    }
     Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
     Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
     Return<void> gnssAcquireWakelockCb() override;
@@ -566,16 +571,47 @@
             override;
     Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
     Return<void> gnssLocationCb_2_0(const GnssLocation_V2_0& location) override;
-
-    // Templated implementation for gnnsLocationCb and gnnsLocationCb_2_0.
-    template <class T>
-    Return<void> gnssLocationCbImpl(const T& location);
+    Return<void> gnssSvStatusCb_2_0(const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList) override {
+        return gnssSvStatusCbImpl(svInfoList);
+    }
 
     Return<void> gnssSetCapabilitesCbImpl(uint32_t capabilities, bool hasSubHalCapabilityFlags);
 
     // TODO: Reconsider allocation cost vs threadsafety on these statics
     static const char* sNmeaString;
     static size_t sNmeaStringLength;
+private:
+    template<class T>
+    Return<void> gnssLocationCbImpl(const T& location);
+
+    template<class T>
+    Return<void> gnssSvStatusCbImpl(const T& svStatus);
+
+    uint32_t getGnssSvInfoListSize(const IGnssCallback_V1_0::GnssSvStatus& svStatus) {
+        return svStatus.numSvs;
+    }
+
+    uint32_t getGnssSvInfoListSize(const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList) {
+        return svInfoList.size();
+    }
+
+    const IGnssCallback_V1_0::GnssSvInfo& getGnssSvInfoOfIndex(
+            const IGnssCallback_V1_0::GnssSvStatus& svStatus, size_t i) {
+        return svStatus.gnssSvList.data()[i];
+    }
+
+    const IGnssCallback_V1_0::GnssSvInfo& getGnssSvInfoOfIndex(
+            const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList, size_t i) {
+        return svInfoList[i].v1_0;
+    }
+
+    uint32_t getConstellationType(const IGnssCallback_V1_0::GnssSvStatus& svStatus, size_t i) {
+        return static_cast<uint32_t>(svStatus.gnssSvList.data()[i].constellation);
+    }
+
+    uint32_t getConstellationType(const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList, size_t i) {
+        return static_cast<uint32_t>(svInfoList[i].constellation);
+    }
 };
 
 Return<void> GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
@@ -623,10 +659,11 @@
     return Void();
 }
 
-Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) {
+template<class T>
+Return<void> GnssCallback::gnssSvStatusCbImpl(const T& svStatus) {
     JNIEnv* env = getJniEnv();
 
-    uint32_t listSize = svStatus.numSvs;
+    uint32_t listSize = getGnssSvInfoListSize(svStatus);
     if (listSize > static_cast<uint32_t>(
             android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)) {
         ALOGD("Too many satellites %u. Clamps to %u.", listSize,
@@ -655,9 +692,9 @@
             CONSTELLATION_TYPE_SHIFT_WIDTH = 4
         };
 
-        const IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList.data()[i];
+        const IGnssCallback_V1_0::GnssSvInfo& info = getGnssSvInfoOfIndex(svStatus, i);
         svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
-            (static_cast<uint32_t>(info.constellation) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
+            (getConstellationType(svStatus, i) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
             static_cast<uint32_t>(info.svFlag);
         cn0s[i] = info.cN0Dbhz;
         elev[i] = info.elevationDegrees;
@@ -1079,6 +1116,9 @@
 
     // Overwrite with v2_0.state since v2_0->v1_1->v1_0.state is deprecated.
     SET(State, static_cast<int32_t>(measurement_V2_0->state));
+
+    // Overwrite with v2_0.constellation since v2_0->v1_1->v1_0.constellation is deprecated.
+    SET(ConstellationType, static_cast<int32_t>(measurement_V2_0->constellation));
 }
 
 jobject GnssMeasurementCallback::translateGnssClock(
@@ -1656,11 +1696,21 @@
          }
     }
 
-    auto gnssDebug = gnssHal->getExtensionGnssDebug();
-    if (!gnssDebug.isOk()) {
-        ALOGD("Unable to get a handle to GnssDebug");
+    if (gnssHal_V2_0 != nullptr) {
+        auto gnssDebug = gnssHal_V2_0->getExtensionGnssDebug_2_0();
+        if (!gnssDebug.isOk()) {
+            ALOGD("Unable to get a handle to GnssDebug_V2_0");
+        } else {
+            gnssDebugIface_V2_0 = gnssDebug;
+            gnssDebugIface = gnssDebugIface_V2_0;
+        }
     } else {
-        gnssDebugIface = gnssDebug;
+        auto gnssDebug = gnssHal->getExtensionGnssDebug();
+        if (!gnssDebug.isOk()) {
+            ALOGD("Unable to get a handle to GnssDebug");
+        } else {
+            gnssDebugIface = gnssDebug;
+        }
     }
 
     auto gnssNi = gnssHal->getExtensionGnssNi();
@@ -2189,6 +2239,76 @@
     gnssNiIface->respond(notifId, static_cast<IGnssNiCallback::GnssUserResponseType>(response));
 }
 
+const IGnssDebug_V1_0::SatelliteData& getSatelliteData(const hidl_vec<IGnssDebug_V1_0::SatelliteData>& satelliteDataArray, size_t i) {
+    return satelliteDataArray[i];
+}
+
+const IGnssDebug_V1_0::SatelliteData& getSatelliteData(const hidl_vec<IGnssDebug_V2_0::SatelliteData>& satelliteDataArray, size_t i) {
+    return satelliteDataArray[i].v1_0;
+}
+
+template<class T>
+uint32_t getConstellationType(const hidl_vec<T>& satelliteDataArray, size_t i) {
+    return static_cast<uint32_t>(satelliteDataArray[i].constellation);
+}
+
+template<class T>
+static jstring parseDebugData(JNIEnv* env, std::stringstream& internalState, const T& data) {
+    internalState << "Gnss Location Data:: ";
+    if (!data.position.valid) {
+        internalState << "not valid";
+    } else {
+        internalState << "LatitudeDegrees: " << data.position.latitudeDegrees
+                      << ", LongitudeDegrees: " << data.position.longitudeDegrees
+                      << ", altitudeMeters: " << data.position.altitudeMeters
+                      << ", speedMetersPerSecond: " << data.position.speedMetersPerSec
+                      << ", bearingDegrees: " << data.position.bearingDegrees
+                      << ", horizontalAccuracyMeters: "
+                      << data.position.horizontalAccuracyMeters
+                      << ", verticalAccuracyMeters: " << data.position.verticalAccuracyMeters
+                      << ", speedAccuracyMetersPerSecond: "
+                      << data.position.speedAccuracyMetersPerSecond
+                      << ", bearingAccuracyDegrees: " << data.position.bearingAccuracyDegrees
+                      << ", ageSeconds: " << data.position.ageSeconds;
+    }
+    internalState << std::endl;
+
+    internalState << "Gnss Time Data:: timeEstimate: " << data.time.timeEstimate
+                  << ", timeUncertaintyNs: " << data.time.timeUncertaintyNs
+                  << ", frequencyUncertaintyNsPerSec: "
+                  << data.time.frequencyUncertaintyNsPerSec << std::endl;
+
+    if (data.satelliteDataArray.size() != 0) {
+        internalState << "Satellite Data for " << data.satelliteDataArray.size()
+                      << " satellites:: " << std::endl;
+    }
+
+    internalState << "constell: 1=GPS, 2=SBAS, 3=GLO, 4=QZSS, 5=BDS, 6=GAL, 7=IRNSS; "
+                  << "ephType: 0=Eph, 1=Alm, 2=Unk; "
+                  << "ephSource: 0=Demod, 1=Supl, 2=Server, 3=Unk; "
+                  << "ephHealth: 0=Good, 1=Bad, 2=Unk" << std::endl;
+    for (size_t i = 0; i < data.satelliteDataArray.size(); i++) {
+        IGnssDebug_V1_0::SatelliteData satelliteData =
+                getSatelliteData(data.satelliteDataArray, i);
+        internalState << "constell: "
+                      << getConstellationType(data.satelliteDataArray, i)
+                      << ", svid: " << std::setw(3) << satelliteData.svid
+                      << ", serverPredAvail: "
+                      << satelliteData.serverPredictionIsAvailable
+                      << ", serverPredAgeSec: " << std::setw(7)
+                      << satelliteData.serverPredictionAgeSeconds
+                      << ", ephType: "
+                      << static_cast<uint32_t>(satelliteData.ephemerisType)
+                      << ", ephSource: "
+                      << static_cast<uint32_t>(satelliteData.ephemerisSource)
+                      << ", ephHealth: "
+                      << static_cast<uint32_t>(satelliteData.ephemerisHealth)
+                      << ", ephAgeSec: " << std::setw(7)
+                      << satelliteData.ephemerisAgeSeconds << std::endl;
+    }
+    return (jstring) env->NewStringUTF(internalState.str().c_str());
+}
+
 static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
                                                                        jobject /* obj */) {
     jstring result = nullptr;
@@ -2200,65 +2320,19 @@
 
     if (gnssDebugIface == nullptr) {
         internalState << "Gnss Debug Interface not available"  << std::endl;
-    } else {
-        IGnssDebug::DebugData data;
-        gnssDebugIface->getDebugData([&data](const IGnssDebug::DebugData& debugData) {
+    } else if (gnssDebugIface_V2_0 != nullptr) {
+        IGnssDebug_V2_0::DebugData data;
+        gnssDebugIface_V2_0->getDebugData_2_0([&data](const IGnssDebug_V2_0::DebugData& debugData) {
             data = debugData;
         });
-
-        internalState << "Gnss Location Data:: ";
-        if (!data.position.valid) {
-            internalState << "not valid";
-        } else {
-            internalState << "LatitudeDegrees: " << data.position.latitudeDegrees
-                          << ", LongitudeDegrees: " << data.position.longitudeDegrees
-                          << ", altitudeMeters: " << data.position.altitudeMeters
-                          << ", speedMetersPerSecond: " << data.position.speedMetersPerSec
-                          << ", bearingDegrees: " << data.position.bearingDegrees
-                          << ", horizontalAccuracyMeters: "
-                          << data.position.horizontalAccuracyMeters
-                          << ", verticalAccuracyMeters: " << data.position.verticalAccuracyMeters
-                          << ", speedAccuracyMetersPerSecond: "
-                          << data.position.speedAccuracyMetersPerSecond
-                          << ", bearingAccuracyDegrees: " << data.position.bearingAccuracyDegrees
-                          << ", ageSeconds: " << data.position.ageSeconds;
-        }
-        internalState << std::endl;
-
-        internalState << "Gnss Time Data:: timeEstimate: " << data.time.timeEstimate
-                      << ", timeUncertaintyNs: " << data.time.timeUncertaintyNs
-                      << ", frequencyUncertaintyNsPerSec: "
-                      << data.time.frequencyUncertaintyNsPerSec << std::endl;
-
-        if (data.satelliteDataArray.size() != 0) {
-            internalState << "Satellite Data for " << data.satelliteDataArray.size()
-                          << " satellites:: " << std::endl;
-        }
-
-        internalState << "constell: 1=GPS, 2=SBAS, 3=GLO, 4=QZSS, 5=BDS, 6=GAL; "
-                      << "ephType: 0=Eph, 1=Alm, 2=Unk; "
-                      << "ephSource: 0=Demod, 1=Supl, 2=Server, 3=Unk; "
-                      << "ephHealth: 0=Good, 1=Bad, 2=Unk" << std::endl;
-        for (size_t i = 0; i < data.satelliteDataArray.size(); i++) {
-            internalState << "constell: "
-                          << static_cast<uint32_t>(data.satelliteDataArray[i].constellation)
-                          << ", svid: " << std::setw(3) << data.satelliteDataArray[i].svid
-                          << ", serverPredAvail: "
-                          << data.satelliteDataArray[i].serverPredictionIsAvailable
-                          << ", serverPredAgeSec: " << std::setw(7)
-                          << data.satelliteDataArray[i].serverPredictionAgeSeconds
-                          << ", ephType: "
-                          << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisType)
-                          << ", ephSource: "
-                          << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisSource)
-                          << ", ephHealth: "
-                          << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisHealth)
-                          << ", ephAgeSec: " << std::setw(7)
-                          << data.satelliteDataArray[i].ephemerisAgeSeconds << std::endl;
-        }
+        result = parseDebugData(env, internalState, data);
+    } else {
+        IGnssDebug_V1_0::DebugData data;
+        gnssDebugIface->getDebugData([&data](const IGnssDebug_V1_0::DebugData& debugData) {
+            data = debugData;
+        });
+        result = parseDebugData(env, internalState, data);
     }
-
-    result = env->NewStringUTF(internalState.str().c_str());
     return result;
 }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 39af565..419f52c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1230,6 +1230,7 @@
             }
 
             startContentCaptureService(context);
+            startAttentionService(context);
 
             // App prediction manager service
             traceBeginAndSlog("StartAppPredictionService");
@@ -1284,10 +1285,6 @@
                 traceEnd();
             }
 
-            traceBeginAndSlog("StartAttentionManagerService");
-            mSystemServiceManager.startService(AttentionManagerService.class);
-            traceEnd();
-
             traceBeginAndSlog("StartNetworkScoreService");
             mSystemServiceManager.startService(NetworkScoreService.Lifecycle.class);
             traceEnd();
@@ -2260,6 +2257,17 @@
         traceEnd();
     }
 
+    private void startAttentionService(@NonNull Context context) {
+        if (!AttentionManagerService.isServiceConfigured(context)) {
+            Slog.d(TAG, "AttentionService is not configured on this device");
+            return;
+        }
+
+        traceBeginAndSlog("StartAttentionManagerService");
+        mSystemServiceManager.startService(AttentionManagerService.class);
+        traceEnd();
+    }
+
     static final void startSystemUi(Context context, WindowManagerService windowManager) {
         Intent intent = new Intent();
         intent.setComponent(new ComponentName("com.android.systemui",
diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java
index 398a6b31..d79ad1f 100644
--- a/services/net/java/android/net/TcpKeepalivePacketData.java
+++ b/services/net/java/android/net/TcpKeepalivePacketData.java
@@ -25,8 +25,8 @@
 import android.os.Parcelable;
 import android.system.OsConstants;
 
-import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.Objects;
@@ -56,10 +56,10 @@
 
     // This should only be constructed via static factory methods, such as
     // tcpKeepalivePacket.
-    private TcpKeepalivePacketData(TcpSocketInfo tcpDetails, byte[] data)
-            throws InvalidPacketException {
-        super(tcpDetails.srcAddress, tcpDetails.srcPort, tcpDetails.dstAddress,
-                tcpDetails.dstPort, data);
+    private TcpKeepalivePacketData(final TcpKeepalivePacketDataParcelable tcpDetails,
+            final byte[] data) throws InvalidPacketException, UnknownHostException {
+        super(InetAddress.getByAddress(tcpDetails.srcAddress), tcpDetails.srcPort,
+                InetAddress.getByAddress(tcpDetails.dstAddress), tcpDetails.dstPort, data);
         tcpSeq = tcpDetails.seq;
         tcpAck = tcpDetails.ack;
         // In the packet, the window is shifted right by the window scale.
@@ -71,17 +71,22 @@
      * Factory method to create tcp keepalive packet structure.
      */
     public static TcpKeepalivePacketData tcpKeepalivePacket(
-            TcpSocketInfo tcpDetails) throws InvalidPacketException {
+            TcpKeepalivePacketDataParcelable tcpDetails) throws InvalidPacketException {
         final byte[] packet;
-        if ((tcpDetails.srcAddress instanceof Inet4Address)
-                && (tcpDetails.dstAddress instanceof Inet4Address)) {
-            packet = buildV4Packet(tcpDetails);
-        } else {
-            // TODO: support ipv6
+        try {
+            if ((tcpDetails.srcAddress != null) && (tcpDetails.dstAddress != null)
+                    && (tcpDetails.srcAddress.length == 4 /* V4 IP length */)
+                    && (tcpDetails.dstAddress.length == 4 /* V4 IP length */)) {
+                packet = buildV4Packet(tcpDetails);
+            } else {
+                // TODO: support ipv6
+                throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+            }
+            return new TcpKeepalivePacketData(tcpDetails, packet);
+        } catch (UnknownHostException e) {
             throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
         }
 
-        return new TcpKeepalivePacketData(tcpDetails, packet);
     }
 
     /**
@@ -89,7 +94,7 @@
      */
     // TODO : if this code is ever moved to the network stack, factorize constants with the ones
     // over there.
-    private static byte[] buildV4Packet(TcpSocketInfo tcpDetails) {
+    private static byte[] buildV4Packet(TcpKeepalivePacketDataParcelable tcpDetails) {
         final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH;
         ByteBuffer buf = ByteBuffer.allocate(length);
         buf.order(ByteOrder.BIG_ENDIAN);
@@ -102,8 +107,8 @@
         buf.put((byte) OsConstants.IPPROTO_TCP);
         final int ipChecksumOffset = buf.position();
         buf.putShort((short) 0);                    // IP checksum
-        buf.put(tcpDetails.srcAddress.getAddress());
-        buf.put(tcpDetails.dstAddress.getAddress());
+        buf.put(tcpDetails.srcAddress);
+        buf.put(tcpDetails.dstAddress);
         buf.putShort((short) tcpDetails.srcPort);
         buf.putShort((short) tcpDetails.dstPort);
         buf.putInt(tcpDetails.seq);                 // Sequence Number
@@ -122,31 +127,6 @@
 
     // TODO: add buildV6Packet.
 
-    /** Represents tcp/ip information. */
-    // TODO: Replace TcpSocketInfo with TcpKeepalivePacketDataParcelable.
-    public static class TcpSocketInfo {
-        public final InetAddress srcAddress;
-        public final InetAddress dstAddress;
-        public final int srcPort;
-        public final int dstPort;
-        public final int seq;
-        public final int ack;
-        public final int rcvWnd;
-        public final int rcvWndScale;
-
-        public TcpSocketInfo(InetAddress sAddr, int sPort, InetAddress dAddr,
-                int dPort, int writeSeq, int readSeq, int rWnd, int rWndScale) {
-            srcAddress = sAddr;
-            dstAddress = dAddr;
-            srcPort = sPort;
-            dstPort = dPort;
-            seq = writeSeq;
-            ack = readSeq;
-            rcvWnd = rWnd;
-            rcvWndScale = rWndScale;
-        }
-    }
-
     @Override
     public boolean equals(@Nullable final Object o) {
         if (!(o instanceof TcpKeepalivePacketData)) return false;
@@ -218,6 +198,8 @@
         parcel.dstPort = dstPort;
         parcel.seq = tcpSeq;
         parcel.ack = tcpAck;
+        parcel.rcvWnd = tcpWnd;
+        parcel.rcvWndScale = tcpWndScale;
         return parcel;
     }
 
diff --git a/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java
index 9a6e003..42115d4 100644
--- a/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java
@@ -554,7 +554,7 @@
                 transportManager.getTransportCurrentDestinationString(mTransportA1.transportName);
         Intent dataManagementIntent =
                 transportManager.getTransportDataManagementIntent(mTransportA1.transportName);
-        String dataManagementLabel =
+        CharSequence dataManagementLabel =
                 transportManager.getTransportDataManagementLabel(mTransportA1.transportName);
         String transportDirName = transportManager.getTransportDirName(mTransportA1.transportName);
         String transportDirNameByComponent =
diff --git a/services/robotests/backup/src/com/android/server/backup/testing/TransportData.java b/services/robotests/backup/src/com/android/server/backup/testing/TransportData.java
index 77f5d9a4..3c29810 100644
--- a/services/robotests/backup/src/com/android/server/backup/testing/TransportData.java
+++ b/services/robotests/backup/src/com/android/server/backup/testing/TransportData.java
@@ -75,7 +75,7 @@
     @Nullable public Intent configurationIntent;
     @Nullable public String currentDestinationString;
     @Nullable public Intent dataManagementIntent;
-    @Nullable public String dataManagementLabel;
+    @Nullable public CharSequence dataManagementLabel;
 
     private TransportData(
             @TransportStatus int transportStatus,
@@ -85,7 +85,7 @@
             Intent configurationIntent,
             String currentDestinationString,
             Intent dataManagementIntent,
-            String dataManagementLabel) {
+            CharSequence dataManagementLabel) {
         this.transportStatus = transportStatus;
         this.transportName = transportName;
         this.transportComponentShort = transportComponentShort;
@@ -103,7 +103,7 @@
             Intent configurationIntent,
             String currentDestinationString,
             Intent dataManagementIntent,
-            String dataManagementLabel) {
+            CharSequence dataManagementLabel) {
         this(
                 TransportStatus.REGISTERED_AVAILABLE,
                 transportName,
diff --git a/services/robotests/backup/src/com/android/server/backup/testing/TransportTestUtils.java b/services/robotests/backup/src/com/android/server/backup/testing/TransportTestUtils.java
index f6ed630..7dd5be5 100644
--- a/services/robotests/backup/src/com/android/server/backup/testing/TransportTestUtils.java
+++ b/services/robotests/backup/src/com/android/server/backup/testing/TransportTestUtils.java
@@ -188,7 +188,8 @@
             when(transportBinder.currentDestinationString())
                     .thenReturn(transport.currentDestinationString);
             when(transportBinder.dataManagementIntent()).thenReturn(transport.dataManagementIntent);
-            when(transportBinder.dataManagementLabel()).thenReturn(transport.dataManagementLabel);
+            when(transportBinder.dataManagementIntentLabel())
+                    .thenReturn(transport.dataManagementLabel);
         } catch (RemoteException e) {
             fail("RemoteException?");
         }
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index 3e5ce46..dd79aad 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -82,7 +82,7 @@
     private static final String CURRENT_PASSWORD = "current_password";
     private static final String NEW_PASSWORD = "new_password";
     private static final String ENCRYPTION_PASSWORD = "encryption_password";
-    private static final String DATA_MANAGEMENT_LABEL = "data_management_label";
+    private static final CharSequence DATA_MANAGEMENT_LABEL = "data_management_label";
     private static final String DESTINATION_STRING = "destination_string";
     private static final String[] PACKAGE_NAMES =
             new String[]{"some.package.name._1", "some.package.name._2"};
@@ -1104,8 +1104,8 @@
     }
 
     @Test
-    public void getDataManagementLabel_calledBeforeInitialize_ignored() throws Exception {
-        assertNull(mTrampoline.getDataManagementLabel(TRANSPORT_NAME));
+    public void getDataManagementLabelForUser_calledBeforeInitialize_ignored() throws Exception {
+        assertNull(mTrampoline.getDataManagementLabelForUser(mUserId, TRANSPORT_NAME));
         verifyNoMoreInteractions(mBackupManagerServiceMock);
     }
 
@@ -1122,17 +1122,6 @@
     }
 
     @Test
-    public void getDataManagementLabel_forwarded() throws Exception {
-        TrampolineTestable.sCallingUserId = mUserId;
-        when(mBackupManagerServiceMock.getDataManagementLabel(mUserId, TRANSPORT_NAME)).thenReturn(
-                DATA_MANAGEMENT_LABEL);
-        mTrampoline.initializeService();
-
-        assertEquals(DATA_MANAGEMENT_LABEL, mTrampoline.getDataManagementLabel(TRANSPORT_NAME));
-        verify(mBackupManagerServiceMock).getDataManagementLabel(mUserId, TRANSPORT_NAME);
-    }
-
-    @Test
     public void beginRestoreSession_calledBeforeInitialize_ignored() throws Exception {
         mTrampoline.beginRestoreSessionForUser(mUserId, PACKAGE_NAME, TRANSPORT_NAME);
         verifyNoMoreInteractions(mBackupManagerServiceMock);
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
index 26b1224..caf6c9c 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
@@ -1138,7 +1138,7 @@
     }
 
     @Override
-    public String getContentCaptureServicePackageName() throws RemoteException {
+    public String getSystemCaptionsServicePackageName() throws RemoteException {
         return null;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index cd095a5..fa1bcac 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -35,6 +35,7 @@
 import android.app.Person;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.LocusId;
 import android.content.pm.ShortcutInfo;
 import android.content.res.Resources;
 import android.graphics.BitmapFactory;
@@ -895,6 +896,7 @@
                 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
                 .setRank(123)
                 .setExtras(pb)
+                .setLocusId(new LocusId("1.2.3.4.5"))
                 .build();
         sorig.setTimestamp(mInjectedCurrentTimeMillis);
 
@@ -906,6 +908,7 @@
                 .setPersons(list(makePerson("person1", "personKey1", "personUri1"),
                         makePerson("person2", "personKey2", "personUri2")).toArray(new Person[2]))
                 .setRank(456)
+                .setLocusId(new LocusId("6.7.8.9"))
                 .build();
         sorig2.setTimestamp(mInjectedCurrentTimeMillis);
 
@@ -946,6 +949,7 @@
         assertEquals("personUri", si.getPersons()[0].getUri());
         assertEquals(0, si.getRank());
         assertEquals(1, si.getExtras().getInt("k"));
+        assertEquals("1.2.3.4.5", si.getLocusId().getId());
 
         assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE
                 | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
@@ -959,6 +963,7 @@
         assertEquals(1, si.getRank());
         assertEquals(2, si.getPersons().length);
         assertEquals("personUri2", si.getPersons()[1].getUri());
+        assertEquals("6.7.8.9", si.getLocusId().getId());
 
         dumpUserFile(USER_10);
     }
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index a2f1f01..a1a58b4 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -105,6 +105,13 @@
     }
 
     @Test
+    public void testOnUserActivity_doesntCrashIfNoAttentionService() {
+        mAttentionManagerInternal = null;
+        registerAttention();
+        // Does not crash.
+    }
+
+    @Test
     public void onUserActivity_ignoresWhiteListedActivityTypes() {
         for (int i = 0; i < NUM_USER_ACTIVITY_TYPES; i++) {
             int result = mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(), i);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 6f96759..a8da80e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -391,7 +391,8 @@
 
         mBinderService.createNotificationChannels(
                 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
-        assertNotNull(mBinderService.getNotificationChannel(PKG, TEST_CHANNEL_ID));
+        assertNotNull(mBinderService.getNotificationChannel(
+                PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
     }
 
     @After
@@ -497,7 +498,7 @@
         mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(channel)));
         final NotificationChannel createdChannel =
-                mBinderService.getNotificationChannel(PKG, "id");
+                mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
         assertTrue(createdChannel != null);
     }
 
@@ -520,8 +521,10 @@
                 new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT);
         mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
-        assertTrue(mBinderService.getNotificationChannel(PKG, "id1") != null);
-        assertTrue(mBinderService.getNotificationChannel(PKG, "id2") != null);
+        assertTrue(mBinderService.getNotificationChannel(
+                PKG, mContext.getUserId(), PKG, "id1") != null);
+        assertTrue(mBinderService.getNotificationChannel(
+                PKG, mContext.getUserId(), PKG, "id2") != null);
     }
 
     @Test
@@ -538,7 +541,7 @@
         mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(dupeChannel)));
         final NotificationChannel createdChannel =
-                mBinderService.getNotificationChannel(PKG, "id");
+                mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
     }
 
@@ -556,7 +559,7 @@
         mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(dupeChannel)));
         final NotificationChannel createdChannel =
-                mBinderService.getNotificationChannel(PKG, "id");
+                mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
         assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
     }
 
@@ -579,7 +582,7 @@
         mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(dupeChannel)));
         final NotificationChannel createdChannel =
-                mBinderService.getNotificationChannel(PKG, "id");
+                mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
         assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance());
     }
 
@@ -593,7 +596,7 @@
         mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
         final NotificationChannel createdChannel =
-                mBinderService.getNotificationChannel(PKG, "id");
+                mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
         assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance());
     }
 
@@ -646,8 +649,8 @@
         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
         assertEquals(IMPORTANCE_LOW,
                 mService.getNotificationRecord(sbn.getKey()).getImportance());
-        assertEquals(IMPORTANCE_LOW,
-                mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+        assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
+                PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
     }
 
     @Test
@@ -664,8 +667,8 @@
                 new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
         waitForIdle();
-        assertEquals(IMPORTANCE_NONE,
-                mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+        assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
+                PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
 
         StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -677,8 +680,8 @@
         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
         assertEquals(IMPORTANCE_LOW,
                 mService.getNotificationRecord(sbn.getKey()).getImportance());
-        assertEquals(IMPORTANCE_LOW,
-                mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+        assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel(
+                PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
         mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
         waitForIdle();
 
@@ -686,8 +689,8 @@
         update.setFgServiceShown(true);
         mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
         waitForIdle();
-        assertEquals(IMPORTANCE_NONE,
-                mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+        assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
+                PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
 
         sbn = generateNotificationRecord(channel).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -697,8 +700,8 @@
         // The second time it is shown, we keep the user's preference.
         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
         assertNull(mService.getNotificationRecord(sbn.getKey()));
-        assertEquals(IMPORTANCE_NONE,
-                mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+        assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel(
+                PKG, mContext.getUserId(), PKG, channel.getId()).getImportance());
     }
 
     @Test
@@ -2692,7 +2695,7 @@
                 mService.getNotificationRecord(sbn.getKey()).getImportance());
 
         NotificationChannel defaultChannel = mBinderService.getNotificationChannel(
-                preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
+                preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID);
         assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance());
     }
 
@@ -4192,6 +4195,25 @@
     }
 
     @Test
+    public void testgetNotificationChannels_crossUser() throws Exception {
+        // same user no problem
+        mBinderService.getNotificationChannels("src", "target", mContext.getUserId());
+
+        // cross user, no permission, problem
+        try {
+            mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
+            fail("Should not be callable cross user without cross user permission");
+        } catch (SecurityException e) {
+            // good
+        }
+
+        // cross user, with permission, no problem
+        TestablePermissions perms = mContext.getTestablePermissions();
+        perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED);
+        mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1);
+    }
+
+    @Test
     public void setDefaultAssistantForUser_fromConfigXml() {
         clearDeviceConfig();
         ComponentName xmlConfig = new ComponentName("config", "xml");
@@ -4264,4 +4286,18 @@
                 componentName,
                 false);
     }
+
+    public void testGetAllowedAssistantCapabilities() throws Exception {
+        List<String> capabilities = mBinderService.getAllowedAssistantCapabilities(null);
+        assertNotNull(capabilities);
+
+        for (int i = capabilities.size() - 1; i >= 0; i--) {
+            String capability = capabilities.get(i);
+            mBinderService.disallowAssistantCapability(capability);
+            assertEquals(i + 1, mBinderService.getAllowedAssistantCapabilities(null).size());
+            List<String> currentCapabilities = mBinderService.getAllowedAssistantCapabilities(null);
+            assertNotNull(currentCapabilities);
+            assertFalse(currentCapabilities.contains(capability));
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 81133d1..9bd9930 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -17,12 +17,16 @@
 package com.android.server.wm;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
 
 import android.platform.test.annotations.Presubmit;
 import android.view.WindowManager;
@@ -95,4 +99,24 @@
                             TRANSIT_TASK_CHANGE_WINDOWING_MODE));
         }
     }
+
+    @Test
+    public void testTransitWithinTask() {
+        synchronized (mWm.mGlobalLock) {
+            final AppWindowToken opening = createAppWindowToken(mDisplayContent,
+                    WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
+            opening.setFillsParent(false);
+            final AppWindowToken closing = createAppWindowToken(mDisplayContent,
+                    WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
+            closing.setFillsParent(false);
+            Task task = opening.getTask();
+            mDisplayContent.mOpeningApps.add(opening);
+            mDisplayContent.mClosingApps.add(closing);
+            assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_ACTIVITY_OPEN, task));
+            closing.getTask().removeChild(closing);
+            task.addChild(closing, 0);
+            assertTrue(mAppTransitionController.isTransitWithinTask(TRANSIT_ACTIVITY_OPEN, task));
+            assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_TASK_OPEN, task));
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 98333b2..e60e54c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -25,6 +25,8 @@
 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.DisplayCutout.fromBoundingRect;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -58,12 +60,15 @@
 import android.app.WindowConfiguration;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.metrics.LogMaker;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.util.DisplayMetrics;
+import android.util.MutableBoolean;
 import android.view.DisplayCutout;
 import android.view.Gravity;
+import android.view.ISystemGestureExclusionListener;
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.ViewRootImpl;
@@ -683,6 +688,60 @@
     }
 
     @Test
+    public void testUpdateSystemGestureExclusion() throws Exception {
+        final DisplayContent dc = createNewDisplay();
+        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
+        win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+        win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
+
+        dc.setLayoutNeeded();
+        dc.performLayout(true /* initial */, false /* updateImeWindows */);
+
+        win.setHasSurface(true);
+        dc.updateSystemGestureExclusion();
+
+        final MutableBoolean invoked = new MutableBoolean(false);
+        final ISystemGestureExclusionListener.Stub verifier =
+                new ISystemGestureExclusionListener.Stub() {
+            @Override
+            public void onSystemGestureExclusionChanged(int displayId, Region actual) {
+                Region expected = Region.obtain();
+                expected.set(10, 20, 30, 40);
+                assertEquals(expected, actual);
+                invoked.value = true;
+            }
+        };
+        try {
+            dc.registerSystemGestureExclusionListener(verifier);
+        } finally {
+            dc.unregisterSystemGestureExclusionListener(verifier);
+        }
+        assertTrue("SystemGestureExclusionListener was not invoked", invoked.value);
+    }
+
+    @Test
+    public void testCalculateSystemGestureExclusion() throws Exception {
+        final DisplayContent dc = createNewDisplay();
+        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
+        win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+        win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
+
+        final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
+        win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+        win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
+
+        dc.setLayoutNeeded();
+        dc.performLayout(true /* initial */, false /* updateImeWindows */);
+
+        win.setHasSurface(true);
+        win2.setHasSurface(true);
+
+        final Region expected = Region.obtain();
+        expected.set(20, 30, 40, 50);
+        assertEquals(expected, dc.calculateSystemGestureExclusion());
+    }
+
+    @Test
     public void testOrientationChangeLogging() {
         MetricsLogger mockLogger = mock(MetricsLogger.class);
         Configuration oldConfig = new Configuration();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index a03d28b..e392353 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -20,17 +20,23 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
 
 import android.os.Binder;
@@ -67,7 +73,11 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-
+        synchronized (mWm.mGlobalLock) {
+            // Hold the lock to protect the stubbing from being accessed by other threads.
+            spyOn(mWm.mRoot);
+            doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
+        }
         when(mMockRunner.asBinder()).thenReturn(new Binder());
         mController = new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks,
                 DEFAULT_DISPLAY);
@@ -88,7 +98,7 @@
         // Verify that the finish callback to reparent the leash is called
         verify(mFinishedCallback).onAnimationFinished(eq(adapter));
         // Verify the animation canceled callback to the app was made
-        verify(mMockRunner).onAnimationCanceled();
+        verify(mMockRunner).onAnimationCanceled(false);
         verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
     }
 
@@ -131,6 +141,31 @@
         assertFalse(mController.isAnimatingTask(hiddenAppWindow.getTask()));
     }
 
+    @Test
+    public void testCancelAnimationWithScreenShot() throws Exception {
+        mWm.setRecentsAnimationController(mController);
+        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
+        appWindow.addWindow(win1);
+        assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow);
+        assertEquals(appWindow.findMainWindow(), win1);
+
+        mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */);
+        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+
+        mController.setCancelWithDeferredScreenshotLocked(true);
+        mController.cancelAnimationWithScreenShot();
+        verify(mMockRunner).onAnimationCanceled(true /* deferredWithScreenshot */);
+        assertNotNull(mController.mRecentScreenshotAnimator);
+        assertTrue(mController.mRecentScreenshotAnimator.isAnimating());
+
+        // Assume IRecentsAnimationController#cleanupScreenshot called to finish screenshot
+        // animation.
+        mController.mRecentScreenshotAnimator.cancelAnimation();
+        verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, true);
+    }
+
     private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
         verify(binder, atLeast(0)).asBinder();
         verifyNoMoreInteractions(binder);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 5f3a290..5625ea4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -20,7 +20,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -29,6 +28,8 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 
+import static org.mockito.ArgumentMatchers.any;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -51,11 +52,15 @@
 
     private Context mContext = InstrumentationRegistry.getContext();
     private ComponentName mRecentsComponent;
+    private RecentsAnimationController mRecentsAnimationController;
 
     @Before
     public void setUp() throws Exception {
         mRecentsComponent = new ComponentName(mContext.getPackageName(), "RecentsActivity");
         mService = new TestActivityTaskManagerService(mContext);
+        mRecentsAnimationController = mock(RecentsAnimationController.class);
+        doReturn(mRecentsAnimationController).when(
+                mService.mWindowManager).getRecentsAnimationController();
 
         final RecentTasks recentTasks = mService.getRecentTasks();
         spyOn(recentTasks);
@@ -96,9 +101,18 @@
 
         fullscreenStack.moveToFront("Activity start");
 
-        // Ensure that the recents animation was canceled
+        // Ensure that the recents animation was canceled by cancelAnimationSynchronously().
         verify(mService.mWindowManager, times(1)).cancelRecentsAnimationSynchronously(
                 eq(REORDER_KEEP_IN_PLACE), any());
+
+        // Assume recents animation already started, set a state that cancel recents animation
+        // with screenshot.
+        doReturn(true).when(mRecentsAnimationController).shouldCancelWithDeferredScreenshot();
+        // Start another fullscreen activity.
+        fullscreenStack2.moveToFront("Activity start");
+
+        // Ensure that the recents animation was canceled by cancelOnNextTransitionStart().
+        verify(mRecentsAnimationController, times(1)).cancelOnNextTransitionStart();
     }
 
     @Test
@@ -137,5 +151,6 @@
         // Ensure that the recents animation was NOT canceled
         verify(mService.mWindowManager, times(0)).cancelRecentsAnimationSynchronously(
                 eq(REORDER_KEEP_IN_PLACE), any());
+        verify(mRecentsAnimationController, times(0)).cancelOnNextTransitionStart();
     }
 }
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index f5b4308..92ea872 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -22,7 +22,6 @@
     ],
     shared_libs: [
         "libbase",
-        "libz",
         "slicer",
     ],
     static_libs: [
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c4c5983..2edef83 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2595,7 +2595,9 @@
      *              {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means
      *              it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *              is used to determine which modem is preferred.
-     * @param needValidation whether validation is needed before switch happens.
+     * @param needValidation whether Telephony will wait until the network is validated by
+     *              connectivity service before switching data to it. More details see
+     *              {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}.
      * @param executor The executor of where the callback will execute.
      * @param callback Callback will be triggered once it succeeds or failed.
      *                 See {@link TelephonyManager.SetOpportunisticSubscriptionResult}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a897e35..1eb6cc3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10373,7 +10373,7 @@
     @IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
             SET_OPPORTUNISTIC_SUB_SUCCESS,
             SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED,
-            SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER})
+            SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION})
     public @interface SetOpportunisticSubscriptionResult {}
 
     /**
@@ -10387,9 +10387,9 @@
     public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1;
 
     /**
-     * The parameter passed in is invalid.
+     * The subscription is not valid. It must be an active opportunistic subscription.
      */
-    public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2;
+    public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -10609,45 +10609,77 @@
      * <p>Note: the API does not prevent access to the SIM cards for operations that don't require
      * access to the network.
      *
-     * @param isMultisimCarrierRestricted true if usage of multiple SIMs is restricted, false
+     * @param isMultiSimCarrierRestricted true if usage of multiple SIMs is restricted, false
      * otherwise.
      *
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted) {
+    public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                service.setMultisimCarrierRestriction(isMultisimCarrierRestricted);
+                service.setMultiSimCarrierRestriction(isMultiSimCarrierRestricted);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "setMultisimCarrierRestriction RemoteException", e);
+            Log.e(TAG, "setMultiSimCarrierRestriction RemoteException", e);
         }
     }
 
     /**
+     * The usage of multiple SIM cards at the same time to register on the network (e.g. Dual
+     * Standby or Dual Active) is supported.
+     */
+    public static final int MULTISIM_ALLOWED = 0;
+
+    /**
+     * The usage of multiple SIM cards at the same time to register on the network (e.g. Dual
+     * Standby or Dual Active) is not supported by the hardware.
+     */
+    public static final int MULTISIM_NOT_SUPPORTED_BY_HARDWARE = 1;
+
+    /**
+     * The usage of multiple SIM cards at the same time to register on the network (e.g. Dual
+     * Standby or Dual Active) is supported by the hardware, but restricted by the carrier.
+     */
+    public static final int MULTISIM_NOT_SUPPORTED_BY_CARRIER = 2;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"MULTISIM_"},
+            value = {
+                    MULTISIM_ALLOWED,
+                    MULTISIM_NOT_SUPPORTED_BY_HARDWARE,
+                    MULTISIM_NOT_SUPPORTED_BY_CARRIER
+            })
+    public @interface IsMultiSimSupportedResult {}
+
+    /**
      * Returns if the usage of multiple SIM cards at the same time to register on the network
      * (e.g. Dual Standby or Dual Active) is supported by the device and by the carrier.
      *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
-     * @return true if usage of multiple SIMs is supported, false otherwise.
+     * @return {@link #MULTISIM_ALLOWED} if the device supports multiple SIMs.
+     * {@link #MULTISIM_NOT_SUPPORTED_BY_HARDWARE} if the device does not support multiple SIMs.
+     * {@link #MULTISIM_NOT_SUPPORTED_BY_CARRIER} in the device supports multiple SIMs, but the
+     * functionality is restricted by the carrier.
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public boolean isMultisimSupported() {
+    @IsMultiSimSupportedResult
+    public int isMultiSimSupported() {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                return service.isMultisimSupported(getOpPackageName());
+                return service.isMultiSimSupported(getOpPackageName());
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "isMultisimSupported RemoteException", e);
+            Log.e(TAG, "isMultiSimSupported RemoteException", e);
         }
-        return false;
+        return MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
     }
 
     /**
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 875bd78..cde10ea 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -118,9 +118,9 @@
     /**
      * Intent action sent by system apps (such as the Settings app) to the Telephony framework to
      * enable or disable a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID} and
-     * {@link #EXTRA_ENABLE_SUBSCRIPTION}.
+     * {@link #EXTRA_ENABLE_SUBSCRIPTION}, and optionally {@link #EXTRA_FROM_SUBSCRIPTION_ID}.
      *
-     * Requires the caller to be a privileged process with the
+     * <p>Requires the caller to be a privileged process with the
      * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
      * stack.
      *
@@ -143,7 +143,7 @@
      * Intent action sent by system apps (such as the Settings app) to the Telephony framework to
      * delete a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID}.
      *
-     * Requires the caller to be a privileged process with the
+     * <p>Requires the caller to be a privileged process with the
      * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
      * stack.
      *
@@ -167,7 +167,7 @@
      * rename a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID} and
      * {@link #EXTRA_SUBSCRIPTION_NICKNAME}.
      *
-     * Requires the caller to be a privileged process with the
+     * <p>Requires the caller to be a privileged process with the
      * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
      * stack.
      *
@@ -318,6 +318,22 @@
             "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME";
 
     /**
+     * Key for an extra set on {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED} providing the ID of
+     * the subscription we're toggling from. This extra is optional and is only used for UI
+     * purposes by the underlying eUICC service (i.e. the LPA app), such as displaying a dialog
+     * titled "Switch X with Y". If set, the provided subscription will be used as the "from"
+     * subscription in UI (the "X" in the dialog example). Otherwise, the currently active
+     * subscription that will be disabled is the "from" subscription.
+     *
+     * <p>Expected type of the extra data: int
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_FROM_SUBSCRIPTION_ID =
+            "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID";
+
+    /**
      * Optional meta-data attribute for a carrier app providing an icon to use to represent the
      * carrier. If not provided, the app's launcher icon will be used as a fallback.
      */
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index 02eddf6..8c686f7 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -31,7 +31,7 @@
  * @hide
  */
 @SystemApi
-public class ImsException extends Exception {
+public final class ImsException extends Exception {
 
     /**
      * The operation has failed due to an unknown or unspecified error.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c2c31cc..10cc99e 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1919,15 +1919,18 @@
      * Indicate if the enablement of multi SIM functionality is restricted.
      * @hide
      */
-    void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted);
+    void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted);
 
     /**
      * Returns if the usage of multiple SIM cards at the same time is supported.
      *
      * @param callingPackage The package making the call.
-     * @return true if multisim is supported, false otherwise.
+     * @return {@link #MULTISIM_ALLOWED} if the device supports multiple SIMs.
+     * {@link #MULTISIM_NOT_SUPPORTED_BY_HARDWARE} if the device does not support multiple SIMs.
+     * {@link #MULTISIM_NOT_SUPPORTED_BY_CARRIER} in the device supports multiple SIMs, but the
+     * functionality is restricted by the carrier.
      */
-    boolean isMultisimSupported(String callingPackage);
+    int isMultiSimSupported(String callingPackage);
 
     /**
      * Switch configs to enable multi-sim or switch back to single-sim
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
index 8a925b9..ebe5418 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
@@ -63,6 +63,13 @@
     }
 
     /**
+     * Waits forever for the next rollback broadcast.
+     */
+    Intent take() throws InterruptedException {
+        return mRollbackBroadcasts.take();
+    }
+
+    /**
      * Unregisters this broadcast receiver.
      */
     void unregister() {
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 48bc9e8..834743d 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -27,7 +27,6 @@
 import static org.junit.Assert.fail;
 
 import android.Manifest;
-import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -40,14 +39,11 @@
 
 import androidx.test.InstrumentationRegistry;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 import java.util.Collections;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -87,6 +83,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
                     Manifest.permission.MANAGE_ROLLBACKS);
 
             // Register a broadcast receiver for notification when the
@@ -175,7 +172,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
 
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
@@ -233,7 +230,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
 
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
@@ -290,7 +287,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
 
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
@@ -343,7 +340,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
                     Manifest.permission.WRITE_DEVICE_CONFIG);
 
             DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
@@ -403,7 +400,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
                     Manifest.permission.WRITE_DEVICE_CONFIG,
                     Manifest.permission.SET_TIME);
 
@@ -475,7 +472,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
 
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
             RollbackTestUtils.uninstall(TEST_APP_A);
@@ -512,7 +509,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
 
             RollbackTestUtils.uninstall(TEST_APP_A);
             RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
@@ -533,14 +530,13 @@
     /**
      * Test rollback of apks involving splits.
      */
-    @Ignore("b/127520966 build issues with splits need to be sorted out")
     @Test
     public void testRollbackWithSplits() throws Exception {
         try {
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
 
             RollbackTestUtils.uninstall(TEST_APP_A);
             RollbackTestUtils.installSplit(false,
@@ -598,7 +594,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
             // Prep installation of the test apps.
@@ -693,6 +689,75 @@
     }
 
     /**
+     * Test that you cannot enable rollback for a package without the
+     * MANAGE_ROLLBACKS permission.
+     */
+    @Test
+    public void testEnableRollbackPermission() throws Exception {
+        try {
+            RollbackTestUtils.adoptShellPermissionIdentity(
+                    Manifest.permission.INSTALL_PACKAGES,
+                    Manifest.permission.DELETE_PACKAGES);
+
+            RollbackTestUtils.uninstall(TEST_APP_A);
+            RollbackTestUtils.install("RollbackTestAppAv1.apk", /* enableRollback */ false);
+            assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+            RollbackTestUtils.install("RollbackTestAppAv2.apk", /* enableRollback */ true);
+
+            // We expect v2 of the app was installed, but rollback has not
+            // been enabled.
+            assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+            // TODO: See if there is a way to remove this race condition
+            // between when the app is installed and when the rollback
+            // would be made available.
+            Thread.sleep(1000);
+
+            RollbackTestUtils.adoptShellPermissionIdentity(
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
+            RollbackManager rm = RollbackTestUtils.getRollbackManager();
+            assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A));
+        } finally {
+            RollbackTestUtils.dropShellPermissionIdentity();
+        }
+    }
+
+    /**
+     * Test that you cannot enable rollback for a non-module package when
+     * holding the MANAGE_ROLLBACKS permission.
+     */
+    @Test
+    public void testNonModuleEnableRollback() throws Exception {
+        try {
+            RollbackTestUtils.adoptShellPermissionIdentity(
+                    Manifest.permission.INSTALL_PACKAGES,
+                    Manifest.permission.DELETE_PACKAGES,
+                    Manifest.permission.MANAGE_ROLLBACKS);
+
+            RollbackTestUtils.uninstall(TEST_APP_A);
+            RollbackTestUtils.install("RollbackTestAppAv1.apk", /* enableRollback */ false);
+            assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+            RollbackTestUtils.install("RollbackTestAppAv2.apk", /* enableRollback */ true);
+
+            // We expect v2 of the app was installed, but rollback has not
+            // been enabled because the test app is not a module.
+            assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+            // TODO: See if there is a way to remove this race condition
+            // between when the app is installed and when the rollback
+            // would be made available.
+            Thread.sleep(1000);
+
+            RollbackManager rm = RollbackTestUtils.getRollbackManager();
+            assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A));
+        } finally {
+            RollbackTestUtils.dropShellPermissionIdentity();
+        }
+    }
+
+    /**
      * Test rollback of multi-package installs is implemented.
      */
     @Test
@@ -701,7 +766,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
             // Prep installation of the test apps.
@@ -761,6 +826,7 @@
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
                     Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
                     Manifest.permission.KILL_BACKGROUND_PROCESSES,
                     Manifest.permission.RESTART_PACKAGES);
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
@@ -790,34 +856,14 @@
                     rm.getAvailableRollbacks(), TEST_APP_B);
             assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB);
 
-            BlockingQueue<Integer> crashQueue = new SynchronousQueue<>();
+            // Register rollback committed receiver
+            RollbackBroadcastReceiver rollbackReceiver = new RollbackBroadcastReceiver();
 
-            IntentFilter crashCountFilter = new IntentFilter();
-            crashCountFilter.addAction("com.android.tests.rollback.CRASH");
-            crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT);
+            // Crash TEST_APP_A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback
+            crashCountReceiver = RollbackTestUtils.sendCrashBroadcast(context, TEST_APP_A, 5);
 
-            crashCountReceiver = new BroadcastReceiver() {
-                    @Override
-                    public void onReceive(Context context, Intent intent) {
-                        try {
-                            // Sleep long enough for packagewatchdog to be notified of crash
-                            Thread.sleep(1000);
-                            // Kill app and close AppErrorDialog
-                            ActivityManager am = context.getSystemService(ActivityManager.class);
-                            am.killBackgroundProcesses(TEST_APP_A);
-                            // Allow another package launch
-                            crashQueue.put(intent.getIntExtra("count", 0));
-                        } catch (InterruptedException e) {
-                            fail("Failed to communicate with test app");
-                        }
-                    }
-                };
-            context.registerReceiver(crashCountReceiver, crashCountFilter);
-
-            // Start apps PackageWatchdog#TRIGGER_FAILURE_COUNT times so TEST_APP_A crashes
-            do {
-                RollbackTestUtils.launchPackage(TEST_APP_A);
-            } while(crashQueue.take() < 5);
+            // Verify we received a broadcast for the rollback.
+            rollbackReceiver.take();
 
             // TEST_APP_A is automatically rolled back by the RollbackPackageHealthObserver
             assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index 9aed074..81629aa 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
+import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -47,6 +48,7 @@
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.SynchronousQueue;
 
 /**
  * Utilities to facilitate testing rollbacks.
@@ -187,7 +189,7 @@
     }
 
     /** Launches {@code packageName} with {@link Intent#ACTION_MAIN}. */
-    static void launchPackage(String packageName)
+    private static void launchPackage(String packageName)
             throws InterruptedException, IOException {
         Context context = InstrumentationRegistry.getContext();
         Intent intent = new Intent(Intent.ACTION_MAIN);
@@ -488,4 +490,39 @@
         }
         return null;
     }
+
+    /**
+     * Send broadcast to crash {@code packageName} {@code count} times. If {@code count} is at least
+     * {@link PackageWatchdog#TRIGGER_FAILURE_COUNT}, watchdog crash detection will be triggered.
+     */
+    static BroadcastReceiver sendCrashBroadcast(Context context, String packageName, int count)
+            throws InterruptedException, IOException {
+        BlockingQueue<Integer> crashQueue = new SynchronousQueue<>();
+        IntentFilter crashCountFilter = new IntentFilter();
+        crashCountFilter.addAction("com.android.tests.rollback.CRASH");
+        crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT);
+
+        BroadcastReceiver crashCountReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    try {
+                        // Sleep long enough for packagewatchdog to be notified of crash
+                        Thread.sleep(1000);
+                        // Kill app and close AppErrorDialog
+                        ActivityManager am = context.getSystemService(ActivityManager.class);
+                        am.killBackgroundProcesses(packageName);
+                        // Allow another package launch
+                        crashQueue.put(intent.getIntExtra("count", 0));
+                    } catch (InterruptedException e) {
+                        fail("Failed to communicate with test app");
+                    }
+                }
+            };
+        context.registerReceiver(crashCountReceiver, crashCountFilter);
+
+        do {
+            launchPackage(packageName);
+        } while(crashQueue.take() < count);
+        return crashCountReceiver;
+    }
 }
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 047451b..7e711c2 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -63,7 +63,7 @@
         RollbackTestUtils.adoptShellPermissionIdentity(
                 Manifest.permission.INSTALL_PACKAGES,
                 Manifest.permission.DELETE_PACKAGES,
-                Manifest.permission.MANAGE_ROLLBACKS);
+                Manifest.permission.TEST_MANAGE_ROLLBACKS);
     }
 
     /**
diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
index 1f2dd27..372ffcd 100644
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
@@ -21,12 +21,9 @@
 import static org.junit.Assert.fail;
 
 import android.net.SocketKeepalive.InvalidPacketException;
-import android.net.TcpKeepalivePacketData.TcpSocketInfo;
 
 import com.android.internal.util.TestUtils;
 
-import libcore.net.InetAddressUtils;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -37,14 +34,14 @@
 
 @RunWith(JUnit4.class)
 public final class TcpKeepalivePacketDataTest {
+    private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1};
+    private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5};
 
     @Before
     public void setUp() {}
 
     @Test
-    public void testV4TcpKeepalivePacket() {
-        final InetAddress srcAddr = InetAddressUtils.parseNumericAddress("192.168.0.1");
-        final InetAddress dstAddr = InetAddressUtils.parseNumericAddress("192.168.0.10");
+    public void testV4TcpKeepalivePacket() throws Exception {
         final int srcPort = 1234;
         final int dstPort = 4321;
         final int seq = 0x11111111;
@@ -52,20 +49,28 @@
         final int wnd = 8000;
         final int wndScale = 2;
         TcpKeepalivePacketData resultData = null;
-        TcpSocketInfo testInfo = new TcpSocketInfo(
-                srcAddr, srcPort, dstAddr, dstPort, seq, ack, wnd, wndScale);
+        final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
+        testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+        testInfo.srcPort = srcPort;
+        testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+        testInfo.dstPort = dstPort;
+        testInfo.seq = seq;
+        testInfo.ack = ack;
+        testInfo.rcvWnd = wnd;
+        testInfo.rcvWndScale = wndScale;
         try {
             resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
         } catch (InvalidPacketException e) {
             fail("InvalidPacketException: " + e);
         }
 
-        assertEquals(testInfo.srcAddress, resultData.srcAddress);
-        assertEquals(testInfo.dstAddress, resultData.dstAddress);
+        assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.srcAddress);
+        assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.dstAddress);
         assertEquals(testInfo.srcPort, resultData.srcPort);
         assertEquals(testInfo.dstPort, resultData.dstPort);
         assertEquals(testInfo.seq, resultData.tcpSeq);
         assertEquals(testInfo.ack, resultData.tcpAck);
+        assertEquals(testInfo.rcvWnd, resultData.tcpWnd);
         assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale);
 
         TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR);
@@ -78,11 +83,11 @@
         byte[] ip = new byte[4];
         buf = ByteBuffer.wrap(packet, 12, 4);
         buf.get(ip);
-        assertArrayEquals(ip, srcAddr.getAddress());
+        assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR);
         // Destination IP address.
         buf = ByteBuffer.wrap(packet, 16, 4);
         buf.get(ip);
-        assertArrayEquals(ip, dstAddr.getAddress());
+        assertArrayEquals(ip, IPV4_KEEPALIVE_DST_ADDR);
 
         buf = ByteBuffer.wrap(packet, 20, 12);
         // Source port.
@@ -102,25 +107,32 @@
 
     @Test
     public void testParcel() throws Exception {
-        final InetAddress srcAddr = InetAddresses.parseNumericAddress("192.168.0.1");
-        final InetAddress dstAddr = InetAddresses.parseNumericAddress("192.168.0.10");
         final int srcPort = 1234;
         final int dstPort = 4321;
         final int sequence = 0x11111111;
         final int ack = 0x22222222;
         final int wnd = 48_000;
         final int wndScale = 2;
+        final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
+        testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+        testInfo.srcPort = srcPort;
+        testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+        testInfo.dstPort = dstPort;
+        testInfo.seq = sequence;
+        testInfo.ack = ack;
+        testInfo.rcvWnd = wnd;
+        testInfo.rcvWndScale = wndScale;
         TcpKeepalivePacketData testData = null;
         TcpKeepalivePacketDataParcelable resultData = null;
-        TcpSocketInfo testInfo = new TcpSocketInfo(
-                srcAddr, srcPort, dstAddr, dstPort, sequence, ack, wnd, wndScale);
         testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
         resultData = testData.toStableParcelable();
-        assertArrayEquals(resultData.srcAddress, srcAddr.getAddress());
-        assertArrayEquals(resultData.dstAddress, dstAddr.getAddress());
+        assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR);
+        assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR);
         assertEquals(resultData.srcPort, srcPort);
         assertEquals(resultData.dstPort, dstPort);
         assertEquals(resultData.seq, sequence);
         assertEquals(resultData.ack, ack);
+        assertEquals(resultData.rcvWnd, wnd);
+        assertEquals(resultData.rcvWndScale, wndScale);
     }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 3263ef9..9dfe436 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -495,7 +495,7 @@
             try {
                 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected();
                 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
-                doAnswer(validateAnswer).when(mNetworkMonitor).notifyAcceptPartialConnectivity();
+                doAnswer(validateAnswer).when(mNetworkMonitor).setAcceptPartialConnectivity();
             } catch (RemoteException e) {
                 fail(e.getMessage());
             }
@@ -2550,7 +2550,7 @@
         verifyActiveNetwork(TRANSPORT_CELLULAR);
     }
 
-    // TODO: deflake and re-enable
+    // TODO(b/128426024): deflake and re-enable
     // @Test
     public void testPartialConnectivity() {
         // Register network callback.
@@ -2585,7 +2585,7 @@
         waitForIdle();
         try {
             verify(mWiFiNetworkAgent.mNetworkMonitor,
-                    timeout(TIMEOUT_MS).times(1)).notifyAcceptPartialConnectivity();
+                    timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity();
         } catch (RemoteException e) {
             fail(e.getMessage());
         }
@@ -2641,7 +2641,7 @@
         waitForIdle();
         try {
             verify(mWiFiNetworkAgent.mNetworkMonitor,
-                    timeout(TIMEOUT_MS).times(1)).notifyAcceptPartialConnectivity();
+                    timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity();
         } catch (RemoteException e) {
             fail(e.getMessage());
         }
diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
index 6fb3225..968b307 100644
--- a/tests/net/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
@@ -23,11 +24,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.net.INetd;
+import android.net.INetdUnsolicitedEventListener;
 import android.net.LinkAddress;
-import android.net.LocalServerSocket;
-import android.net.LocalSocket;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.IBinder;
@@ -43,12 +44,11 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.io.IOException;
-import java.io.OutputStream;
-
 /**
  * Tests for {@link NetworkManagementService}.
  */
@@ -56,16 +56,16 @@
 @SmallTest
 public class NetworkManagementServiceTest {
 
-    private static final String SOCKET_NAME = "__test__NetworkManagementServiceTest";
     private NetworkManagementService mNMService;
-    private LocalServerSocket mServerSocket;
-    private LocalSocket mSocket;
-    private OutputStream mOutputStream;
 
     @Mock private Context mContext;
     @Mock private IBatteryStats.Stub mBatteryStatsService;
     @Mock private INetd.Stub mNetdService;
 
+    @NonNull
+    @Captor
+    private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor;
+
     private final SystemServices mServices = new SystemServices() {
         @Override
         public IBinder getService(String name) {
@@ -88,32 +88,15 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-
-        // Set up a sheltered test environment.
-        mServerSocket = new LocalServerSocket(SOCKET_NAME);
-
+        doNothing().when(mNetdService)
+                .registerUnsolicitedEventListener(mUnsolListenerCaptor.capture());
         // Start the service and wait until it connects to our socket.
-        mNMService = NetworkManagementService.create(mContext, SOCKET_NAME, mServices);
-        mSocket = mServerSocket.accept();
-        mOutputStream = mSocket.getOutputStream();
+        mNMService = NetworkManagementService.create(mContext, mServices);
     }
 
     @After
     public void tearDown() throws Exception {
         mNMService.shutdown();
-        // Once NetworkManagementService#shutdown() actually does something and shutdowns
-        // the underlying NativeDaemonConnector, the block below should be uncommented.
-        // if (mOutputStream != null) mOutputStream.close();
-        // if (mSocket != null) mSocket.close();
-        // if (mServerSocket != null) mServerSocket.close();
-    }
-
-    /**
-     * Sends a message on the netd socket and gives the events some time to make it back.
-     */
-    private void sendMessage(String message) throws IOException {
-        // Strings are null-terminated, so add "\0" at the end.
-        mOutputStream.write((message + "\0").getBytes());
     }
 
     private static <T> T expectSoon(T mock) {
@@ -131,125 +114,78 @@
 
         // Forget everything that happened to the mock so far, so we can explicitly verify
         // everything that happens and does not happen to it from now on.
-        reset(observer);
 
-        // Now send NetworkManagementService messages and ensure that the observer methods are
-        // called. After every valid message we expect a callback soon after; to ensure that
+        INetdUnsolicitedEventListener unsolListener = mUnsolListenerCaptor.getValue();
+        reset(observer);
+        // Now call unsolListener methods and ensure that the observer methods are
+        // called. After every method we expect a callback soon after; to ensure that
         // invalid messages don't cause any callbacks, we call verifyNoMoreInteractions at the end.
 
         /**
          * Interface changes.
          */
-        sendMessage("600 Iface added rmnet12");
+        unsolListener.onInterfaceAdded("rmnet12");
         expectSoon(observer).interfaceAdded("rmnet12");
 
-        sendMessage("600 Iface removed eth1");
+        unsolListener.onInterfaceRemoved("eth1");
         expectSoon(observer).interfaceRemoved("eth1");
 
-        sendMessage("607 Iface removed eth1");
-        // Invalid code.
-
-        sendMessage("600 Iface borked lo down");
-        // Invalid event.
-
-        sendMessage("600 Iface changed clat4 up again");
-        // Extra tokens.
-
-        sendMessage("600 Iface changed clat4 up");
+        unsolListener.onInterfaceChanged("clat4", true);
         expectSoon(observer).interfaceStatusChanged("clat4", true);
 
-        sendMessage("600 Iface linkstate rmnet0 down");
+        unsolListener.onInterfaceLinkStateChanged("rmnet0", false);
         expectSoon(observer).interfaceLinkStateChanged("rmnet0", false);
 
-        sendMessage("600 IFACE linkstate clat4 up");
-        // Invalid group.
-
         /**
          * Bandwidth control events.
          */
-        sendMessage("601 limit alert data rmnet_usb0");
+        unsolListener.onQuotaLimitReached("data", "rmnet_usb0");
         expectSoon(observer).limitReached("data", "rmnet_usb0");
 
-        sendMessage("601 invalid alert data rmnet0");
-        // Invalid group.
-
-        sendMessage("601 limit increased data rmnet0");
-        // Invalid event.
-
-
         /**
          * Interface class activity.
          */
-
-        sendMessage("613 IfaceClass active 1 1234 10012");
+        unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, 0);
         expectSoon(observer).interfaceClassDataActivityChanged("1", true, 1234);
 
-        sendMessage("613 IfaceClass idle 9 5678");
+        unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, 0);
         expectSoon(observer).interfaceClassDataActivityChanged("9", false, 5678);
 
-        sendMessage("613 IfaceClass reallyactive 9 4321");
+        unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, 0);
         expectSoon(observer).interfaceClassDataActivityChanged("9", false, 4321);
 
-        sendMessage("613 InterfaceClass reallyactive 1");
-        // Invalid group.
-
-
         /**
          * IP address changes.
          */
-        sendMessage("614 Address updated fe80::1/64 wlan0 128 253");
+        unsolListener.onInterfaceAddressUpdated("fe80::1/64", "wlan0", 128, 253);
         expectSoon(observer).addressUpdated("wlan0", new LinkAddress("fe80::1/64", 128, 253));
 
-        // There is no "added", so we take this as "removed".
-        sendMessage("614 Address added fe80::1/64 wlan0 128 253");
+        unsolListener.onInterfaceAddressRemoved("fe80::1/64", "wlan0", 128, 253);
         expectSoon(observer).addressRemoved("wlan0", new LinkAddress("fe80::1/64", 128, 253));
 
-        sendMessage("614 Address removed 2001:db8::1/64 wlan0 1 0");
+        unsolListener.onInterfaceAddressRemoved("2001:db8::1/64", "wlan0", 1, 0);
         expectSoon(observer).addressRemoved("wlan0", new LinkAddress("2001:db8::1/64", 1, 0));
 
-        sendMessage("614 Address removed 2001:db8::1/64 wlan0 1");
-        // Not enough arguments.
-
-        sendMessage("666 Address removed 2001:db8::1/64 wlan0 1 0");
-        // Invalid code.
-
-
         /**
          * DNS information broadcasts.
          */
-        sendMessage("615 DnsInfo servers rmnet_usb0 3600 2001:db8::1");
+        unsolListener.onInterfaceDnsServerInfo("rmnet_usb0", 3600, new String[]{"2001:db8::1"});
         expectSoon(observer).interfaceDnsServerInfo("rmnet_usb0", 3600,
                 new String[]{"2001:db8::1"});
 
-        sendMessage("615 DnsInfo servers wlan0 14400 2001:db8::1,2001:db8::2");
+        unsolListener.onInterfaceDnsServerInfo("wlan0", 14400,
+                new String[]{"2001:db8::1", "2001:db8::2"});
         expectSoon(observer).interfaceDnsServerInfo("wlan0", 14400,
                 new String[]{"2001:db8::1", "2001:db8::2"});
 
         // We don't check for negative lifetimes, only for parse errors.
-        sendMessage("615 DnsInfo servers wlan0 -3600 ::1");
+        unsolListener.onInterfaceDnsServerInfo("wlan0", -3600, new String[]{"::1"});
         expectSoon(observer).interfaceDnsServerInfo("wlan0", -3600,
                 new String[]{"::1"});
 
-        sendMessage("615 DnsInfo servers wlan0 SIXHUNDRED ::1");
-        // Non-numeric lifetime.
-
-        sendMessage("615 DnsInfo servers wlan0 2001:db8::1");
-        // Missing lifetime.
-
-        sendMessage("615 DnsInfo servers wlan0 3600");
-        // No servers.
-
-        sendMessage("615 DnsInfo servers 3600 wlan0 2001:db8::1,2001:db8::2");
-        // Non-numeric lifetime.
-
-        sendMessage("615 DnsInfo wlan0 7200 2001:db8::1,2001:db8::2");
-        // Invalid tokens.
-
-        sendMessage("666 DnsInfo servers wlan0 5400 2001:db8::1");
-        // Invalid code.
-
         // No syntax checking on the addresses.
-        sendMessage("615 DnsInfo servers wlan0 600 ,::,,foo,::1,");
+        unsolListener.onInterfaceDnsServerInfo("wlan0", 600,
+                new String[]{"", "::", "", "foo", "::1"});
         expectSoon(observer).interfaceDnsServerInfo("wlan0", 600,
                 new String[]{"", "::", "", "foo", "::1"});
 
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 8bef221..aca2be1 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -198,3 +198,22 @@
     static_libs: ["libaapt2"],
     defaults: ["aapt2_defaults"],
 }
+
+// ==========================================================
+// Dist the protos
+// ==========================================================
+genrule {
+    name: "aapt2-protos",
+    tools: [":soong_zip"],
+    srcs: [
+        "Configuration.proto",
+        "Resources.proto",
+    ],
+    out: ["aapt2-protos.zip"],
+    cmd: "mkdir $(genDir)/protos && " +
+        "cp $(in) $(genDir)/protos && " +
+        "$(location :soong_zip) -o $(out) -C $(genDir)/protos -D $(genDir)/protos",
+    dist: {
+        targets: ["sdk_repo"],
+    },
+}
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index e937517..a24e0d2f 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -58,7 +58,7 @@
       // valid. This is because un-mangled references are mangled, then looked up at resolution
       // time. Also, when linking, we convert references with no package name to use the compilation
       // package name.
-      error |= !DoMerge(src, table, package.get(), false /*mangle*/, overlay, allow_new);
+      error |= !DoMerge(src, package.get(), false /*mangle*/, overlay, allow_new);
     }
   }
   return !error;
@@ -78,7 +78,7 @@
 
     bool mangle = package_name != context_->GetCompilationPackage();
     merged_packages_.insert(package->name);
-    error |= !DoMerge(src, table, package.get(), mangle, false /*overlay*/, true /*allow_new*/);
+    error |= !DoMerge(src, package.get(), mangle, false /*overlay*/, true /*allow_new*/);
   }
   return !error;
 }
@@ -213,9 +213,8 @@
   return collision_result;
 }
 
-bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table,
-                          ResourceTablePackage* src_package, bool mangle_package, bool overlay,
-                          bool allow_new_resources) {
+bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package, bool mangle_package,
+                          bool overlay, bool allow_new_resources) {
   bool error = false;
 
   for (auto& src_type : src_package->types) {
@@ -337,8 +336,7 @@
       ->FindOrCreateValue(file_desc.config, {})
       ->value = std::move(file_ref);
 
-  return DoMerge(file->GetSource(), &table, pkg, false /*mangle*/, overlay /*overlay*/,
-                 true /*allow_new*/);
+  return DoMerge(file->GetSource(), pkg, false /*mangle*/, overlay /*overlay*/, true /*allow_new*/);
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index 24c5e13..51305cf 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -85,8 +85,8 @@
 
   bool MergeImpl(const Source& src, ResourceTable* src_table, bool overlay, bool allow_new);
 
-  bool DoMerge(const Source& src, ResourceTable* src_table, ResourceTablePackage* src_package,
-               bool mangle_package, bool overlay, bool allow_new_resources);
+  bool DoMerge(const Source& src, ResourceTablePackage* src_package, bool mangle_package,
+               bool overlay, bool allow_new_resources);
 
   std::unique_ptr<FileReference> CloneAndMangleFile(const std::string& package,
                                                     const FileReference& value);
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
index 147f054..04710e4 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
@@ -39,7 +39,6 @@
 public final class InspectableClassModel {
     private final @NonNull ClassName mClassName;
     private final @NonNull Map<String, Property> mPropertyMap;
-    private @NonNull Optional<String> mNodeName = Optional.empty();
 
     /**
      * @param className The name of the modeled class
@@ -54,15 +53,6 @@
         return mClassName;
     }
 
-    @NonNull
-    public Optional<String> getNodeName() {
-        return mNodeName;
-    }
-
-    public void setNodeName(@NonNull Optional<String> nodeName) {
-        mNodeName = nodeName;
-    }
-
     /**
      * Add a property to the model, replacing an existing property of the same name.
      *
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java
deleted file mode 100644
index 64a60fb..0000000
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 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.processor.view.inspector;
-
-import androidx.annotation.NonNull;
-
-import java.util.Optional;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-
-/**
- * Process {@code @InspectableNodeName} annotations.
- *
- * @see android.view.inspector.InspectableNodeName
- */
-public final class InspectableNodeNameProcessor implements ModelProcessor {
-    private final @NonNull String mQualifiedName;
-    private final @NonNull ProcessingEnvironment mProcessingEnv;
-    private final @NonNull AnnotationUtils mAnnotationUtils;
-
-    /**
-     * @param annotationQualifiedName The qualified name of the annotation to process
-     * @param processingEnv The processing environment from the parent processor
-     */
-    public InspectableNodeNameProcessor(
-            @NonNull String annotationQualifiedName,
-            @NonNull ProcessingEnvironment processingEnv) {
-        mQualifiedName = annotationQualifiedName;
-        mProcessingEnv = processingEnv;
-        mAnnotationUtils = new AnnotationUtils(processingEnv);
-    }
-
-    /**
-     * Set the node name on the model if one is supplied.
-     *
-     * If the model already has a different node name, the node name will not be updated, and
-     * the processor will print an error the the messager.
-     *
-     * @param element The annotated element to operate on
-     * @param model The model this element should be merged into
-     */
-    @Override
-    public void process(@NonNull Element element, @NonNull InspectableClassModel model) {
-        try {
-            final AnnotationMirror mirror =
-                    mAnnotationUtils.exactlyOneMirror(mQualifiedName, element);
-            final Optional<String> nodeName = mAnnotationUtils
-                    .typedValueByName("value", String.class, element, mirror);
-
-            if (!model.getNodeName().isPresent() || model.getNodeName().equals(nodeName)) {
-                model.setNodeName(nodeName);
-            } else {
-                final String message = String.format(
-                        "Node name was already set to \"%s\", refusing to change it to \"%s\".",
-                        model.getNodeName().get(),
-                        nodeName);
-                throw new ProcessingException(message, element, mirror);
-            }
-        } catch (ProcessingException processingException) {
-            processingException.print(mProcessingEnv.getMessager());
-        }
-    }
-}
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java
index 7f5f9ca..2bd867c 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java
@@ -46,7 +46,7 @@
  *
  * @see android.view.inspector.InspectableProperty
  */
-public final class InspectablePropertyProcessor implements ModelProcessor {
+public final class InspectablePropertyProcessor {
     private final @NonNull String mQualifiedName;
     private final @NonNull ProcessingEnvironment mProcessingEnv;
     private final @NonNull AnnotationUtils mAnnotationUtils;
@@ -139,7 +139,6 @@
         mAnnotationUtils = new AnnotationUtils(processingEnv);
     }
 
-    @Override
     public void process(@NonNull Element element, @NonNull InspectableClassModel model) {
         try {
             final AnnotationMirror annotation =
@@ -608,7 +607,7 @@
      * Build a model of an {@code int} enumeration mapping from annotation values.
      *
      * This method only handles the one-to-one mapping of mirrors of
-     * {@link android.view.inspector.InspectableProperty.EnumMap} annotations into
+     * {@link android.view.inspector.InspectableProperty.EnumEntry} annotations into
      * {@link IntEnumEntry} objects. Further validation should be handled elsewhere
      *
      * @see android.view.inspector.InspectableProperty#enumMapping()
@@ -656,7 +655,7 @@
      * Build a model of an {@code int} flag mapping from annotation values.
      *
      * This method only handles the one-to-one mapping of mirrors of
-     * {@link android.view.inspector.InspectableProperty.FlagMap} annotations into
+     * {@link android.view.inspector.InspectableProperty.FlagEntry} annotations into
      * {@link IntFlagEntry} objects. Further validation should be handled elsewhere
      *
      * @see android.view.inspector.IntFlagMapping
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
index c428a46..6e38c24 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
@@ -163,8 +163,6 @@
                 .addMethod(generateMapProperties(properties, fields))
                 .addMethod(generateReadProperties(properties, fields, model.getClassName()));
 
-        model.getNodeName().ifPresent(name -> builder.addMethod(generateGetNodeName(name)));
-
         return builder.build();
     }
 
@@ -451,31 +449,6 @@
     }
 
     /**
-     * Generate an implementation of
-     * {@link android.view.inspector.InspectionCompanion#getNodeName()}.
-     *
-     * Example:
-     * <pre>
-     *     @Override
-     *     public String getNodeName() {
-     *         return "nodeName";
-     *     }
-     * </pre>
-     *
-     * @param nodeName The name of this node
-     * @return A method definition that returns the node name
-     */
-    @NonNull
-    private MethodSpec generateGetNodeName(@NonNull String nodeName) {
-        return MethodSpec.methodBuilder("getNodeName")
-                .addAnnotation(Override.class)
-                .addModifiers(Modifier.PUBLIC)
-                .returns(String.class)
-                .addStatement("return $S", nodeName)
-                .build();
-    }
-
-    /**
      * Generate the final class name for the inspection companion from the model's class name.
      *
      * The generated class is added to the same package as the source class. If the class in the
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java
deleted file mode 100644
index ab38f4c..0000000
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 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.processor.view.inspector;
-
-import androidx.annotation.NonNull;
-
-import javax.lang.model.element.Element;
-
-/**
- * An interface for annotation processors that operate on a single element and a class model.
- */
-public interface ModelProcessor {
-    /**
-     * Process the supplied element, mutating the model as needed.
-     *
-     * @param element The annotated element to operate on
-     * @param model The model this element should be merged into
-     */
-    void process(@NonNull Element element, @NonNull InspectableClassModel model);
-}
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
index d9ed1fb..80d3727 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
@@ -38,25 +38,18 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.util.ElementFilter;
 
-
 /**
  * An annotation processor for the platform inspectable annotations.
  *
- * It mostly delegates to {@link ModelProcessor} and {@link InspectionCompanionGenerator}. This
- * modular architecture allows the core generation code to be reused for comparable annotations
- * outside the platform, such as in AndroidX.
+ * It mostly delegates to {@link InspectablePropertyProcessor} and
+ * {@link InspectionCompanionGenerator}. This modular architecture allows the core generation code
+ * to be reused for comparable annotations outside the platform.
  *
- * @see android.view.inspector.InspectableNodeName
  * @see android.view.inspector.InspectableProperty
  */
-@SupportedAnnotationTypes({
-        PlatformInspectableProcessor.NODE_NAME_QUALIFIED_NAME,
-        PlatformInspectableProcessor.PROPERTY_QUALIFIED_NAME
-})
+@SupportedAnnotationTypes({PlatformInspectableProcessor.ANNOTATION_QUALIFIED_NAME})
 public final class PlatformInspectableProcessor extends AbstractProcessor {
-    static final String NODE_NAME_QUALIFIED_NAME =
-            "android.view.inspector.InspectableNodeName";
-    static final String PROPERTY_QUALIFIED_NAME =
+    static final String ANNOTATION_QUALIFIED_NAME =
             "android.view.inspector.InspectableProperty";
 
     @Override
@@ -71,18 +64,8 @@
         final Map<String, InspectableClassModel> modelMap = new HashMap<>();
 
         for (TypeElement annotation : annotations) {
-            if (annotation.getQualifiedName().contentEquals(NODE_NAME_QUALIFIED_NAME)) {
-                runModelProcessor(
-                        roundEnv.getElementsAnnotatedWith(annotation),
-                        new InspectableNodeNameProcessor(NODE_NAME_QUALIFIED_NAME, processingEnv),
-                        modelMap);
-
-            } else if (annotation.getQualifiedName().contentEquals(PROPERTY_QUALIFIED_NAME)) {
-                runModelProcessor(
-                        roundEnv.getElementsAnnotatedWith(annotation),
-                        new InspectablePropertyProcessor(PROPERTY_QUALIFIED_NAME, processingEnv),
-                        modelMap);
-
+            if (annotation.getQualifiedName().contentEquals(ANNOTATION_QUALIFIED_NAME)) {
+                processProperties(roundEnv.getElementsAnnotatedWith(annotation), modelMap);
             } else {
                 fail("Unexpected annotation type", annotation);
             }
@@ -106,16 +89,17 @@
     }
 
     /**
-     * Run a {@link ModelProcessor} for a set of elements
+     * Runs {@link PlatformInspectableProcessor} on a set of annotated elements.
      *
-     * @param elements Elements to process, should be annotated correctly
-     * @param processor The processor to use
-     * @param modelMap A map of qualified class names to models
+     * @param elements A set of annotated elements to process
+     * @param modelMap A map of qualified class names to class models to update
      */
-    private void runModelProcessor(
+    private void processProperties(
             @NonNull Set<? extends Element> elements,
-            @NonNull ModelProcessor processor,
             @NonNull Map<String, InspectableClassModel> modelMap) {
+        final InspectablePropertyProcessor processor =
+                new InspectablePropertyProcessor(ANNOTATION_QUALIFIED_NAME, processingEnv);
+
         for (Element element : elements) {
             final Optional<TypeElement> classElement = enclosingClassElement(element);
 
diff --git a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
index 3ec620a..c6e6018 100644
--- a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
+++ b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
@@ -36,7 +36,6 @@
 import java.io.IOException;
 import java.net.URL;
 import java.util.Arrays;
-import java.util.Optional;
 
 /**
  * Tests for {@link InspectionCompanionGenerator}
@@ -56,12 +55,6 @@
     }
 
     @Test
-    public void testNodeName() {
-        mModel.setNodeName(Optional.of("NodeName"));
-        assertGeneratedFileEquals("NodeName");
-    }
-
-    @Test
     public void testNestedClass() {
         mModel = new InspectableClassModel(
                 ClassName.get("com.android.node", "Outer", "Inner"));
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt
deleted file mode 100644
index ffa1f0b..0000000
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.android.node;
-
-import android.view.inspector.InspectionCompanion;
-import android.view.inspector.PropertyMapper;
-import android.view.inspector.PropertyReader;
-import java.lang.Override;
-import java.lang.String;
-
-/**
- * Inspection companion for {@link TestNode}.
- *
- * Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
- * on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
- */
-public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
-    /**
-     * Guards against reading properties before mapping them.
-     */
-    private boolean mPropertiesMapped = false;
-
-    @Override
-    public void mapProperties(PropertyMapper propertyMapper) {
-        mPropertiesMapped = true;
-    }
-
-    @Override
-    public void readProperties(TestNode node, PropertyReader propertyReader) {
-        if (!mPropertiesMapped) {
-            throw new InspectionCompanion.UninitializedPropertyMapException();
-        }
-    }
-
-    @Override
-    public String getNodeName() {
-        return "NodeName";
-    }
-}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
index b225116..daea601 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -18,6 +18,7 @@
 
 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.net.NetworkSpecifier;
@@ -302,12 +303,6 @@
     /**
      * A builder class for a Wi-Fi Aware network specifier to set up an Aware connection with a
      * peer.
-     * <p>
-     * Note that all Wi-Fi Aware connection specifier objects must call the
-     * {@link Builder#setDiscoverySession(DiscoverySession)} to specify the context
-     * within which the connection is created, and
-     * {@link Builder#setPeerHandle(PeerHandle)} to specify the peer to which the
-     * connection is created.
      */
     public static final class Builder {
         private DiscoverySession mDiscoverySession;
@@ -318,42 +313,27 @@
         private int mTransportProtocol = -1; // invalid value
 
         /**
-         * Configure the {@link PublishDiscoverySession} or {@link SubscribeDiscoverySession}
-         * discovery session in whose context the connection is created.
-         * <p>
-         * Note: this method must be called for any connection request!
+         * Create a builder for {@link WifiAwareNetworkSpecifier} used in requests to set up a
+         * Wi-Fi Aware connection with a peer.
          *
-         * @param discoverySession A Wi-Fi Aware discovery session.
-         * @return the current {@link Builder} builder, enabling chaining of builder
-         *         methods.
-         */
-        public @NonNull Builder setDiscoverySession(@NonNull DiscoverySession discoverySession) {
-            if (discoverySession == null) {
-                throw new IllegalArgumentException("Non-null discoverySession required");
-            }
-            mDiscoverySession = discoverySession;
-            return this;
-        }
-
-        /**
-         * Configure the {@link PeerHandle} of the peer to which the Wi-Fi Aware connection is
-         * requested. The peer is discovered through Wi-Fi Aware discovery,
-         * <p>
-         * Note: this method must be called for any connection request!
-         *
-         * @param peerHandle The peer's handle obtained through
+         * @param discoverySession A Wi-Fi Aware discovery session in whose context the connection
+         *                         is created.
+         * @param peerHandle The handle of the peer to which the Wi-Fi Aware connection is
+         *                   requested. The peer is discovered through Wi-Fi Aware discovery. The
+         *                   handle can be obtained through
          * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
          *                   or
          *                   {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
-         * @return the current {@link Builder} builder, enabling chaining of builder
-         *         methods.
          */
-        public @NonNull Builder setPeerHandle(@NonNull PeerHandle peerHandle) {
+        public Builder(@NonNull DiscoverySession discoverySession, @NonNull PeerHandle peerHandle) {
+            if (discoverySession == null) {
+                throw new IllegalArgumentException("Non-null discoverySession required");
+            }
             if (peerHandle == null) {
                 throw new IllegalArgumentException("Non-null peerHandle required");
             }
+            mDiscoverySession = discoverySession;
             mPeerHandle = peerHandle;
-            return this;
         }
 
         /**
@@ -407,7 +387,7 @@
          * @return the current {@link Builder} builder, enabling chaining of builder
          *         methods.
          */
-        public @NonNull Builder setPort(int port) {
+        public @NonNull Builder setPort(@IntRange(from = 0, to = 65535) int port) {
             if (port <= 0 || port > 65535) {
                 throw new IllegalArgumentException("The port must be a positive value (0, 65535]");
             }
@@ -432,7 +412,8 @@
          * @return the current {@link Builder} builder, enabling chaining of builder
          *         methods.
          */
-        public @NonNull Builder setTransportProtocol(int transportProtocol) {
+        public @NonNull
+                Builder setTransportProtocol(@IntRange(from = 0, to = 255) int transportProtocol) {
             if (transportProtocol < 0 || transportProtocol > 255) {
                 throw new IllegalArgumentException(
                         "The transport protocol must be in range [0, 255]");
@@ -460,6 +441,9 @@
             if (mDiscoverySession == null) {
                 throw new IllegalStateException("Null discovery session!?");
             }
+            if (mPeerHandle == null) {
+                throw new IllegalStateException("Null peerHandle!?");
+            }
             if (mPskPassphrase != null & mPmk != null) {
                 throw new IllegalStateException(
                         "Can only specify a Passphrase or a PMK - not both!");
@@ -481,10 +465,6 @@
                 }
             }
 
-            if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR && mPeerHandle == null) {
-                throw new IllegalStateException("Null peerHandle!?");
-            }
-
             return new WifiAwareNetworkSpecifier(
                     WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB, role,
                     mDiscoverySession.mClientId, mDiscoverySession.mSessionId, mPeerHandle.peerId,
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 657a338..905540e 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -958,8 +958,8 @@
         WifiAwareNetworkSpecifier ns =
                 (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierOpen(
                         peerHandle);
-        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                publishSession.getValue()).setPeerHandle(peerHandle).build();
+        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(
+                publishSession.getValue(), peerHandle).build();
 
         // validate format
         collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
@@ -979,9 +979,8 @@
         // (4) request an encrypted (PMK) network specifier from the session
         ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPmk(
                 peerHandle, pmk);
-        nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                publishSession.getValue()).setPeerHandle(peerHandle).setPmk(pmk).setPort(
-                port).setTransportProtocol(transportProtocol).build();
+        nsb = new WifiAwareNetworkSpecifier.Builder(publishSession.getValue(), peerHandle).setPmk(
+                pmk).setPort(port).setTransportProtocol(transportProtocol).build();
 
         // validate format
         collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
@@ -1005,9 +1004,9 @@
                 (WifiAwareNetworkSpecifier) publishSession.getValue()
                         .createNetworkSpecifierPassphrase(
                         peerHandle, passphrase);
-        nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                publishSession.getValue()).setPeerHandle(peerHandle).setPskPassphrase(
-                passphrase).setPort(port).setTransportProtocol(transportProtocol).build();
+        nsb = new WifiAwareNetworkSpecifier.Builder(publishSession.getValue(),
+                peerHandle).setPskPassphrase(passphrase).setPort(port).setTransportProtocol(
+                transportProtocol).build();
 
         // validate format
         collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
@@ -1255,16 +1254,15 @@
         // (3) create network specifier
         if (doPmk) {
             if (useBuilder) {
-                new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                        publishSession.getValue()).setPeerHandle(peerHandle).setPmk(pmk).build();
+                new WifiAwareNetworkSpecifier.Builder(publishSession.getValue(), peerHandle).setPmk(
+                        pmk).build();
             } else {
                 publishSession.getValue().createNetworkSpecifierPmk(peerHandle, pmk);
             }
         } else {
             if (useBuilder) {
-                new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                        publishSession.getValue()).setPeerHandle(peerHandle).setPskPassphrase(
-                        passphrase).build();
+                new WifiAwareNetworkSpecifier.Builder(publishSession.getValue(),
+                        peerHandle).setPskPassphrase(passphrase).build();
             } else {
                 publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle, passphrase);
             }
@@ -1353,8 +1351,8 @@
 
         DiscoverySession publishSession = executeSessionStartup(true);
 
-        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                publishSession).setPeerHandle(peerHandle).setPmk(pmk).setPort(port).build();
+        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession,
+                peerHandle).setPmk(pmk).setPort(port).build();
     }
 
     /**
@@ -1368,8 +1366,8 @@
 
         DiscoverySession publishSession = executeSessionStartup(true);
 
-        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                publishSession).setPeerHandle(peerHandle).setPort(port).build();
+        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession,
+                peerHandle).setPort(port).build();
     }
 
     /**
@@ -1383,8 +1381,8 @@
 
         DiscoverySession subscribeSession = executeSessionStartup(false);
 
-        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                subscribeSession).setPeerHandle(peerHandle).setPort(port).build();
+        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(subscribeSession,
+                peerHandle).setPort(port).build();
     }
 
     /**
@@ -1403,27 +1401,23 @@
         DiscoverySession publishSession = executeSessionStartup(true);
 
         try {
-            WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
-                            .setDiscoverySession(publishSession).setPeerHandle(peerHandle)
-                            .setPmk(pmk).setTransportProtocol(tpNegative).build();
+            WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession,
+                    peerHandle).setPmk(pmk).setTransportProtocol(tpNegative).build();
             assertTrue("No exception on negative transport protocol!", false);
         } catch (IllegalArgumentException e) {
             // nop - exception is correct!
         }
         try {
-            WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
-                            .setDiscoverySession(publishSession).setPeerHandle(peerHandle)
-                            .setPmk(pmk).setTransportProtocol(tpTooLarge).build();
+            WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession,
+                    peerHandle).setPmk(pmk).setTransportProtocol(tpTooLarge).build();
             assertTrue("No exception on >255 transport protocol!", false);
         } catch (IllegalArgumentException e) {
             // nop - exception is correct!
         }
-        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
-                        .setDiscoverySession(publishSession).setPeerHandle(peerHandle)
-                        .setPmk(pmk).setTransportProtocol(tpSmallest).build();
-        nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
-                publishSession).setPeerHandle(peerHandle).setPmk(pmk).setTransportProtocol(
-                tpLargest).build();
+        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession,
+                peerHandle).setPmk(pmk).setTransportProtocol(tpSmallest).build();
+        nsb = new WifiAwareNetworkSpecifier.Builder(publishSession, peerHandle).setPmk(
+                pmk).setTransportProtocol(tpLargest).build();
     }
 
     /**
@@ -1437,9 +1431,8 @@
 
         DiscoverySession publishSession = executeSessionStartup(true);
 
-        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
-                        .setDiscoverySession(publishSession).setPeerHandle(peerHandle)
-                        .setTransportProtocol(transportProtocol).build();
+        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession,
+                peerHandle).setTransportProtocol(transportProtocol).build();
     }
 
     /**
@@ -1453,9 +1446,8 @@
 
         DiscoverySession subscribeSession = executeSessionStartup(false);
 
-        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
-                        .setDiscoverySession(subscribeSession).setPeerHandle(peerHandle)
-                        .setTransportProtocol(transportProtocol).build();
+        WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(subscribeSession,
+                peerHandle).setTransportProtocol(transportProtocol).build();
     }
 
     /*