Merge "Persists LocusId for Shortcuts."
diff --git a/Android.bp b/Android.bp
index 05c7dbc..0acc3d6 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",
diff --git a/api/current.txt b/api/current.txt
index 79a909d..34c2c29 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";
@@ -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";
@@ -25699,14 +25700,14 @@
   public static class MediaPlayer2.DrmEventCallback {
     ctor public MediaPlayer2.DrmEventCallback();
     method public void onDrmConfig(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaDrm);
-    method public android.media.MediaPlayer2.DrmPreparationInfo onDrmInfo(android.media.MediaPlayer2, android.media.DataSourceDesc, android.media.MediaPlayer2.DrmInfo);
-    method public byte[] onDrmKeyRequest(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaDrm.KeyRequest);
+    method @Nullable public android.media.MediaPlayer2.DrmPreparationInfo onDrmInfo(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.DrmInfo);
+    method @NonNull public byte[] onDrmKeyRequest(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaDrm.KeyRequest);
     method public void onDrmPrepared(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, int, @Nullable byte[]);
   }
 
   public static final class MediaPlayer2.DrmInfo {
-    method public java.util.Map<java.util.UUID,byte[]> getPssh();
-    method public java.util.List<java.util.UUID> getSupportedSchemes();
+    method @NonNull public java.util.Map<java.util.UUID,byte[]> getPssh();
+    method @NonNull public java.util.List<java.util.UUID> getSupportedSchemes();
   }
 
   public static final class MediaPlayer2.DrmPreparationInfo {
@@ -25714,13 +25715,13 @@
 
   public static final class MediaPlayer2.DrmPreparationInfo.Builder {
     ctor public MediaPlayer2.DrmPreparationInfo.Builder();
-    method public android.media.MediaPlayer2.DrmPreparationInfo build();
-    method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setInitData(@Nullable byte[]);
-    method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeySetId(@Nullable byte[]);
-    method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeyType(int);
-    method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setMimeType(@Nullable String);
-    method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setOptionalParameters(@Nullable java.util.Map<java.lang.String,java.lang.String>);
-    method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setUuid(@NonNull java.util.UUID);
+    method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo build();
+    method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setInitData(@Nullable byte[]);
+    method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeySetId(@Nullable byte[]);
+    method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeyType(int);
+    method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setMimeType(@Nullable String);
+    method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setOptionalParameters(@Nullable java.util.Map<java.lang.String,java.lang.String>);
+    method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setUuid(@NonNull java.util.UUID);
   }
 
   public static class MediaPlayer2.EventCallback {
@@ -25751,7 +25752,7 @@
   }
 
   public static final class MediaPlayer2.NoDrmSchemeException extends android.media.MediaDrmException {
-    ctor public MediaPlayer2.NoDrmSchemeException(String);
+    ctor public MediaPlayer2.NoDrmSchemeException(@Nullable String);
   }
 
   public static class MediaPlayer2.TrackInfo {
@@ -45062,7 +45063,6 @@
     method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean removeSubscriptionsFromGroup(@NonNull int[]);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setMetered(boolean, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunistic(boolean, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String setSubscriptionGroup(@NonNull int[]);
     method public void setSubscriptionOverrideCongested(int, boolean, long);
@@ -45300,7 +45300,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 +50444,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();
@@ -51957,6 +51958,7 @@
     method @NonNull public android.view.WindowInsets consumeStableInsets();
     method @NonNull public android.view.WindowInsets consumeSystemWindowInsets();
     method @Nullable public android.view.DisplayCutout getDisplayCutout();
+    method @NonNull public android.graphics.Insets getMandatorySystemGestureInsets();
     method public int getStableInsetBottom();
     method public int getStableInsetLeft();
     method public int getStableInsetRight();
@@ -51968,6 +51970,7 @@
     method public int getSystemWindowInsetRight();
     method public int getSystemWindowInsetTop();
     method @NonNull public android.graphics.Insets getSystemWindowInsets();
+    method @NonNull public android.graphics.Insets getTappableElementInsets();
     method public boolean hasInsets();
     method public boolean hasStableInsets();
     method public boolean hasSystemWindowInsets();
@@ -51983,9 +51986,11 @@
     ctor public WindowInsets.Builder(@NonNull android.view.WindowInsets);
     method @NonNull public android.view.WindowInsets build();
     method @NonNull public android.view.WindowInsets.Builder setDisplayCutout(@Nullable android.view.DisplayCutout);
+    method @NonNull public android.view.WindowInsets.Builder setMandatorySystemGestureInsets(@NonNull android.graphics.Insets);
     method @NonNull public android.view.WindowInsets.Builder setStableInsets(@NonNull android.graphics.Insets);
     method @NonNull public android.view.WindowInsets.Builder setSystemGestureInsets(@NonNull android.graphics.Insets);
     method @NonNull public android.view.WindowInsets.Builder setSystemWindowInsets(@NonNull android.graphics.Insets);
+    method @NonNull public android.view.WindowInsets.Builder setTappableElementInsets(@NonNull android.graphics.Insets);
   }
 
   public interface WindowManager extends android.view.ViewManager {
@@ -53030,7 +53035,7 @@
     method public int describeContents();
     method @NonNull public static android.view.contentcapture.ContentCaptureContext forLocusId(@NonNull String);
     method @Nullable public android.os.Bundle getExtras();
-    method @NonNull public android.content.LocusId getLocusId();
+    method @Nullable public android.content.LocusId getLocusId();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureContext> CREATOR;
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 570e1ac..220a79c 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";
@@ -1478,6 +1479,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);
@@ -1836,9 +1838,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
@@ -4281,11 +4283,14 @@
 
 package android.net.apf {
 
-  public class ApfCapabilities {
+  public final class ApfCapabilities implements android.os.Parcelable {
     ctor public ApfCapabilities(int, int, int);
+    method public int describeContents();
     method public static boolean getApfDrop8023Frames(android.content.Context);
     method public static int[] getApfEthTypeBlackList(android.content.Context);
     method public boolean hasDataAccess();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR;
     field public final int apfPacketFormat;
     field public final int apfVersionSupported;
     field public final int maximumApfProgramSize;
@@ -5619,6 +5624,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedProfile(int);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isPrimaryUser();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile();
+    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String);
@@ -5879,6 +5885,8 @@
     field public static final String NAMESPACE_RUNTIME = "runtime";
     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_TEXTCLASSIFIER = "textclassifier";
   }
@@ -5907,16 +5915,6 @@
     method @Nullable public String getString(@NonNull String, @Nullable String);
   }
 
-  public static interface DeviceConfig.Scheduler {
-    field public static final String ENABLE_FAST_METRICS_COLLECTION = "enable_fast_metrics_collection";
-    field public static final String NAMESPACE = "scheduler";
-  }
-
-  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";
@@ -6054,6 +6052,7 @@
     field public static final String ACTION_ACCESSIBILITY_DETAILS_SETTINGS = "android.settings.ACCESSIBILITY_DETAILS_SETTINGS";
     field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
     field public static final String ACTION_LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS = "android.settings.LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS";
+    field public static final String ACTION_MANAGE_DOMAIN_URLS = "android.settings.MANAGE_DOMAIN_URLS";
     field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
     field public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
   }
@@ -6117,6 +6116,7 @@
     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 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
@@ -6427,6 +6427,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
@@ -6445,6 +6446,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 {
diff --git a/api/test-current.txt b/api/test-current.txt
index 7494415..9e8b02a 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";
@@ -720,11 +721,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";
@@ -1306,11 +1307,14 @@
 
 package android.net.apf {
 
-  public class ApfCapabilities {
+  public final class ApfCapabilities implements android.os.Parcelable {
     ctor public ApfCapabilities(int, int, int);
+    method public int describeContents();
     method public static boolean getApfDrop8023Frames(android.content.Context);
     method public static int[] getApfEthTypeBlackList(android.content.Context);
     method public boolean hasDataAccess();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR;
     field public final int apfPacketFormat;
     field public final int apfVersionSupported;
     field public final int maximumApfProgramSize;
@@ -2390,6 +2394,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
@@ -2408,6 +2413,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 {
@@ -3172,19 +3178,19 @@
 
   @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.EnumMap[] enumMapping() default {};
-    method public abstract android.view.inspector.InspectableProperty.FlagMap[] flagMapping() default {};
+    method public abstract android.view.inspector.InspectableProperty.EnumEntry[] enumMapping() default {};
+    method public abstract android.view.inspector.InspectableProperty.FlagEntry[] flagMapping() default {};
     method public abstract boolean hasAttributeId() default true;
     method public abstract String name() default "";
     method public abstract android.view.inspector.InspectableProperty.ValueType valueType() default android.view.inspector.InspectableProperty.ValueType.INFERRED;
   }
 
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface InspectableProperty.EnumMap {
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface InspectableProperty.EnumEntry {
     method public abstract String name();
     method public abstract int value();
   }
 
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface InspectableProperty.FlagMap {
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface InspectableProperty.FlagEntry {
     method public abstract int mask() default 0;
     method public abstract String name();
     method public abstract int target();
@@ -3213,7 +3219,7 @@
   }
 
   public class DatePicker extends android.widget.FrameLayout {
-    method @android.view.inspector.InspectableProperty(name="datePickerMode", enumMapping={@android.view.inspector.InspectableProperty.EnumMap(value=android.widget.DatePicker.MODE_SPINNER, name="spinner"), @android.view.inspector.InspectableProperty.EnumMap(value=android.widget.DatePicker.MODE_CALENDAR, name="calendar")}) public int getMode();
+    method @android.view.inspector.InspectableProperty(name="datePickerMode", enumMapping={@android.view.inspector.InspectableProperty.EnumEntry(value=android.widget.DatePicker.MODE_SPINNER, name="spinner"), @android.view.inspector.InspectableProperty.EnumEntry(value=android.widget.DatePicker.MODE_CALENDAR, name="calendar")}) public int getMode();
     field public static final int MODE_CALENDAR = 2; // 0x2
     field public static final int MODE_SPINNER = 1; // 0x1
   }
@@ -3249,7 +3255,7 @@
     method public android.view.View getAmView();
     method public android.view.View getHourView();
     method public android.view.View getMinuteView();
-    method @android.view.inspector.InspectableProperty(name="timePickerMode", enumMapping={@android.view.inspector.InspectableProperty.EnumMap(name="clock", value=android.widget.TimePicker.MODE_CLOCK), @android.view.inspector.InspectableProperty.EnumMap(name="spinner", value=android.widget.TimePicker.MODE_SPINNER)}) public int getMode();
+    method @android.view.inspector.InspectableProperty(name="timePickerMode", enumMapping={@android.view.inspector.InspectableProperty.EnumEntry(name="clock", value=android.widget.TimePicker.MODE_CLOCK), @android.view.inspector.InspectableProperty.EnumEntry(name="spinner", value=android.widget.TimePicker.MODE_SPINNER)}) public int getMode();
     method public android.view.View getPmView();
     field public static final int MODE_CLOCK = 2; // 0x2
     field public static final int MODE_SPINNER = 1; // 0x1
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..9afdd437 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -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/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/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/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/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 3ecb587..bcd43a2 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -440,7 +440,7 @@
      */
     public boolean isKeyguardSecure() {
         try {
-            return mWM.isKeyguardSecure();
+            return mWM.isKeyguardSecure(mContext.getUserId());
         } catch (RemoteException ex) {
             return false;
         }
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/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 99324ba..2f99879 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.
      */
@@ -6863,9 +6855,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..7873fc0 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -29,15 +29,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;
diff --git a/core/java/android/net/apf/ApfCapabilities.java b/core/java/android/net/apf/ApfCapabilities.java
index e09fa8f..d6023d7 100644
--- a/core/java/android/net/apf/ApfCapabilities.java
+++ b/core/java/android/net/apf/ApfCapabilities.java
@@ -19,17 +19,20 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
 
 import com.android.internal.R;
 
 /**
  * APF program support capabilities.
  *
+ * This class is immutable.
  * @hide
  */
 @SystemApi
 @TestApi
-public class ApfCapabilities {
+public final class ApfCapabilities implements Parcelable {
     /**
      * Version of APF instruction set supported for packet filtering. 0 indicates no support for
      * packet filtering using APF programs.
@@ -53,6 +56,37 @@
         this.apfPacketFormat = apfPacketFormat;
     }
 
+    private ApfCapabilities(Parcel in) {
+        apfVersionSupported = in.readInt();
+        maximumApfProgramSize = in.readInt();
+        apfPacketFormat = in.readInt();
+    }
+
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(apfVersionSupported);
+        dest.writeInt(maximumApfProgramSize);
+        dest.writeInt(apfPacketFormat);
+    }
+
+    public static final Creator<ApfCapabilities> CREATOR = new Creator<ApfCapabilities>() {
+        @Override
+        public ApfCapabilities createFromParcel(Parcel in) {
+            return new ApfCapabilities(in);
+        }
+
+        @Override
+        public ApfCapabilities[] newArray(int size) {
+            return new ApfCapabilities[size];
+        }
+    };
+
     @Override
     public String toString() {
         return String.format("%s{version: %d, maxSize: %d, format: %d}", getClass().getSimpleName(),
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 6432c24..b82e517 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -935,12 +935,16 @@
     }
 
     /**
-     * Returns the value associated with the given key, or null if
-     * no mapping of the desired type exists for the given key or a null
+     * Returns the value associated with the given key, or {@code null} if
+     * no mapping of the desired type exists for the given key or a {@code null}
      * value is explicitly associated with the key.
      *
-     * @param key a String, or null
-     * @return a Parcelable value, or null
+     * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
+     * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
+     * Otherwise, this method might throw an exception or return {@code null}.
+     *
+     * @param key a String, or {@code null}
+     * @return a Parcelable value, or {@code null}
      */
     @Nullable
     public <T extends Parcelable> T getParcelable(@Nullable String key) {
@@ -958,12 +962,16 @@
     }
 
     /**
-     * Returns the value associated with the given key, or null if
+     * Returns the value associated with the given key, or {@code null} if
      * no mapping of the desired type exists for the given key or a null
      * value is explicitly associated with the key.
      *
-     * @param key a String, or null
-     * @return a Parcelable[] value, or null
+     * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
+     * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
+     * Otherwise, this method might throw an exception or return {@code null}.
+     *
+     * @param key a String, or {@code null}
+     * @return a Parcelable[] value, or {@code null}
      */
     @Nullable
     public Parcelable[] getParcelableArray(@Nullable String key) {
@@ -981,12 +989,16 @@
     }
 
     /**
-     * Returns the value associated with the given key, or null if
-     * no mapping of the desired type exists for the given key or a null
+     * Returns the value associated with the given key, or {@code null} if
+     * no mapping of the desired type exists for the given key or a {@code null}
      * value is explicitly associated with the key.
      *
-     * @param key a String, or null
-     * @return an ArrayList<T> value, or null
+     * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
+     * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
+     * Otherwise, this method might throw an exception or return {@code null}.
+     *
+     * @param key a String, or {@code null}
+     * @return an ArrayList<T> value, or {@code null}
      */
     @Nullable
     public <T extends Parcelable> ArrayList<T> getParcelableArrayList(@Nullable String key) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 790bb27..9c9829f 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1470,6 +1470,24 @@
     }
 
     /**
+     * Check if a user is a restricted profile. Restricted profiles may have a reduced number of
+     * available apps, app restrictions, and account restrictions.
+     *
+     * @param user the user to check
+     * @return whether the user is a restricted profile.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    public boolean isRestrictedProfile(@NonNull UserHandle user) {
+        try {
+            return mService.getUserInfo(user.getIdentifier()).isRestricted();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Checks if specified user can have restricted profile.
      * @hide
      */
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index cc73786..7fc07b0 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -216,6 +216,23 @@
     public static final String NAMESPACE_RUNTIME_NATIVE_BOOT = "runtime_native_boot";
 
     /**
+     * Namespace for system scheduler related features. These features will be applied
+     * immediately upon change.
+     *
+     * @hide
+     */
+    @SystemApi
+    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
@@ -285,42 +302,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";
-    }
-
-    /**
-     * Namespace for system scheduler related features. These features will be applied
-     * immediately upon change.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface Scheduler {
-        String NAMESPACE = "scheduler";
-
-        /**
-         * Flag for enabling fast metrics collection in system scheduler.
-         * A flag value of '' or '0' means the fast metrics collection is not
-         * enabled. Otherwise fast metrics collection is enabled and flag value
-         * is the order id.
-         */
-        String ENABLE_FAST_METRICS_COLLECTION = "enable_fast_metrics_collection";
-    }
-
     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 313384d..63235a1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1696,6 +1696,19 @@
     public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE =
             "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
 
+    /**
+     * Activity Action: Show screen that let user manage how Android handles URL resolution.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_DOMAIN_URLS = "android.settings.MANAGE_DOMAIN_URLS";
+
     // End of Intent actions for Settings
 
     /**
@@ -5594,6 +5607,7 @@
          *
          * @hide
          */
+        @SystemApi
         public static final String ODI_CAPTIONS_ENABLED = "odi_captions_enabled";
 
         private static final Validator ODI_CAPTIONS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -12585,8 +12599,9 @@
 
         /**
          * Battery level [1-100] at which low power mode automatically turns on.
-         * Pre-Q If 0, it will not automatically turn on. Q and newer it will only automatically
-         * turn on if the {@link #AUTOMATIC_POWER_SAVER_MODE} setting is also set to
+         * If 0, it will not automatically turn on. For Q and newer, it will only automatically
+         * turn on if the value is greater than 0 and the {@link #AUTOMATIC_POWER_SAVER_MODE}
+         * setting is also set to
          * {@link android.os.PowerManager.AutoPowerSaverMode#POWER_SAVER_MODE_PERCENTAGE}.
          *
          * @see #AUTOMATIC_POWER_SAVER_MODE
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/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/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 83f14d1..100774c 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -536,7 +536,7 @@
          * or playing back a file. The value should be one of the STREAM_ constants
          * defined in {@link AudioManager}.
          *
-         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#speak(CharSequence, int, Bundle, String)
          * @see TextToSpeech#playEarcon(String, int, HashMap)
          */
         public static final String KEY_PARAM_STREAM = "streamType";
@@ -546,7 +546,7 @@
          * speaking text or playing back a file. The value should be set
          * using {@link TextToSpeech#setAudioAttributes(AudioAttributes)}.
          *
-         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#speak(CharSequence, int, Bundle, String)
          * @see TextToSpeech#playEarcon(String, int, HashMap)
          * @hide
          */
@@ -557,7 +557,7 @@
          * {@link TextToSpeech.OnUtteranceCompletedListener} after text has been
          * spoken, a file has been played back or a silence duration has elapsed.
          *
-         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#speak(CharSequence, int, Bundle, String)
          * @see TextToSpeech#playEarcon(String, int, HashMap)
          * @see TextToSpeech#synthesizeToFile(String, HashMap, String)
          */
@@ -568,7 +568,7 @@
          * volume used when speaking text. Volume is specified as a float ranging from 0 to 1
          * where 0 is silence, and 1 is the maximum volume (the default behavior).
          *
-         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#speak(CharSequence, int, Bundle, String)
          * @see TextToSpeech#playEarcon(String, int, HashMap)
          */
         public static final String KEY_PARAM_VOLUME = "volume";
@@ -578,7 +578,7 @@
          * Pan is specified as a float ranging from -1 to +1 where -1 maps to a hard-left pan,
          * 0 to center (the default behavior), and +1 to hard-right.
          *
-         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#speak(CharSequence, int, Bundle, String)
          * @see TextToSpeech#playEarcon(String, int, HashMap)
          */
         public static final String KEY_PARAM_PAN = "pan";
@@ -589,7 +589,7 @@
          * as per {@link TextToSpeech#getFeatures(Locale)}, the engine must
          * use network based synthesis.
          *
-         * @see TextToSpeech#speak(String, int, java.util.HashMap)
+         * @see TextToSpeech#speak(CharSequence, int, Bundle, String)
          * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String)
          * @see TextToSpeech#getFeatures(java.util.Locale)
          *
@@ -607,7 +607,7 @@
          * as per {@link TextToSpeech#getFeatures(Locale)}, the engine must synthesize
          * text on-device (without making network requests).
          *
-         * @see TextToSpeech#speak(String, int, java.util.HashMap)
+         * @see TextToSpeech#speak(CharSequence, int, Bundle, String)
          * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String)
          * @see TextToSpeech#getFeatures(java.util.Locale)
 
@@ -625,7 +625,7 @@
          * output. It can be used to associate one of the {@link android.media.audiofx.AudioEffect}
          * objects with the synthesis (or earcon) output.
          *
-         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#speak(CharSequence, int, Bundle, String)
          * @see TextToSpeech#playEarcon(String, int, HashMap)
          */
         public static final String KEY_PARAM_SESSION_ID = "sessionId";
@@ -881,7 +881,7 @@
     /**
      * Adds a mapping between a string of text and a sound resource in a
      * package. After a call to this method, subsequent calls to
-     * {@link #speak(String, int, HashMap)} will play the specified sound resource
+     * {@link #speak(CharSequence, int, Bundle, String)} will play the specified sound resource
      * if it is available, or synthesize the text it is missing.
      *
      * @param text
@@ -915,7 +915,7 @@
     /**
      * Adds a mapping between a CharSequence (may be spanned with TtsSpans) of text
      * and a sound resource in a package. After a call to this method, subsequent calls to
-     * {@link #speak(String, int, HashMap)} will play the specified sound resource
+     * {@link #speak(CharSequence, int, Bundle, String)} will play the specified sound resource
      * if it is available, or synthesize the text it is missing.
      *
      * @param text
@@ -947,11 +947,10 @@
     }
 
     /**
-     * Adds a mapping between a string of text and a sound file. Using this, it
-     * is possible to add custom pronounciations for a string of text.
-     * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)}
-     * will play the specified sound resource if it is available, or synthesize the text it is
-     * missing.
+     * Adds a mapping between a string of text and a sound file. Using this, it is possible to
+     * add custom pronounciations for a string of text. After a call to this method, subsequent
+     * calls to {@link #speak(CharSequence, int, Bundle, String)} will play the specified sound
+     * resource if it is available, or synthesize the text it is missing.
      *
      * @param text
      *            The string of text. Example: <code>"south_south_east"</code>
@@ -970,8 +969,8 @@
 
     /**
      * Adds a mapping between a CharSequence (may be spanned with TtsSpans and a sound file.
-     * Using this, it is possible to add custom pronounciations for a string of text.
-     * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)}
+     * Using this, it is possible to add custom pronounciations for a string of text. After a call
+     * to this method, subsequent calls to {@link #speak(CharSequence, int, Bundle, String)}
      * will play the specified sound resource if it is available, or synthesize the text it is
      * missing.
      *
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/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 e32c4e1..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;
@@ -129,7 +130,7 @@
     @UnsupportedAppUsage
     boolean isKeyguardLocked();
     @UnsupportedAppUsage
-    boolean isKeyguardSecure();
+    boolean isKeyguardSecure(int userId);
     void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message);
 
     // Requires INTERACT_ACROSS_USERS_FULL permission
@@ -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/InsetsState.java b/core/java/android/view/InsetsState.java
index 2d7e179..6129b38 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -145,7 +145,14 @@
 
             // TODO: set system gesture insets based on actual system gesture area.
             typeInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyContentInsets);
-            typeMaxInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyContentInsets);
+            typeInsetsMap[Type.indexOf(Type.mandatorySystemGestures())] =
+                    Insets.of(legacyContentInsets);
+            typeInsetsMap[Type.indexOf(Type.tappableElement())] = Insets.of(legacyContentInsets);
+
+            typeMaxInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyStableInsets);
+            typeMaxInsetsMap[Type.indexOf(Type.mandatorySystemGestures())] =
+                    Insets.of(legacyStableInsets);
+            typeMaxInsetsMap[Type.indexOf(Type.tappableElement())] = Insets.of(legacyStableInsets);
         }
         for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
             InsetsSource source = mSources.get(type);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 49eb78d..bf0f4e2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -130,8 +130,8 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inspector.InspectableProperty;
-import android.view.inspector.InspectableProperty.EnumMap;
-import android.view.inspector.InspectableProperty.FlagMap;
+import android.view.inspector.InspectableProperty.EnumEntry;
+import android.view.inspector.InspectableProperty.FlagEntry;
 import android.widget.Checkable;
 import android.widget.FrameLayout;
 import android.widget.ScrollBarDrawable;
@@ -6902,13 +6902,13 @@
      * @return a bitmask representing the enabled scroll indicators
      */
     @InspectableProperty(flagMapping = {
-            @FlagMap(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
-            @FlagMap(target = SCROLL_INDICATOR_TOP, name = "top"),
-            @FlagMap(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
-            @FlagMap(target = SCROLL_INDICATOR_LEFT, name = "left"),
-            @FlagMap(target = SCROLL_INDICATOR_RIGHT, name = "right"),
-            @FlagMap(target = SCROLL_INDICATOR_START, name = "start"),
-            @FlagMap(target = SCROLL_INDICATOR_END, name = "end")
+            @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
+            @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
+            @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
+            @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
+            @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
+            @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
+            @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
     })
     @ScrollIndicators
     public int getScrollIndicators() {
@@ -9037,12 +9037,12 @@
             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
                 to = "noExcludeDescendants")})
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
-            @EnumMap(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
-            @EnumMap(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
-            @EnumMap(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
+            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
+            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
+            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
+            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
                     name = "yesExcludeDescendants"),
-            @EnumMap(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
+            @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
                     name = "noExcludeDescendants"),
     })
     public @AutofillImportance int getImportantForAutofill() {
@@ -9230,12 +9230,12 @@
             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
                 to = "noExcludeDescendants")})
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
-            @EnumMap(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
-            @EnumMap(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
-            @EnumMap(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
+            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
+            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
+            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
                     name = "yesExcludeDescendants"),
-            @EnumMap(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
+            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
                     name = "noExcludeDescendants"),
     })
     public @ContentCaptureImportance int getImportantForContentCapture() {
@@ -10539,9 +10539,9 @@
     @Deprecated
     @DrawingCacheQuality
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
-            @EnumMap(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
-            @EnumMap(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
+            @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
+            @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
+            @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
     })
     public int getDrawingCacheQuality() {
         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
@@ -11095,11 +11095,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;
@@ -11281,9 +11280,9 @@
         @ViewDebug.IntToString(from = GONE,      to = "GONE")
     })
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = VISIBLE, name = "visible"),
-            @EnumMap(value = INVISIBLE, name = "invisible"),
-            @EnumMap(value = GONE, name = "gone")
+            @EnumEntry(value = VISIBLE, name = "visible"),
+            @EnumEntry(value = INVISIBLE, name = "invisible"),
+            @EnumEntry(value = GONE, name = "gone")
     })
     @Visibility
     public int getVisibility() {
@@ -11532,10 +11531,10 @@
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
     })
     @InspectableProperty(hasAttributeId = false, enumMapping = {
-            @EnumMap(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
-            @EnumMap(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
-            @EnumMap(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
-            @EnumMap(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
+            @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
+            @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
+            @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
+            @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
     })
     @LayoutDir
     public int getRawLayoutDirection() {
@@ -11591,8 +11590,8 @@
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
     })
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
-            @EnumMap(value = LAYOUT_DIRECTION_RTL, name = "rtl")
+            @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
+            @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
     })
     @ResolvedLayoutDir
     public int getLayoutDirection() {
@@ -12077,9 +12076,9 @@
             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
             }, category = "focus")
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = NOT_FOCUSABLE, name = "false"),
-            @EnumMap(value = FOCUSABLE, name = "true"),
-            @EnumMap(value = FOCUSABLE_AUTO, name = "auto")
+            @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
+            @EnumEntry(value = FOCUSABLE, name = "true"),
+            @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
     })
     @Focusable
     public int getFocusable() {
@@ -12962,10 +12961,10 @@
                     to = "noHideDescendants")
         })
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
-            @EnumMap(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
-            @EnumMap(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
-            @EnumMap(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
+            @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
+            @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
+            @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
+            @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
                     name = "noHideDescendants"),
     })
     public int getImportantForAccessibility() {
@@ -13021,9 +13020,9 @@
      * @see #setAccessibilityLiveRegion(int)
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
-            @EnumMap(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
-            @EnumMap(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
+            @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
+            @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
+            @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
     })
     public int getAccessibilityLiveRegion() {
         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
@@ -18651,9 +18650,9 @@
      * @hide
      */
     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
-            @FlagMap(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
-            @FlagMap(target = FADING_EDGE_VERTICAL, name = "vertical"),
-            @FlagMap(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
+            @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
+            @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
+            @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
     })
     public int getFadingEdge() {
         return mViewFlags & FADING_EDGE_MASK;
@@ -18948,10 +18947,10 @@
             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
     })
     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
-            @EnumMap(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
-            @EnumMap(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
-            @EnumMap(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
-            @EnumMap(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
+            @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
+            @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
+            @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
+            @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
     })
     @ScrollBarStyle
     public int getScrollBarStyle() {
@@ -20504,9 +20503,9 @@
      * @see #LAYER_TYPE_HARDWARE
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = LAYER_TYPE_NONE, name = "none"),
-            @EnumMap(value = LAYER_TYPE_SOFTWARE, name = "software"),
-            @EnumMap(value = LAYER_TYPE_HARDWARE, name = "hardware")
+            @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
+            @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
+            @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
     })
     @LayerType
     public int getLayerType() {
@@ -26187,9 +26186,9 @@
      * @return This view's over-scroll mode.
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = OVER_SCROLL_ALWAYS, name = "always"),
-            @EnumMap(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
-            @EnumMap(value = OVER_SCROLL_NEVER, name = "never")
+            @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
+            @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
+            @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
     })
     public int getOverScrollMode() {
         return mOverScrollMode;
@@ -26580,14 +26579,14 @@
             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
     })
     @InspectableProperty(hasAttributeId = false, enumMapping = {
-            @EnumMap(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
-            @EnumMap(value = TEXT_DIRECTION_LOCALE, name = "locale"),
-            @EnumMap(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
-            @EnumMap(value = TEXT_DIRECTION_LTR, name = "ltr"),
-            @EnumMap(value = TEXT_DIRECTION_RTL, name = "rtl"),
-            @EnumMap(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
-            @EnumMap(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
-            @EnumMap(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
+            @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
+            @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
+            @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
+            @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
+            @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
+            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
+            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
+            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
     })
     @UnsupportedAppUsage
     public int getRawTextDirection() {
@@ -26657,13 +26656,13 @@
             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
     })
     @InspectableProperty(hasAttributeId = false, enumMapping = {
-            @EnumMap(value = TEXT_DIRECTION_LOCALE, name = "locale"),
-            @EnumMap(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
-            @EnumMap(value = TEXT_DIRECTION_LTR, name = "ltr"),
-            @EnumMap(value = TEXT_DIRECTION_RTL, name = "rtl"),
-            @EnumMap(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
-            @EnumMap(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
-            @EnumMap(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
+            @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
+            @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
+            @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
+            @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
+            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
+            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
+            @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
     })
     public int getTextDirection() {
         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
@@ -26837,13 +26836,13 @@
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
     })
     @InspectableProperty(hasAttributeId = false, enumMapping = {
-            @EnumMap(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
-            @EnumMap(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
-            @EnumMap(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
-            @EnumMap(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
-            @EnumMap(value = TEXT_ALIGNMENT_CENTER, name = "center"),
-            @EnumMap(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
-            @EnumMap(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
+            @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
+            @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
+            @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
+            @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
+            @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
+            @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
+            @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
     })
     @TextAlignment
     @UnsupportedAppUsage
@@ -26912,12 +26911,12 @@
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
     })
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
-            @EnumMap(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
-            @EnumMap(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
-            @EnumMap(value = TEXT_ALIGNMENT_CENTER, name = "center"),
-            @EnumMap(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
-            @EnumMap(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
+            @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
+            @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
+            @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
+            @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
+            @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
+            @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
     })
     @TextAlignment
     public int getTextAlignment() {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 4964ee1..a4d80dc 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -61,7 +61,7 @@
 import android.view.animation.Transformation;
 import android.view.autofill.Helper;
 import android.view.inspector.InspectableProperty;
-import android.view.inspector.InspectableProperty.EnumMap;
+import android.view.inspector.InspectableProperty.EnumEntry;
 
 import com.android.internal.R;
 
@@ -778,9 +778,9 @@
         @ViewDebug.IntToString(from = FOCUS_BLOCK_DESCENDANTS, to = "FOCUS_BLOCK_DESCENDANTS")
     })
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = FOCUS_BEFORE_DESCENDANTS, name = "beforeDescendants"),
-            @EnumMap(value = FOCUS_AFTER_DESCENDANTS, name = "afterDescendants"),
-            @EnumMap(value = FOCUS_BLOCK_DESCENDANTS, name = "blocksDescendants")
+            @EnumEntry(value = FOCUS_BEFORE_DESCENDANTS, name = "beforeDescendants"),
+            @EnumEntry(value = FOCUS_AFTER_DESCENDANTS, name = "afterDescendants"),
+            @EnumEntry(value = FOCUS_BLOCK_DESCENDANTS, name = "blocksDescendants")
     })
     public int getDescendantFocusability() {
         return mGroupFlags & FLAG_MASK_FOCUSABILITY;
@@ -6574,10 +6574,10 @@
         @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES,      to = "ALL")
     })
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = PERSISTENT_NO_CACHE, name = "none"),
-            @EnumMap(value = PERSISTENT_ANIMATION_CACHE, name = "animation"),
-            @EnumMap(value = PERSISTENT_SCROLLING_CACHE, name = "scrolling"),
-            @EnumMap(value = PERSISTENT_ALL_CACHES, name = "all"),
+            @EnumEntry(value = PERSISTENT_NO_CACHE, name = "none"),
+            @EnumEntry(value = PERSISTENT_ANIMATION_CACHE, name = "animation"),
+            @EnumEntry(value = PERSISTENT_SCROLLING_CACHE, name = "scrolling"),
+            @EnumEntry(value = PERSISTENT_ALL_CACHES, name = "all"),
     })
     public int getPersistentDrawingCache() {
         return mPersistentDrawingCache;
@@ -6657,8 +6657,8 @@
      * @see #setLayoutMode(int)
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = LAYOUT_MODE_CLIP_BOUNDS, name = "clipBounds"),
-            @EnumMap(value = LAYOUT_MODE_OPTICAL_BOUNDS, name = "opticalBounds")
+            @EnumEntry(value = LAYOUT_MODE_CLIP_BOUNDS, name = "clipBounds"),
+            @EnumEntry(value = LAYOUT_MODE_OPTICAL_BOUNDS, name = "opticalBounds")
     })
     public int getLayoutMode() {
         if (mLayoutMode == LAYOUT_MODE_UNDEFINED) {
@@ -7849,8 +7849,8 @@
             @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT")
         })
         @InspectableProperty(name = "layout_width", enumMapping = {
-                @InspectableProperty.EnumMap(name = "match_parent", value = MATCH_PARENT),
-                @InspectableProperty.EnumMap(name = "wrap_content", value = WRAP_CONTENT)
+                @EnumEntry(name = "match_parent", value = MATCH_PARENT),
+                @EnumEntry(name = "wrap_content", value = WRAP_CONTENT)
         })
         public int width;
 
@@ -7864,8 +7864,8 @@
             @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT")
         })
         @InspectableProperty(name = "layout_height", enumMapping = {
-                @InspectableProperty.EnumMap(name = "match_parent", value = MATCH_PARENT),
-                @InspectableProperty.EnumMap(name = "wrap_content", value = WRAP_CONTENT)
+                @EnumEntry(name = "match_parent", value = MATCH_PARENT),
+                @EnumEntry(name = "wrap_content", value = WRAP_CONTENT)
         })
         public int height;
 
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/WindowInsets.java b/core/java/android/view/WindowInsets.java
index f1a992c..aac0e34 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -20,14 +20,18 @@
 import static android.view.WindowInsets.Type.FIRST;
 import static android.view.WindowInsets.Type.IME;
 import static android.view.WindowInsets.Type.LAST;
+import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
 import static android.view.WindowInsets.Type.SIDE_BARS;
 import static android.view.WindowInsets.Type.SIZE;
 import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
+import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT;
 import static android.view.WindowInsets.Type.TOP_BAR;
 import static android.view.WindowInsets.Type.all;
 import static android.view.WindowInsets.Type.compatSystemInsets;
 import static android.view.WindowInsets.Type.indexOf;
+import static android.view.WindowInsets.Type.mandatorySystemGestures;
 import static android.view.WindowInsets.Type.systemGestures;
+import static android.view.WindowInsets.Type.tappableElement;
 
 import android.annotation.IntDef;
 import android.annotation.IntRange;
@@ -223,6 +227,8 @@
         assignCompatInsets(typeInsetMap, insets);
         // TODO: set system gesture insets based on actual system gesture area.
         typeInsetMap[indexOf(systemGestures())] = Insets.of(insets);
+        typeInsetMap[indexOf(mandatorySystemGestures())] = Insets.of(insets);
+        typeInsetMap[indexOf(tappableElement())] = Insets.of(insets);
         return typeInsetMap;
     }
 
@@ -639,15 +645,22 @@
      * priority and may consume some or all touch input, e.g. due to the a system bar
      * occupying it, or it being reserved for touch-only gestures.
      *
+     * <p>An app can declare priority over system gestures with
+     * {@link View#setSystemGestureExclusionRects} outside of the
+     * {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}.
+     *
      * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
-     * as long as they are outside the {@link #getSystemWindowInsets() system window insets}.
+     * as long as they are outside the {@link #getTappableElementInsets() system window insets}.
      *
      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
      * even when the system gestures are inactive due to
      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
      *
-     * <p>This inset does not affect the result of {@link #isConsumed()} and cannot be consumed.
+     * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
+     * system window insets} by {@link #consumeSystemWindowInsets()}.
+     *
+     * @see #getMandatorySystemGestureInsets
      */
     @NonNull
     public Insets getSystemGestureInsets() {
@@ -655,6 +668,60 @@
     }
 
     /**
+     * Returns the mandatory system gesture insets.
+     *
+     * <p>The mandatory system gesture insets represent the area of a window where mandatory system
+     * gestures have priority and may consume some or all touch input, e.g. due to the a system bar
+     * occupying it, or it being reserved for touch-only gestures.
+     *
+     * <p>In contrast to {@link #getSystemGestureInsets regular system gestures}, <b>mandatory</b>
+     * system gestures cannot be overriden by {@link View#setSystemGestureExclusionRects}.
+     *
+     * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
+     * as long as they are outside the {@link #getTappableElementInsets() system window insets}.
+     *
+     * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
+     * even when the system gestures are inactive due to
+     * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
+     * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
+     *
+     * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
+     * system window insets} by {@link #consumeSystemWindowInsets()}.
+     *
+     * @see #getSystemGestureInsets
+     */
+    @NonNull
+    public Insets getMandatorySystemGestureInsets() {
+        return getInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES);
+    }
+
+    /**
+     * Returns the tappable element insets.
+     *
+     * <p>The tappable element insets represent how much tappable elements <b>must at least</b> be
+     * inset to remain both tappable and visually unobstructed by persistent system windows.
+     *
+     * <p>This may be smaller than {@link #getSystemWindowInsets()} if the system window is
+     * largely transparent and lets through simple taps (but not necessarily more complex gestures).
+     *
+     * <p>Note that generally, tappable elements <strong>should</strong> be aligned with the
+     * {@link #getSystemWindowInsets() system window insets} instead to avoid overlapping with the
+     * system bars.
+     *
+     * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
+     * even when the area covered by the inset would be tappable due to
+     * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
+     * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
+     *
+     * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
+     * system window insets} by {@link #consumeSystemWindowInsets()}.
+     */
+    @NonNull
+    public Insets getTappableElementInsets() {
+        return getInsets(mTypeInsetsMap, TAPPABLE_ELEMENT);
+    }
+
+    /**
      * Returns a copy of this WindowInsets with the stable insets fully consumed.
      *
      * @return A modified copy of this WindowInsets
@@ -895,6 +962,41 @@
         }
 
         /**
+         * Sets mandatory system gesture insets in pixels.
+         *
+         * <p>The mandatory system gesture insets represent the area of a window where mandatory
+         * system gestures have priority and may consume some or all touch input, e.g. due to the a
+         * system bar occupying it, or it being reserved for touch-only gestures.
+         *
+         * <p>In contrast to {@link #setSystemGestureInsets regular system gestures},
+         * <b>mandatory</b> system gestures cannot be overriden by
+         * {@link View#setSystemGestureExclusionRects}.
+         *
+         * @see #getMandatorySystemGestureInsets()
+         * @return itself
+         */
+        @NonNull
+        public Builder setMandatorySystemGestureInsets(@NonNull Insets insets) {
+            WindowInsets.setInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES, insets);
+            return this;
+        }
+
+        /**
+         * Sets tappable element insets in pixels.
+         *
+         * <p>The tappable element insets represent how much tappable elements <b>must at least</b>
+         * be inset to remain both tappable and visually unobstructed by persistent system windows.
+         *
+         * @see #getTappableElementInsets()
+         * @return itself
+         */
+        @NonNull
+        public Builder setTappableElementInsets(@NonNull Insets insets) {
+            WindowInsets.setInsets(mTypeInsetsMap, TAPPABLE_ELEMENT, insets);
+            return this;
+        }
+
+        /**
          * Sets the insets of a specific window type in pixels.
          *
          * <p>The insets represents the area of a a window that is partially or fully obscured by
@@ -1041,16 +1143,18 @@
      */
     public static final class Type {
 
-        static final int FIRST = 0x1;
+        static final int FIRST = 1 << 0;
         static final int TOP_BAR = FIRST;
 
-        static final int IME = 0x2;
-        static final int SIDE_BARS = 0x4;
+        static final int IME = 1 << 1;
+        static final int SIDE_BARS = 1 << 2;
 
-        static final int SYSTEM_GESTURES = 0x8;
+        static final int SYSTEM_GESTURES = 1 << 3;
+        static final int MANDATORY_SYSTEM_GESTURES = 1 << 4;
+        static final int TAPPABLE_ELEMENT = 1 << 5;
 
-        static final int LAST = 0x10;
-        static final int SIZE = 5;
+        static final int LAST = 1 << 6;
+        static final int SIZE = 7;
         static final int WINDOW_DECOR = LAST;
 
         static int indexOf(@InsetType int type) {
@@ -1063,8 +1167,12 @@
                     return 2;
                 case SYSTEM_GESTURES:
                     return 3;
-                case WINDOW_DECOR:
+                case MANDATORY_SYSTEM_GESTURES:
                     return 4;
+                case TAPPABLE_ELEMENT:
+                    return 5;
+                case WINDOW_DECOR:
+                    return 6;
                 default:
                     throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST,"
                             + " type=" + type);
@@ -1076,7 +1184,8 @@
 
         /** @hide */
         @Retention(RetentionPolicy.SOURCE)
-        @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR, SYSTEM_GESTURES })
+        @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR, SYSTEM_GESTURES,
+                MANDATORY_SYSTEM_GESTURES, TAPPABLE_ELEMENT})
         public @interface InsetType {
         }
 
@@ -1131,6 +1240,20 @@
         }
 
         /**
+         * @see #getMandatorySystemGestureInsets
+         */
+        public static @InsetType int mandatorySystemGestures() {
+            return MANDATORY_SYSTEM_GESTURES;
+        }
+
+        /**
+         * @see #getTappableElementInsets
+         */
+        public static @InsetType int tappableElement() {
+            return TAPPABLE_ELEMENT;
+        }
+
+        /**
          * @return All system bars. Includes {@link #topBar()} as well as {@link #sideBars()}, but
          *         not {@link #ime()}.
          */
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 019ebff..5a27e94 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -161,7 +161,7 @@
     /**
      * Gets the context id.
      */
-    @NonNull
+    @Nullable
     public LocusId getLocusId() {
         return mId;
     }
diff --git a/core/java/android/view/inspector/InspectableProperty.java b/core/java/android/view/inspector/InspectableProperty.java
index 97ede86..03f1ec5 100644
--- a/core/java/android/view/inspector/InspectableProperty.java
+++ b/core/java/android/view/inspector/InspectableProperty.java
@@ -87,21 +87,21 @@
      *
      * Note that {@link #enumMapping()} cannot be used simultaneously with {@link #flagMapping()}.
      *
-     * @return An array of {@link EnumMap}, empty if not applicable
+     * @return An array of {@link EnumEntry}, empty if not applicable
      * @see android.annotation.IntDef
      */
-    EnumMap[] enumMapping() default {};
+    EnumEntry[] enumMapping() default {};
 
     /**
      * For flags packed into primitive {int} properties, model the string names of the flags.
      *
      * Note that {@link #flagMapping()} cannot be used simultaneously with {@link #enumMapping()}.
      *
-     * @return An array of {@link FlagMap}, empty if not applicable
+     * @return An array of {@link FlagEntry}, empty if not applicable
      * @see android.annotation.IntDef
      * @see IntFlagMapping
      */
-    FlagMap[] flagMapping() default {};
+    FlagEntry[] flagMapping() default {};
 
 
     /**
@@ -113,7 +113,7 @@
     @Target({TYPE})
     @Retention(SOURCE)
     @TestApi
-    @interface EnumMap {
+    @interface EnumEntry {
         /**
          * The string name of this enumeration value.
          *
@@ -138,7 +138,7 @@
     @Target({TYPE})
     @Retention(SOURCE)
     @TestApi
-    @interface FlagMap {
+    @interface FlagEntry {
         /**
          * The string name of this flag.
          *
@@ -195,7 +195,7 @@
          *
          * This is inferred if {@link #enumMapping()} is specified.
          *
-         * @see EnumMap
+         * @see EnumEntry
          * @hide
          */
         @TestApi
@@ -206,7 +206,7 @@
          *
          * This is inferred if {@link #flagMapping()} is specified.
          *
-         * @see FlagMap
+         * @see FlagEntry
          * @hide
          */
         @TestApi
@@ -227,7 +227,7 @@
         /**
          * Value packs gravity information.
          *
-         * This type is not inferred, and is non-trivial to represent using {@link FlagMap}.
+         * This type is not inferred, and is non-trivial to represent using {@link FlagEntry}.
          *
          * @see android.view.Gravity
          * @hide
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/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 034cabd..26dba45 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2292,9 +2292,9 @@
      * @return the requested renderer priority policy.
      */
     @InspectableProperty(hasAttributeId = false, enumMapping = {
-            @InspectableProperty.EnumMap(name = "waived", value = RENDERER_PRIORITY_WAIVED),
-            @InspectableProperty.EnumMap(name = "bound", value = RENDERER_PRIORITY_BOUND),
-            @InspectableProperty.EnumMap(name = "important", value = RENDERER_PRIORITY_IMPORTANT)
+            @InspectableProperty.EnumEntry(name = "waived", value = RENDERER_PRIORITY_WAIVED),
+            @InspectableProperty.EnumEntry(name = "bound", value = RENDERER_PRIORITY_BOUND),
+            @InspectableProperty.EnumEntry(name = "important", value = RENDERER_PRIORITY_IMPORTANT)
     })
     @RendererPriority
     public int getRendererRequestedPriority() {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 24f1fb5..4cb552d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -83,7 +83,7 @@
 import android.view.inputmethod.InputContentInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inspector.InspectableProperty;
-import android.view.inspector.InspectableProperty.EnumMap;
+import android.view.inspector.InspectableProperty.EnumEntry;
 import android.widget.RemoteViews.OnClickHandler;
 
 import com.android.internal.R;
@@ -1221,10 +1221,10 @@
      * @return The current choice mode
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = CHOICE_MODE_NONE, name = "none"),
-            @EnumMap(value = CHOICE_MODE_SINGLE, name = "singleChoice"),
-            @EnumMap(value = CHOICE_MODE_MULTIPLE, name = "multipleChoice"),
-            @EnumMap(value = CHOICE_MODE_MULTIPLE_MODAL, name = "multipleChoiceModal")
+            @EnumEntry(value = CHOICE_MODE_NONE, name = "none"),
+            @EnumEntry(value = CHOICE_MODE_SINGLE, name = "singleChoice"),
+            @InspectableProperty.EnumEntry(value = CHOICE_MODE_MULTIPLE, name = "multipleChoice"),
+            @EnumEntry(value = CHOICE_MODE_MULTIPLE_MODAL, name = "multipleChoiceModal")
     })
     public int getChoiceMode() {
         return mChoiceMode;
@@ -6293,9 +6293,9 @@
      *         {@link #TRANSCRIPT_MODE_ALWAYS_SCROLL}
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(value = TRANSCRIPT_MODE_DISABLED, name = "disabled"),
-            @EnumMap(value = TRANSCRIPT_MODE_NORMAL, name = "normal"),
-            @EnumMap(value = TRANSCRIPT_MODE_ALWAYS_SCROLL, name = "alwaysScroll")
+            @EnumEntry(value = TRANSCRIPT_MODE_DISABLED, name = "disabled"),
+            @EnumEntry(value = TRANSCRIPT_MODE_NORMAL, name = "normal"),
+            @EnumEntry(value = TRANSCRIPT_MODE_ALWAYS_SCROLL, name = "alwaysScroll")
     })
     public int getTranscriptMode() {
         return mTranscriptMode;
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index ecb846b..0c593be 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -216,8 +216,8 @@
      * @hide Visible for testing only.
      */
     @InspectableProperty(name = "datePickerMode", enumMapping = {
-            @InspectableProperty.EnumMap(value = MODE_SPINNER, name = "spinner"),
-            @InspectableProperty.EnumMap(value = MODE_CALENDAR, name = "calendar")
+            @InspectableProperty.EnumEntry(value = MODE_SPINNER, name = "spinner"),
+            @InspectableProperty.EnumEntry(value = MODE_CALENDAR, name = "calendar")
     })
     @DatePickerMode
     @TestApi
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/GridLayout.java b/core/java/android/widget/GridLayout.java
index 1c8bb04..8cda47d 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -331,8 +331,8 @@
      */
     @Orientation
     @InspectableProperty(enumMapping = {
-            @InspectableProperty.EnumMap(value = HORIZONTAL, name = "horizontal"),
-            @InspectableProperty.EnumMap(value = VERTICAL, name = "vertical")
+            @InspectableProperty.EnumEntry(value = HORIZONTAL, name = "horizontal"),
+            @InspectableProperty.EnumEntry(value = VERTICAL, name = "vertical")
     })
     public int getOrientation() {
         return mOrientation;
@@ -510,8 +510,8 @@
      */
     @AlignmentMode
     @InspectableProperty(enumMapping = {
-            @InspectableProperty.EnumMap(value = ALIGN_BOUNDS, name = "alignBounds"),
-            @InspectableProperty.EnumMap(value = ALIGN_MARGINS, name = "alignMargins"),
+            @InspectableProperty.EnumEntry(value = ALIGN_BOUNDS, name = "alignBounds"),
+            @InspectableProperty.EnumEntry(value = ALIGN_MARGINS, name = "alignMargins"),
     })
     public int getAlignmentMode() {
         return mAlignmentMode;
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index f44c331..4e39a55 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -2174,11 +2174,11 @@
 
     @StretchMode
     @InspectableProperty(enumMapping = {
-            @InspectableProperty.EnumMap(value = NO_STRETCH, name = "none"),
-            @InspectableProperty.EnumMap(value = STRETCH_SPACING, name = "spacingWidth"),
-            @InspectableProperty.EnumMap(
+            @InspectableProperty.EnumEntry(value = NO_STRETCH, name = "none"),
+            @InspectableProperty.EnumEntry(value = STRETCH_SPACING, name = "spacingWidth"),
+            @InspectableProperty.EnumEntry(
                     value = STRETCH_SPACING_UNIFORM, name = "spacingWidthUniform"),
-            @InspectableProperty.EnumMap(value = STRETCH_COLUMN_WIDTH, name = "columnWidth"),
+            @InspectableProperty.EnumEntry(value = STRETCH_COLUMN_WIDTH, name = "columnWidth"),
     })
     public int getStretchMode() {
         return mStretchMode;
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index bdde435..a83e826 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1850,8 +1850,8 @@
      */
     @OrientationMode
     @InspectableProperty(enumMapping = {
-            @InspectableProperty.EnumMap(value = HORIZONTAL, name = "horizontal"),
-            @InspectableProperty.EnumMap(value = VERTICAL, name = "vertical")
+            @InspectableProperty.EnumEntry(value = HORIZONTAL, name = "horizontal"),
+            @InspectableProperty.EnumEntry(value = VERTICAL, name = "vertical")
     })
     public int getOrientation() {
         return mOrientation;
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/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 04bcb14..a5a1a80c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -173,8 +173,8 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inspector.InspectableProperty;
-import android.view.inspector.InspectableProperty.EnumMap;
-import android.view.inspector.InspectableProperty.FlagMap;
+import android.view.inspector.InspectableProperty.EnumEntry;
+import android.view.inspector.InspectableProperty.FlagEntry;
 import android.view.textclassifier.TextClassification;
 import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassificationManager;
@@ -1900,8 +1900,8 @@
      * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int)
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(name = "none", value = AUTO_SIZE_TEXT_TYPE_NONE),
-            @EnumMap(name = "uniform", value = AUTO_SIZE_TEXT_TYPE_UNIFORM)
+            @EnumEntry(name = "none", value = AUTO_SIZE_TEXT_TYPE_NONE),
+            @EnumEntry(name = "uniform", value = AUTO_SIZE_TEXT_TYPE_UNIFORM)
     })
     @AutoSizeTextType
     public int getAutoSizeTextType() {
@@ -3527,10 +3527,10 @@
      * @attr ref android.R.styleable#TextView_autoLink
      */
     @InspectableProperty(name = "autoLink", flagMapping = {
-            @FlagMap(name = "web", target = Linkify.WEB_URLS),
-            @FlagMap(name = "email", target = Linkify.EMAIL_ADDRESSES),
-            @FlagMap(name = "phone", target = Linkify.PHONE_NUMBERS),
-            @FlagMap(name = "map", target = Linkify.MAP_ADDRESSES)
+            @FlagEntry(name = "web", target = Linkify.WEB_URLS),
+            @FlagEntry(name = "email", target = Linkify.EMAIL_ADDRESSES),
+            @FlagEntry(name = "phone", target = Linkify.PHONE_NUMBERS),
+            @FlagEntry(name = "map", target = Linkify.MAP_ADDRESSES)
     })
     public final int getAutoLinkMask() {
         return mAutoLinkMask;
@@ -4515,9 +4515,9 @@
      * @see #setBreakStrategy(int)
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(name = "simple", value = Layout.BREAK_STRATEGY_SIMPLE),
-            @EnumMap(name = "high_quality", value = Layout.BREAK_STRATEGY_HIGH_QUALITY),
-            @EnumMap(name = "balanced", value = Layout.BREAK_STRATEGY_BALANCED)
+            @EnumEntry(name = "simple", value = Layout.BREAK_STRATEGY_SIMPLE),
+            @EnumEntry(name = "high_quality", value = Layout.BREAK_STRATEGY_HIGH_QUALITY),
+            @EnumEntry(name = "balanced", value = Layout.BREAK_STRATEGY_BALANCED)
     })
     @Layout.BreakStrategy
     public int getBreakStrategy() {
@@ -4566,9 +4566,9 @@
      * @see #setHyphenationFrequency(int)
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(name = "none", value = Layout.HYPHENATION_FREQUENCY_NONE),
-            @EnumMap(name = "normal", value = Layout.HYPHENATION_FREQUENCY_NORMAL),
-            @EnumMap(name = "full", value = Layout.HYPHENATION_FREQUENCY_FULL)
+            @EnumEntry(name = "none", value = Layout.HYPHENATION_FREQUENCY_NONE),
+            @EnumEntry(name = "normal", value = Layout.HYPHENATION_FREQUENCY_NORMAL),
+            @EnumEntry(name = "full", value = Layout.HYPHENATION_FREQUENCY_FULL)
     })
     @Layout.HyphenationFrequency
     public int getHyphenationFrequency() {
@@ -4628,8 +4628,8 @@
      * @see #setJustificationMode(int)
      */
     @InspectableProperty(enumMapping = {
-            @EnumMap(name = "none", value = Layout.JUSTIFICATION_MODE_NONE),
-            @EnumMap(name = "inter_word", value = Layout.JUSTIFICATION_MODE_INTER_WORD)
+            @EnumEntry(name = "none", value = Layout.JUSTIFICATION_MODE_NONE),
+            @EnumEntry(name = "inter_word", value = Layout.JUSTIFICATION_MODE_INTER_WORD)
     })
     public @Layout.JustificationMode int getJustificationMode() {
         return mJustificationMode;
@@ -6667,142 +6667,142 @@
      * @see android.text.InputType
      */
     @InspectableProperty(flagMapping = {
-            @FlagMap(name = "none", mask = 0xffffffff, target = InputType.TYPE_NULL),
-            @FlagMap(
+            @FlagEntry(name = "none", mask = 0xffffffff, target = InputType.TYPE_NULL),
+            @FlagEntry(
                     name = "text",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL),
-            @FlagMap(
+            @FlagEntry(
                     name = "textUri",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI),
-            @FlagMap(
+            @FlagEntry(
                     name = "textEmailAddress",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS),
-            @FlagMap(
+            @FlagEntry(
                     name = "textEmailSubject",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT),
-            @FlagMap(
+            @FlagEntry(
                     name = "textShortMessage",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE),
-            @FlagMap(
+            @FlagEntry(
                     name = "textLongMessage",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE),
-            @FlagMap(
+            @FlagEntry(
                     name = "textPersonName",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_PERSON_NAME),
-            @FlagMap(
+            @FlagEntry(
                     name = "textPostalAddress",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS),
-            @FlagMap(
+            @FlagEntry(
                     name = "textPassword",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD),
-            @FlagMap(
+            @FlagEntry(
                     name = "textVisiblePassword",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD),
-            @FlagMap(
+            @FlagEntry(
                     name = "textWebEditText",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT),
-            @FlagMap(
+            @FlagEntry(
                     name = "textFilter",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_FILTER),
-            @FlagMap(
+            @FlagEntry(
                     name = "textPhonetic",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PHONETIC),
-            @FlagMap(
+            @FlagEntry(
                     name = "textWebEmailAddress",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS),
-            @FlagMap(
+            @FlagEntry(
                     name = "textWebPassword",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD),
-            @FlagMap(
+            @FlagEntry(
                     name = "number",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL),
-            @FlagMap(
+            @FlagEntry(
                     name = "numberPassword",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_NUMBER
                             | InputType.TYPE_NUMBER_VARIATION_PASSWORD),
-            @FlagMap(
+            @FlagEntry(
                     name = "phone",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_PHONE),
-            @FlagMap(
+            @FlagEntry(
                     name = "datetime",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_DATETIME
                             | InputType.TYPE_DATETIME_VARIATION_NORMAL),
-            @FlagMap(
+            @FlagEntry(
                     name = "date",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_DATETIME
                             | InputType.TYPE_DATETIME_VARIATION_DATE),
-            @FlagMap(
+            @FlagEntry(
                     name = "time",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION,
                     target = InputType.TYPE_CLASS_DATETIME
                             | InputType.TYPE_DATETIME_VARIATION_TIME),
-            @FlagMap(
+            @FlagEntry(
                     name = "textCapCharacters",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS),
-            @FlagMap(
+            @FlagEntry(
                     name = "textCapWords",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_WORDS),
-            @FlagMap(
+            @FlagEntry(
                     name = "textCapSentences",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES),
-            @FlagMap(
+            @FlagEntry(
                     name = "textAutoCorrect",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT),
-            @FlagMap(
+            @FlagEntry(
                     name = "textAutoComplete",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE),
-            @FlagMap(
+            @FlagEntry(
                     name = "textMultiLine",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE),
-            @FlagMap(
+            @FlagEntry(
                     name = "textImeMultiLine",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE),
-            @FlagMap(
+            @FlagEntry(
                     name = "textNoSuggestions",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS),
-            @FlagMap(
+            @FlagEntry(
                     name = "numberSigned",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED),
-            @FlagMap(
+            @FlagEntry(
                     name = "numberDecimal",
                     mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS,
                     target = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL),
@@ -6832,49 +6832,51 @@
      * @see EditorInfo
      */
     @InspectableProperty(flagMapping = {
-            @FlagMap(name = "normal", mask = 0xffffffff, target = EditorInfo.IME_NULL),
-            @FlagMap(
+            @FlagEntry(name = "normal", mask = 0xffffffff, target = EditorInfo.IME_NULL),
+            @FlagEntry(
                     name = "actionUnspecified",
                     mask = EditorInfo.IME_MASK_ACTION,
                     target = EditorInfo.IME_ACTION_UNSPECIFIED),
-            @FlagMap(
+            @FlagEntry(
                     name = "actionNone",
                     mask = EditorInfo.IME_MASK_ACTION,
                     target = EditorInfo.IME_ACTION_NONE),
-            @FlagMap(
+            @FlagEntry(
                     name = "actionGo",
                     mask = EditorInfo.IME_MASK_ACTION,
                     target = EditorInfo.IME_ACTION_GO),
-            @FlagMap(
+            @FlagEntry(
                     name = "actionSearch",
                     mask = EditorInfo.IME_MASK_ACTION,
                     target = EditorInfo.IME_ACTION_SEARCH),
-            @FlagMap(
+            @FlagEntry(
                     name = "actionSend",
                     mask = EditorInfo.IME_MASK_ACTION,
                     target = EditorInfo.IME_ACTION_SEND),
-            @FlagMap(
+            @FlagEntry(
                     name = "actionNext",
                     mask = EditorInfo.IME_MASK_ACTION,
                     target = EditorInfo.IME_ACTION_NEXT),
-            @FlagMap(
+            @FlagEntry(
                     name = "actionDone",
                     mask = EditorInfo.IME_MASK_ACTION,
                     target = EditorInfo.IME_ACTION_DONE),
-            @FlagMap(
+            @FlagEntry(
                     name = "actionPrevious",
                     mask = EditorInfo.IME_MASK_ACTION,
                     target = EditorInfo.IME_ACTION_PREVIOUS),
-            @FlagMap(name = "flagForceAscii", target = EditorInfo.IME_FLAG_FORCE_ASCII),
-            @FlagMap(name = "flagNavigateNext", target = EditorInfo.IME_FLAG_NAVIGATE_NEXT),
-            @FlagMap(name = "flagNavigatePrevious", target = EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS),
-            @FlagMap(
+            @FlagEntry(name = "flagForceAscii", target = EditorInfo.IME_FLAG_FORCE_ASCII),
+            @FlagEntry(name = "flagNavigateNext", target = EditorInfo.IME_FLAG_NAVIGATE_NEXT),
+            @FlagEntry(
+                    name = "flagNavigatePrevious",
+                    target = EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS),
+            @FlagEntry(
                     name = "flagNoAccessoryAction",
                     target = EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION),
-            @FlagMap(name = "flagNoEnterAction", target = EditorInfo.IME_FLAG_NO_ENTER_ACTION),
-            @FlagMap(name = "flagNoExtractUi", target = EditorInfo.IME_FLAG_NO_EXTRACT_UI),
-            @FlagMap(name = "flagNoFullscreen", target = EditorInfo.IME_FLAG_NO_FULLSCREEN),
-            @FlagMap(
+            @FlagEntry(name = "flagNoEnterAction", target = EditorInfo.IME_FLAG_NO_ENTER_ACTION),
+            @FlagEntry(name = "flagNoExtractUi", target = EditorInfo.IME_FLAG_NO_EXTRACT_UI),
+            @FlagEntry(name = "flagNoFullscreen", target = EditorInfo.IME_FLAG_NO_FULLSCREEN),
+            @FlagEntry(
                     name = "flagNoPersonalizedLearning",
                     target = EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING),
     })
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index c7a2980..8a5d531 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -169,8 +169,8 @@
     @TimePickerMode
     @TestApi
     @InspectableProperty(name = "timePickerMode", enumMapping = {
-            @InspectableProperty.EnumMap(name = "clock", value = MODE_CLOCK),
-            @InspectableProperty.EnumMap(name = "spinner", value = MODE_SPINNER)
+            @InspectableProperty.EnumEntry(name = "clock", value = MODE_CLOCK),
+            @InspectableProperty.EnumEntry(name = "spinner", value = MODE_SPINNER)
     })
     public int getMode() {
         return mMode;
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/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..efc6ad0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3929,6 +3929,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/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/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/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/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/LocationManager.java b/location/java/android/location/LocationManager.java
index 050b2ec..01f1798 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -167,9 +167,9 @@
 
     /**
      * Broadcast intent action when the set of enabled location providers changes. To check the
-     * status of a provider, use {@link #isProviderEnabled(String)}. Depending on API level, may
+     * status of a provider, use {@link #isProviderEnabled(String)}. From Android Q and above, will
      * include a string intent extra, {@link #EXTRA_PROVIDER_NAME}, with the name of the provider
-     * whose state has changed. See {@link #EXTRA_PROVIDER_NAME} for the supported API level.
+     * whose state has changed.
      *
      * @see #EXTRA_PROVIDER_NAME
      */
diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java
index 5cd3621..fbe184b 100644
--- a/media/apex/java/android/media/MediaPlayer2.java
+++ b/media/apex/java/android/media/MediaPlayer2.java
@@ -3463,7 +3463,7 @@
              * @param uuid of selected crypto scheme
              * @return this
              */
-            public Builder setUuid(@NonNull UUID uuid) {
+            public @NonNull Builder setUuid(@NonNull UUID uuid) {
                 this.mUUID = uuid;
                 return this;
             }
@@ -3480,7 +3480,7 @@
              * @param keySetId identifier of a persisted offline key
              * @return this
              */
-            public Builder setKeySetId(@Nullable byte[] keySetId) {
+            public @NonNull Builder setKeySetId(@Nullable byte[] keySetId) {
                 this.mKeySetId = keySetId;
                 return this;
             }
@@ -3494,7 +3494,7 @@
              * @param initData container-specific DRM initialization data
              * @return this
              */
-            public Builder setInitData(@Nullable byte[] initData) {
+            public @NonNull Builder setInitData(@Nullable byte[] initData) {
                 this.mInitData = initData;
                 return this;
             }
@@ -3505,7 +3505,7 @@
              * @param mimeType mime type to the content
              * @return this
              */
-            public Builder setMimeType(@Nullable String mimeType) {
+            public @NonNull Builder setMimeType(@Nullable String mimeType) {
                 this.mMimeType = mimeType;
                 return this;
             }
@@ -3519,7 +3519,7 @@
              * @param keyType type of the key request
              * @return this
              */
-            public Builder setKeyType(@MediaPlayer2.MediaDrmKeyType int keyType) {
+            public @NonNull Builder setKeyType(@MediaPlayer2.MediaDrmKeyType int keyType) {
                 this.mKeyType = keyType;
                 return this;
             }
@@ -3531,7 +3531,8 @@
              * @param optionalParameters optional parameters to be included in a key request
              * @return this
              */
-            public Builder setOptionalParameters(@Nullable Map<String, String> optionalParameters) {
+            public @NonNull Builder setOptionalParameters(
+                    @Nullable Map<String, String> optionalParameters) {
                 this.mOptionalParameters = optionalParameters;
                 return this;
             }
@@ -3540,7 +3541,7 @@
              * @return an immutable {@link MediaPlayer2.DrmPreparationInfo} representing the
              *         settings of this builder
              */
-            public MediaPlayer2.DrmPreparationInfo build() {
+            public @NonNull MediaPlayer2.DrmPreparationInfo build() {
                 return new MediaPlayer2.DrmPreparationInfo(mUUID, mKeySetId, mInitData, mMimeType,
                         mKeyType, mOptionalParameters);
             }
@@ -3597,7 +3598,8 @@
          * @return a {@link DrmPreparationInfo} object to initialize DRM playback, or null to skip
          *         DRM initialization
          */
-        public DrmPreparationInfo onDrmInfo(MediaPlayer2 mp, DataSourceDesc dsd, DrmInfo drmInfo) {
+        public @Nullable DrmPreparationInfo onDrmInfo(@NonNull MediaPlayer2 mp,
+                @NonNull DataSourceDesc dsd, @NonNull DrmInfo drmInfo) {
             return null;
         }
 
@@ -3630,11 +3632,13 @@
          * @param request a {@link MediaDrm.KeyRequest} prepared using the
          *        {@link DrmPreparationInfo} returned from
          *        {@link #onDrmInfo(MediaPlayer2, DataSourceDesc, DrmInfo)}
-         * @return the response to {@code request} (from license server)
+         * @return the response to {@code request} (from license server); returning {@code null} or
+         *         throwing an {@link RuntimeException} from this callback would trigger an
+         *         {@link EventCallback#onError}.
          */
-        public byte[] onDrmKeyRequest(@NonNull MediaPlayer2 mp, @NonNull DataSourceDesc dsd,
-                @NonNull MediaDrm.KeyRequest request) {
-            return null;
+        public @NonNull byte[] onDrmKeyRequest(@NonNull MediaPlayer2 mp,
+                @NonNull DataSourceDesc dsd, @NonNull MediaDrm.KeyRequest request) {
+            return new byte[0];
         }
 
         /**
@@ -4144,7 +4148,7 @@
         /**
          * Returns the PSSH info of the data source for each supported DRM scheme.
          */
-        public Map<UUID, byte[]> getPssh() {
+        public @NonNull Map<UUID, byte[]> getPssh() {
             return mMapPssh;
         }
 
@@ -4153,7 +4157,7 @@
          * It effectively identifies the subset of the source's DRM schemes which
          * are supported by the device too.
          */
-        public List<UUID> getSupportedSchemes() {
+        public @NonNull List<UUID> getSupportedSchemes() {
             return Arrays.asList(mSupportedSchemes);
         }
 
@@ -4276,7 +4280,7 @@
      * Extends MediaDrm.MediaDrmException
      */
     public static final class NoDrmSchemeException extends MediaDrmException {
-        public NoDrmSchemeException(String detailMessage) {
+        public NoDrmSchemeException(@Nullable String detailMessage) {
             super(detailMessage);
         }
     }
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/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 12e02e7..27499c6 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1036,6 +1036,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/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/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 591cf70..a69b412 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -93,6 +93,7 @@
 
         <activity android:name=".UninstallerActivity"
                 android:configChanges="orientation|keyboardHidden|screenSize"
+                android:theme="@style/Theme.AlertDialogActivity.NoActionBar"
                 android:excludeFromRecents="true"
                 android:noHistory="true">
             <intent-filter android:priority="1">
diff --git a/packages/PackageInstaller/res/values/themes.xml b/packages/PackageInstaller/res/values/themes.xml
index 6c8e4c5..b11d28b 100644
--- a/packages/PackageInstaller/res/values/themes.xml
+++ b/packages/PackageInstaller/res/values/themes.xml
@@ -24,4 +24,9 @@
     <style name="Theme.AlertDialogActivity"
             parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
 
+    <style name="Theme.AlertDialogActivity.NoActionBar">
+        <item name="android:windowActionBar">false</item>
+        <item name="android:windowNoTitle">true</item>
+    </style>
+
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index bf97d77..d3dde92 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -185,8 +185,12 @@
 
     <!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_active_battery_level">Active, <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string>
+    <!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level for untethered headset. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_active_battery_level_untethered">Active, L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_battery_level"><xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string>
+    <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level for untethered headset. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_battery_level_untethered">L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
     <!-- Connected devices settings. Message when Bluetooth is connected and active but no battery information, showing remote device status. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_active_no_battery_level">Active</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/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index ab95910..2405666 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -32,6 +32,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
+import com.android.settingslib.Utils;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -830,6 +831,8 @@
         boolean a2dpConnected = true;        // A2DP is connected
         boolean hfpConnected = true;         // HFP is connected
         boolean hearingAidConnected = true;  // Hearing Aid is connected
+        int leftBattery = -1;
+        int rightBattery = -1;
 
         synchronized (mProfileLock) {
             for (LocalBluetoothProfile profile : getProfiles()) {
@@ -877,8 +880,23 @@
         int stringRes = R.string.bluetooth_pairing;
         //when profile is connected, information would be available
         if (profileConnected) {
+            // Update Meta data for connected device
+            if (Boolean.parseBoolean(
+                    mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET))) {
+                try {
+                    leftBattery = Integer.parseInt(
+                            mDevice.getMetadata(BluetoothDevice.METADATA_UNTHETHERED_LEFT_BATTERY));
+                    rightBattery = Integer.parseInt(mDevice.getMetadata(
+                                    BluetoothDevice.METADATA_UNTHETHERED_RIGHT_BATTERY));
+                } catch (NumberFormatException e) {
+                    Log.d(TAG, "Parse error for unthethered battery level.");
+                }
+            }
+
             // Set default string with battery level in device connected situation.
-            if (batteryLevelPercentageString != null) {
+            if (isTwsBatteryAvailable(leftBattery, rightBattery)) {
+                stringRes = R.string.bluetooth_battery_level_untethered;
+            } else if (batteryLevelPercentageString != null) {
                 stringRes = R.string.bluetooth_battery_level;
             }
 
@@ -887,22 +905,36 @@
             //    2. Headset device active with in-calling state.
             //    3. A2DP device active without in-calling state.
             if (a2dpConnected || hfpConnected || hearingAidConnected) {
-                final boolean isOnCall =
-                        com.android.settingslib.Utils.isAudioModeOngoingCall(mContext);
+                final boolean isOnCall = Utils.isAudioModeOngoingCall(mContext);
                 if ((mIsActiveDeviceHearingAid)
                         || (mIsActiveDeviceHeadset && isOnCall)
                         || (mIsActiveDeviceA2dp && !isOnCall)) {
-                    stringRes = (batteryLevelPercentageString != null)
-                            ? R.string.bluetooth_active_battery_level
-                            : R.string.bluetooth_active_no_battery_level;
+                    if (isTwsBatteryAvailable(leftBattery, rightBattery)) {
+                        stringRes = R.string.bluetooth_active_battery_level_untethered;
+                    } else if (batteryLevelPercentageString != null) {
+                        stringRes = R.string.bluetooth_active_battery_level;
+                    } else {
+                        stringRes = R.string.bluetooth_active_no_battery_level;
+                    }
                 }
             }
         }
 
-        return (stringRes != R.string.bluetooth_pairing
-                || getBondState() == BluetoothDevice.BOND_BONDING)
-                ? mContext.getString(stringRes, batteryLevelPercentageString)
-                : null;
+        if (stringRes != R.string.bluetooth_pairing
+                || getBondState() == BluetoothDevice.BOND_BONDING) {
+            if (isTwsBatteryAvailable(leftBattery, rightBattery)) {
+                return mContext.getString(stringRes, Utils.formatPercentage(leftBattery),
+                        Utils.formatPercentage(rightBattery));
+            } else {
+                return mContext.getString(stringRes, batteryLevelPercentageString);
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private boolean isTwsBatteryAvailable(int leftBattery, int rightBattery) {
+        return leftBattery >= 0 && rightBattery >= 0;
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
index bee1b3c..d28b00a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
@@ -276,6 +276,12 @@
             return null;
         }
         ensureMetadataNotStale(context);
+        final ActivityInfo activityInfo = getActivityInfo(context);
+        if (activityInfo == null) {
+            Log.w(TAG, "Cannot find ActivityInfo for " + getDescription());
+            return null;
+        }
+
         int iconResId = mMetaData.getInt(META_DATA_PREFERENCE_ICON);
         // Set the icon
         if (iconResId == 0) {
@@ -283,11 +289,11 @@
             // ICON_URI should be loaded in app UI when need the icon object. Handling IPC at this
             // level is too complex because we don't have a strong threading contract for this class
             if (!mMetaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
-                iconResId = getActivityInfo(context).icon;
+                iconResId = activityInfo.icon;
             }
         }
         if (iconResId != 0) {
-            return Icon.createWithResource(getActivityInfo(context).packageName, iconResId);
+            return Icon.createWithResource(activityInfo.packageName, iconResId);
         } else {
             return null;
         }
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/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 4e5d38a..79b84b9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -41,14 +41,16 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class CachedBluetoothDeviceTest {
-    private final static String DEVICE_NAME = "TestName";
-    private final static String DEVICE_ALIAS = "TestAlias";
-    private final static String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
-    private final static String DEVICE_ALIAS_NEW = "TestAliasNew";
-    private final static short RSSI_1 = 10;
-    private final static short RSSI_2 = 11;
-    private final static boolean JUSTDISCOVERED_1 = true;
-    private final static boolean JUSTDISCOVERED_2 = false;
+    private static final String DEVICE_NAME = "TestName";
+    private static final String DEVICE_ALIAS = "TestAlias";
+    private static final String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
+    private static final String DEVICE_ALIAS_NEW = "TestAliasNew";
+    private static final String TWS_BATTERY_LEFT = "15";
+    private static final String TWS_BATTERY_RIGHT = "25";
+    private static final short RSSI_1 = 10;
+    private static final short RSSI_2 = 11;
+    private static final boolean JUSTDISCOVERED_1 = true;
+    private static final boolean JUSTDISCOVERED_2 = false;
     @Mock
     private LocalBluetoothProfileManager mProfileManager;
     @Mock
@@ -447,6 +449,41 @@
     }
 
     @Test
+    public void getConnectionSummary_trueWirelessActiveDeviceWithBattery_returnActiveWithBattery() {
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET)).thenReturn(
+                "true");
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTHETHERED_LEFT_BATTERY)).thenReturn(
+                TWS_BATTERY_LEFT);
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTHETHERED_RIGHT_BATTERY)).thenReturn(
+                TWS_BATTERY_RIGHT);
+
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "Active, L: 15% battery, R: 25% battery");
+    }
+
+    @Test
+    public void getConnectionSummary_trueWirelessDeviceWithBattery_returnActiveWithBattery() {
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET)).thenReturn(
+                "true");
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTHETHERED_LEFT_BATTERY)).thenReturn(
+                TWS_BATTERY_LEFT);
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTHETHERED_RIGHT_BATTERY)).thenReturn(
+                TWS_BATTERY_RIGHT);
+
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+                "L: 15% battery, R: 25% battery");
+    }
+
+    @Test
     public void getCarConnectionSummary_singleProfileConnectDisconnect() {
         // Test without battery level
         // Set PAN profile to be connected and test connection state summary
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d639e5e..f0399c5 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" />
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/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 0fed96e..27d2bcd 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -18,8 +18,6 @@
     <declare-styleable name="KeyButtonView">
         <!-- key code to send when pressed; if absent or 0, no key is sent -->
         <attr name="keyCode" format="integer" />
-        <!-- does this button generate longpress / repeat events? -->
-        <attr name="keyRepeat" format="boolean" />
         <!-- Should this button play sound effects, default true -->
         <attr name="playSound" format="boolean" />
         <attr name="android:contentDescription" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index da43391..c6c2763 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"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will start capturing the played audio and everything on your screen including notifications, passwords, photos, messages and payment information.</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">Allow <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> to record or cast your screen and played audio?</string>
 
     <!-- Media projection permission dialog permanent grant check box. [CHAR LIMIT=NONE] -->
     <string name="media_projection_remember_text">Don\'t show again</string>
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..e8b346e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -354,6 +354,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));
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 1cc6b87..461e79c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -238,6 +238,13 @@
         mBubbleContainer.bringToFront();
     }
 
+    /**
+     * Handle config changes.
+     */
+    public void onConfigChanged() {
+        mExpandedBubble.expandedView.updateHeaderColor();
+    }
+
     @Override
     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
         getBoundsOnScreen(outRect);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index d06feed..2db7306 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -61,7 +61,9 @@
 
     @Override
     public void onDestroy() {
-        mPluginManager.removePluginListener(this);
+        if (mPluginManager != null) {
+            mPluginManager.removePluginListener(this);
+        }
         super.onDestroy();
         mDozeMachine = null;
     }
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 7e330e9..c4b41d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -122,6 +122,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
@@ -215,7 +216,6 @@
 import com.android.systemui.statusbar.policy.ExtensionController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -533,8 +533,7 @@
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
     protected UserSwitcherController mUserSwitcherController;
     private NetworkController mNetworkController;
-    private KeyguardMonitorImpl mKeyguardMonitor
-            = (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
+    private KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
     private BatteryController mBatteryController;
     protected boolean mPanelExpanded;
     private UiModeManager mUiModeManager;
@@ -1057,8 +1056,21 @@
         mNotificationShelf.setOnActivatedListener(mPresenter);
         mRemoteInputManager.getController().addCallback(mStatusBarWindowController);
 
-        mNotificationActivityStarter = new StatusBarNotificationActivityStarter(
-                mContext, mNotificationPanel, mPresenter, mHeadsUpManager, mActivityLaunchAnimator);
+        final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback =
+                (StatusBarRemoteInputCallback) Dependency.get(
+                        NotificationRemoteInputManager.Callback.class);
+        final ShadeController shadeController = Dependency.get(ShadeController.class);
+        final ActivityStarter activityStarter = Dependency.get(ActivityStarter.class);
+
+        mNotificationActivityStarter = new StatusBarNotificationActivityStarter(mContext,
+                mCommandQueue, mAssistManager, mNotificationPanel, mPresenter, mEntryManager,
+                mHeadsUpManager, activityStarter, mActivityLaunchAnimator,
+                mBarService, mStatusBarStateController, mKeyguardManager, mDreamManager,
+                mRemoteInputManager, mStatusBarRemoteInputCallback, mGroupManager,
+                mLockscreenUserManager, shadeController, mKeyguardMonitor,
+                mNotificationInterruptionStateProvider, mMetricsLogger,
+                new LockPatternUtils(mContext));
+
         mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
 
         mEntryManager.setRowBinder(rowBinder);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 74c0018..7e45507 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import static com.android.systemui.Dependency.MAIN_HANDLER;
-import static com.android.systemui.SysUiServiceProvider.getComponent;
 import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions;
 
 import android.app.ActivityManager;
@@ -32,9 +31,7 @@
 import android.os.AsyncTask;
 import android.os.Looper;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
@@ -78,27 +75,18 @@
     private static final String TAG = "NotificationClickHandler";
     protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private final AssistManager mAssistManager = Dependency.get(AssistManager.class);
-    private final NotificationGroupManager mGroupManager =
-            Dependency.get(NotificationGroupManager.class);
-    private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback =
-            (StatusBarRemoteInputCallback) Dependency.get(
-                    NotificationRemoteInputManager.Callback.class);
-    private final NotificationRemoteInputManager mRemoteInputManager =
-            Dependency.get(NotificationRemoteInputManager.class);
-    private final NotificationLockscreenUserManager mLockscreenUserManager =
-            Dependency.get(NotificationLockscreenUserManager.class);
-    private final ShadeController mShadeController = Dependency.get(ShadeController.class);
-    private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
-    private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
-    private final NotificationEntryManager mEntryManager =
-            Dependency.get(NotificationEntryManager.class);
-    private final StatusBarStateController mStatusBarStateController =
-            Dependency.get(StatusBarStateController.class);
-    private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider =
-            Dependency.get(NotificationInterruptionStateProvider.class);
-    private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
-
+    private final AssistManager mAssistManager;
+    private final NotificationGroupManager mGroupManager;
+    private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback;
+    private final NotificationRemoteInputManager mRemoteInputManager;
+    private final NotificationLockscreenUserManager mLockscreenUserManager;
+    private final ShadeController mShadeController;
+    private final KeyguardMonitor mKeyguardMonitor;
+    private final ActivityStarter mActivityStarter;
+    private final NotificationEntryManager mEntryManager;
+    private final StatusBarStateController mStatusBarStateController;
+    private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+    private final MetricsLogger mMetricsLogger;
     private final Context mContext;
     private final NotificationPanelView mNotificationPanel;
     private final NotificationPresenter mPresenter;
@@ -113,29 +101,55 @@
     private boolean mIsCollapsingToShowActivityOverLockscreen;
 
     public StatusBarNotificationActivityStarter(Context context,
+            CommandQueue commandQueue,
+            AssistManager assistManager,
             NotificationPanelView panel,
             NotificationPresenter presenter,
+            NotificationEntryManager entryManager,
             HeadsUpManagerPhone headsUpManager,
-            ActivityLaunchAnimator activityLaunchAnimator) {
+            ActivityStarter activityStarter,
+            ActivityLaunchAnimator activityLaunchAnimator,
+            IStatusBarService statusBarService,
+            StatusBarStateController statusBarStateController,
+            KeyguardManager keyguardManager,
+            IDreamManager dreamManager,
+            NotificationRemoteInputManager remoteInputManager,
+            StatusBarRemoteInputCallback remoteInputCallback,
+            NotificationGroupManager groupManager,
+            NotificationLockscreenUserManager lockscreenUserManager,
+            ShadeController shadeController,
+            KeyguardMonitor keyguardMonitor,
+            NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+            MetricsLogger metricsLogger,
+            LockPatternUtils lockPatternUtils) {
         mContext = context;
         mNotificationPanel = panel;
         mPresenter = presenter;
-        mLockPatternUtils = new LockPatternUtils(context);
         mHeadsUpManager = headsUpManager;
-        mKeyguardManager = context.getSystemService(KeyguardManager.class);
         mActivityLaunchAnimator = activityLaunchAnimator;
-        mBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-        mCommandQueue = getComponent(context, CommandQueue.class);
-        mDreamManager = IDreamManager.Stub.asInterface(
-                ServiceManager.checkService(DreamService.DREAM_SERVICE));
-
+        mBarService = statusBarService;
+        mCommandQueue = commandQueue;
+        mKeyguardManager = keyguardManager;
+        mDreamManager = dreamManager;
+        mRemoteInputManager = remoteInputManager;
+        mLockscreenUserManager = lockscreenUserManager;
+        mShadeController = shadeController;
+        mKeyguardMonitor = keyguardMonitor;
+        mActivityStarter = activityStarter;
+        mEntryManager = entryManager;
+        mStatusBarStateController = statusBarStateController;
+        mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+        mMetricsLogger = metricsLogger;
+        mAssistManager = assistManager;
+        mGroupManager = groupManager;
+        mLockPatternUtils = lockPatternUtils;
         mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
             public void onPendingEntryAdded(NotificationEntry entry) {
                 handleFullScreenIntent(entry);
             }
         });
+        mStatusBarRemoteInputCallback = remoteInputCallback;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 024404d..1e05983 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -66,7 +66,6 @@
     private int mTouchDownX;
     private int mTouchDownY;
     private boolean mIsVertical;
-    private boolean mSupportsLongpress = true;
     private AudioManager mAudioManager;
     private boolean mGestureAborted;
     private boolean mLongClicked;
@@ -83,7 +82,7 @@
                     // Just an old-fashioned ImageView
                     performLongClick();
                     mLongClicked = true;
-                } else if (mSupportsLongpress) {
+                } else {
                     sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
                     sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
                     mLongClicked = true;
@@ -104,7 +103,6 @@
 
         mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, KEYCODE_UNKNOWN);
 
-        mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
         mPlaySounds = a.getBoolean(R.styleable.KeyButtonView_playSound, true);
 
         TypedValue value = new TypedValue();
@@ -166,7 +164,7 @@
         super.onInitializeAccessibilityNodeInfo(info);
         if (mCode != KEYCODE_UNKNOWN) {
             info.addAction(new AccessibilityNodeInfo.AccessibilityAction(ACTION_CLICK, null));
-            if (mSupportsLongpress || isLongClickable()) {
+            if (isLongClickable()) {
                 info.addAction(
                         new AccessibilityNodeInfo.AccessibilityAction(ACTION_LONG_CLICK, null));
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index aba2377..01498e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -29,6 +29,25 @@
     long getKeyguardFadingAwayDelay();
     long calculateGoingToFullShadeDelay();
 
+    default boolean isDeviceInteractive() {
+        return false;
+    }
+
+    default void setLaunchTransitionFadingAway(boolean b) {
+    }
+
+    default void notifyKeyguardGoingAway(boolean b) {
+    }
+
+    default void notifyKeyguardFadingAway(long delay, long fadeoutDuration) {
+    }
+
+    default void notifyKeyguardDoneFading() {
+    }
+
+    default void notifyKeyguardState(boolean showing, boolean methodSecure, boolean occluded) {
+    }
+
     interface Callback {
         void onKeyguardShowingChanged();
     }
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/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 1ded6c9..cb5612d 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
@@ -75,7 +75,6 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.appops.AppOpsControllerImpl;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.classifier.FalsingManager;
@@ -112,7 +111,6 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 import org.junit.Before;
@@ -161,7 +159,6 @@
     @Mock private NotificationPresenter mNotificationPresenter;
     @Mock
     private NotificationEntryListener mEntryListener;
-    @Mock private BubbleController mBubbleController;
     @Mock
     private NotificationFilter mNotificationFilter;
     @Mock
@@ -192,8 +189,8 @@
                 mViewHierarchyManager);
         mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
         mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
-        mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class));
-        mDependency.injectTestDependency(AppOpsController.class, mock(AppOpsControllerImpl.class));
+        mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitor.class));
+        mDependency.injectTestDependency(AppOpsController.class, mock(AppOpsController.class));
         mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController);
         mDependency.injectTestDependency(DeviceProvisionedController.class,
                 mDeviceProvisionedController);
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index f106228..c5c4b5a 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7120,6 +7120,10 @@
     // 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;
+
     // ---- 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..c917268 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;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 9612346..dd3efa0 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -156,6 +156,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.
      */
@@ -889,8 +890,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/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/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index a400cc3..3d918fc 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -83,6 +83,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
 import android.util.SparseLongArray;
 import android.util.StatsLog;
 import android.util.TimeUtils;
@@ -195,6 +196,7 @@
     private final Injector mInjector;
     int mBroadcastRefCount = 0;
     PowerManager.WakeLock mWakeLock;
+    SparseIntArray mAlarmsPerUid = new SparseIntArray();
     ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
     ArrayList<InFlight> mInFlight = new ArrayList<>();
     private final ArrayList<AlarmManagerInternal.InFlightListener> mInFlightListeners =
@@ -393,6 +395,8 @@
         @VisibleForTesting
         static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
         @VisibleForTesting
+        static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid";
+        @VisibleForTesting
         static final String KEY_APP_STANDBY_QUOTAS_ENABLED = "app_standby_quotas_enabled";
         private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window";
         @VisibleForTesting
@@ -420,6 +424,7 @@
         private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
         private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
         private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
+        private static final int DEFAULT_MAX_ALARMS_PER_UID = 500;
         private static final boolean DEFAULT_APP_STANDBY_QUOTAS_ENABLED = true;
         private static final long DEFAULT_APP_STANDBY_WINDOW = 60 * 60 * 1000;  // 1 hr
         /**
@@ -461,6 +466,8 @@
 
         // Direct alarm listener callback timeout
         public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
+        public int MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
+
         public boolean APP_STANDBY_QUOTAS_ENABLED = DEFAULT_APP_STANDBY_QUOTAS_ENABLED;
 
         public long APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
@@ -549,6 +556,15 @@
                     APP_STANDBY_QUOTAS[i] = mParser.getInt(KEYS_APP_STANDBY_QUOTAS[i],
                             Math.min(APP_STANDBY_QUOTAS[i - 1], DEFAULT_APP_STANDBY_QUOTAS[i]));
                 }
+
+                MAX_ALARMS_PER_UID = mParser.getInt(KEY_MAX_ALARMS_PER_UID,
+                        DEFAULT_MAX_ALARMS_PER_UID);
+                if (MAX_ALARMS_PER_UID < DEFAULT_MAX_ALARMS_PER_UID) {
+                    Slog.w(TAG, "Cannot set " + KEY_MAX_ALARMS_PER_UID + " lower than "
+                            + DEFAULT_MAX_ALARMS_PER_UID);
+                    MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
+                }
+
                 updateAllowWhileIdleWhitelistDurationLocked();
             }
         }
@@ -590,6 +606,9 @@
             TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
             pw.println();
 
+            pw.print(KEY_MAX_ALARMS_PER_UID); pw.print("=");
+            pw.println(MAX_ALARMS_PER_UID);
+
             for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) {
                 pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("=");
                 TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw);
@@ -671,12 +690,6 @@
 
         final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
 
-        Batch() {
-            start = 0;
-            end = Long.MAX_VALUE;
-            flags = 0;
-        }
-
         Batch(Alarm seed) {
             start = seed.whenElapsed;
             end = clampPositive(seed.maxWhenElapsed);
@@ -728,11 +741,16 @@
             return newStart;
         }
 
+        /**
+         * Remove an alarm from this batch.
+         * <p> <b> Should be used only while re-ordering the alarm within the service </b> as it
+         * does not update {@link #mAlarmsPerUid}
+         */
         boolean remove(Alarm alarm) {
-            return remove(a -> (a == alarm));
+            return remove(a -> (a == alarm), true);
         }
 
-        boolean remove(Predicate<Alarm> predicate) {
+        boolean remove(Predicate<Alarm> predicate, boolean reOrdering) {
             boolean didRemove = false;
             long newStart = 0;  // recalculate endpoints as we go
             long newEnd = Long.MAX_VALUE;
@@ -741,6 +759,9 @@
                 Alarm alarm = alarms.get(i);
                 if (predicate.test(alarm)) {
                     alarms.remove(i);
+                    if (!reOrdering) {
+                        decrementAlarmCount(alarm.uid);
+                    }
                     didRemove = true;
                     if (alarm.alarmClock != null) {
                         mNextAlarmClockMayChange = true;
@@ -1734,6 +1755,15 @@
                         + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
                         + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
             }
+            if (mAlarmsPerUid.get(callingUid, 0) >= mConstants.MAX_ALARMS_PER_UID) {
+                final String errorMsg =
+                        "Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID
+                                + " reached for uid: " + UserHandle.formatUid(callingUid)
+                                + ", callingPackage: " + callingPackage;
+                // STOPSHIP (b/128866264): Just to catch breakages. Remove before final release.
+                Slog.wtf(TAG, errorMsg);
+                throw new UnsupportedOperationException(errorMsg);
+            }
             setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
                     interval, operation, directReceiver, listenerTag, flags, true, workSource,
                     alarmClock, callingUid, callingPackage);
@@ -1756,6 +1786,7 @@
         } catch (RemoteException e) {
         }
         removeLocked(operation, directReceiver);
+        incrementAlarmCount(a.uid);
         setImplLocked(a, false, doValidate);
     }
 
@@ -2197,7 +2228,6 @@
                             ? sdf.format(new Date(nowRTC - (nowELAPSED - time)))
                             : "-");
                 } while (i != mNextTickHistory);
-                pw.println();
             }
 
             SystemServiceManager ssm = LocalServices.getService(SystemServiceManager.class);
@@ -2305,6 +2335,18 @@
             if (!blocked) {
                 pw.println("    none");
             }
+            pw.println();
+            pw.print("  Pending alarms per uid: [");
+            for (int i = 0; i < mAlarmsPerUid.size(); i++) {
+                if (i > 0) {
+                    pw.print(", ");
+                }
+                UserHandle.formatUid(pw, mAlarmsPerUid.keyAt(i));
+                pw.print(":");
+                pw.print(mAlarmsPerUid.valueAt(i));
+            }
+            pw.println("]");
+            pw.println();
 
             mAppWakeupHistory.dump(pw, "  ", nowELAPSED);
 
@@ -3046,7 +3088,7 @@
         final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(operation, directReceiver);
         for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
             Batch b = mAlarmBatches.get(i);
-            didRemove |= b.remove(whichAlarms);
+            didRemove |= b.remove(whichAlarms, false);
             if (b.size() == 0) {
                 mAlarmBatches.remove(i);
             }
@@ -3098,7 +3140,7 @@
         final Predicate<Alarm> whichAlarms = (Alarm a) -> a.uid == uid;
         for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
             Batch b = mAlarmBatches.get(i);
-            didRemove |= b.remove(whichAlarms);
+            didRemove |= b.remove(whichAlarms, false);
             if (b.size() == 0) {
                 mAlarmBatches.remove(i);
             }
@@ -3145,7 +3187,7 @@
         final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
         for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
             Batch b = mAlarmBatches.get(i);
-            didRemove |= b.remove(whichAlarms);
+            didRemove |= b.remove(whichAlarms, false);
             if (b.size() == 0) {
                 mAlarmBatches.remove(i);
             }
@@ -3183,6 +3225,7 @@
         }
     }
 
+    // Only called for ephemeral apps
     void removeForStoppedLocked(final int uid) {
         if (uid == Process.SYSTEM_UID) {
             Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for UID=" + uid);
@@ -3200,7 +3243,7 @@
         };
         for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
             Batch b = mAlarmBatches.get(i);
-            didRemove |= b.remove(whichAlarms);
+            didRemove |= b.remove(whichAlarms, false);
             if (b.size() == 0) {
                 mAlarmBatches.remove(i);
             }
@@ -3237,7 +3280,7 @@
                 (Alarm a) -> UserHandle.getUserId(a.creatorUid) == userHandle;
         for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
             Batch b = mAlarmBatches.get(i);
-            didRemove |= b.remove(whichAlarms);
+            didRemove |= b.remove(whichAlarms, false);
             if (b.size() == 0) {
                 mAlarmBatches.remove(i);
             }
@@ -3407,8 +3450,7 @@
         return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
     }
 
-    boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
-            final long nowRTC) {
+    boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) {
         boolean hasWakeup = false;
         // batches are temporally sorted, so we need only pull from the
         // start of the list until we either empty it or hit a batch
@@ -3984,7 +4026,7 @@
                         }
 
                         mLastTrigger = nowELAPSED;
-                        boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
+                        boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED);
                         if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
                             // if there are no wakeup alarms and the screen is off, we can
                             // delay what we have so far until the future.
@@ -4108,9 +4150,8 @@
                 case ALARM_EVENT: {
                     ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
                     synchronized (mLock) {
-                        final long nowRTC = mInjector.getCurrentTimeMillis();
                         final long nowELAPSED = mInjector.getElapsedRealtime();
-                        triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
+                        triggerAlarmsLocked(triggerList, nowELAPSED);
                         updateNextAlarmClockLocked();
                     }
 
@@ -4719,7 +4760,7 @@
                 mAppWakeupHistory.recordAlarmForPackage(alarm.sourcePackage,
                         UserHandle.getUserId(alarm.creatorUid), nowELAPSED);
             }
-
+            decrementAlarmCount(alarm.uid);
             final BroadcastStats bs = inflight.mBroadcastStats;
             bs.count++;
             if (bs.nesting == 0) {
@@ -4747,6 +4788,27 @@
         }
     }
 
+    private void incrementAlarmCount(int uid) {
+        final int uidIndex = mAlarmsPerUid.indexOfKey(uid);
+        if (uidIndex >= 0) {
+            mAlarmsPerUid.setValueAt(uidIndex, mAlarmsPerUid.valueAt(uidIndex) + 1);
+        } else {
+            mAlarmsPerUid.put(uid, 1);
+        }
+    }
+
+    private void decrementAlarmCount(int uid) {
+        final int uidIndex = mAlarmsPerUid.indexOfKey(uid);
+        if (uidIndex >= 0) {
+            final int newCount = mAlarmsPerUid.valueAt(uidIndex) - 1;
+            if (newCount > 0) {
+                mAlarmsPerUid.setValueAt(uidIndex, newCount);
+            } else {
+                mAlarmsPerUid.removeAt(uidIndex);
+            }
+        }
+    }
+
     private class ShellCmd extends ShellCommand {
 
         IAlarmManager getBinderService() {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 3ab3c34..833faa6 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -115,7 +115,8 @@
  *
  * Test: atest com.android.server.DeviceIdleControllerTest
  *
- * Current idling state machine (as of Android 9 Pie). This can be visualized using Graphviz:
+ * Current idling state machine (as of Android Q). This can be visualized using Graphviz:
+   <pre>
 
    digraph {
      subgraph deep {
@@ -259,6 +260,7 @@
        ]
      }
    }
+   </pre>
  */
 public class DeviceIdleController extends SystemService
         implements AnyMotionDetector.DeviceIdleCallback {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 7fab2b96..6ef5b54 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -102,6 +102,7 @@
 import com.android.server.location.GeofenceProxy;
 import com.android.server.location.GnssBatchingProvider;
 import com.android.server.location.GnssLocationProvider;
+import com.android.server.location.GnssMeasurementCorrectionsProvider;
 import com.android.server.location.GnssMeasurementsProvider;
 import com.android.server.location.GnssNavigationMessageProvider;
 import com.android.server.location.GnssStatusListenerHelper;
@@ -195,6 +196,7 @@
     private PassiveProvider mPassiveProvider;  // track passive provider for special cases
     private LocationBlacklist mBlacklist;
     private GnssMeasurementsProvider mGnssMeasurementsProvider;
+    private GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider;
     private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
     @GuardedBy("mLock")
     private String mLocationControllerExtraPackage;
@@ -309,9 +311,13 @@
                 AppOpsManager.WATCH_FOREGROUND_CHANGES,
                 new AppOpsManager.OnOpChangedInternalListener() {
                     public void onOpChanged(int op, String packageName) {
-                        synchronized (mLock) {
-                            onAppOpChangedLocked();
-                        }
+                        // onOpChanged invoked on ui thread, move to our thread to reduce risk of
+                        // blocking ui thread
+                        mHandler.post(() -> {
+                            synchronized (mLock) {
+                                onAppOpChangedLocked();
+                            }
+                        });
                     }
                 });
         mPackageManager.addOnPermissionsChangeListener(
@@ -757,6 +763,8 @@
             mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
             mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
             mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
+            mGnssMeasurementCorrectionsProvider =
+                    gnssProvider.getGnssMeasurementCorrectionsProvider();
             mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
             mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
         }
@@ -2921,22 +2929,28 @@
         mContext.enforceCallingPermission(
                 android.Manifest.permission.LOCATION_HARDWARE,
                 "Location Hardware permission not granted to inject GNSS measurement corrections.");
-        if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
+        if (!hasGnssPermissions(packageName)) {
             Slog.e(TAG, "Can not inject GNSS corrections due to no permission.");
-        } else {
-            mGnssMeasurementsProvider.injectGnssMeasurementCorrections(measurementCorrections);
+            return;
         }
+        if (mGnssMeasurementCorrectionsProvider == null) {
+            Slog.e(TAG, "Can not inject GNSS corrections. GNSS measurement corrections provider "
+                    + "not available.");
+            return;
+        }
+        mGnssMeasurementCorrectionsProvider.injectGnssMeasurementCorrections(
+                measurementCorrections);
     }
 
     @Override
     public int getGnssCapabilities(String packageName) {
         mContext.enforceCallingPermission(
                 android.Manifest.permission.LOCATION_HARDWARE,
-                "Location Hardware permission not granted to obrain GNSS chipset capabilities.");
-        if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
+                "Location Hardware permission not granted to obtain GNSS chipset capabilities.");
+        if (!hasGnssPermissions(packageName) || mGnssMeasurementCorrectionsProvider == null) {
             return -1;
         }
-        return mGnssMeasurementsProvider.getGnssCapabilities();
+        return mGnssMeasurementCorrectionsProvider.getCapabilities();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 19b0bf7..8cb1ec7 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -208,6 +208,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;
 
@@ -797,7 +804,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 +844,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);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index d6fdbe3..26896f5 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -625,6 +625,11 @@
                 r.callingPackage = callingPackage;
                 r.callerUid = Binder.getCallingUid();
                 r.callerPid = Binder.getCallingPid();
+                if (r.subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && r.subId != subId) {
+                    throw new IllegalArgumentException(
+                            "PhoneStateListener cannot concurrently listen on multiple " +
+                                    "subscriptions. Previously registered on subId: " + r.subId);
+                }
                 // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
                 // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
                 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
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/AssistDataRequester.java b/services/core/java/com/android/server/am/AssistDataRequester.java
index 09df7e20..d8d6528 100644
--- a/services/core/java/com/android/server/am/AssistDataRequester.java
+++ b/services/core/java/com/android/server/am/AssistDataRequester.java
@@ -24,6 +24,7 @@
 
 import android.app.ActivityTaskManager;
 import android.app.AppOpsManager;
+import android.app.IActivityTaskManager;
 import android.app.IAssistDataReceiver;
 import android.content.Context;
 import android.graphics.Bitmap;
@@ -33,6 +34,7 @@
 import android.view.IWindowManager;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 
 import java.io.PrintWriter;
@@ -50,6 +52,8 @@
     public static final String KEY_RECEIVER_EXTRA_INDEX = "index";
 
     private IWindowManager mWindowManager;
+    @VisibleForTesting
+    public IActivityTaskManager mActivityTaskManager;
     private Context mContext;
     private AppOpsManager mAppOpsManager;
 
@@ -128,6 +132,7 @@
         mCallbacks = callbacks;
         mCallbacksLock = callbacksLock;
         mWindowManager = windowManager;
+        mActivityTaskManager = ActivityTaskManager.getService();
         mContext = context;
         mAppOpsManager = appOpsManager;
         mRequestStructureAppOps = requestStructureAppOps;
@@ -195,8 +200,7 @@
         // Ensure that the current activity supports assist data
         boolean isAssistDataAllowed = false;
         try {
-            isAssistDataAllowed =
-                    ActivityTaskManager.getService().isAssistDataAllowedOnCurrentActivity();
+            isAssistDataAllowed = mActivityTaskManager.isAssistDataAllowedOnCurrentActivity();
         } catch (RemoteException e) {
             // Should never happen
         }
@@ -222,9 +226,9 @@
                         receiverExtras.putInt(KEY_RECEIVER_EXTRA_INDEX, i);
                         receiverExtras.putInt(KEY_RECEIVER_EXTRA_COUNT, numActivities);
                         boolean result = requestAutofillData
-                                ? ActivityTaskManager.getService().requestAutofillData(this,
+                                ? mActivityTaskManager.requestAutofillData(this,
                                         receiverExtras, topActivity, 0 /* flags */)
-                                : ActivityTaskManager.getService().requestAssistContextExtras(
+                                : mActivityTaskManager.requestAssistContextExtras(
                                         ASSIST_CONTEXT_FULL, this, receiverExtras, topActivity,
                                         /* focused= */ i == 0, /* newSessionId= */ i == 0);
                         if (result) {
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/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 029c3fb..07c9cca 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -389,14 +389,14 @@
      * Step from {@link UserState#STATE_RUNNING_LOCKED} to
      * {@link UserState#STATE_RUNNING_UNLOCKING}.
      */
-    private void finishUserUnlocking(final UserState uss) {
+    private boolean finishUserUnlocking(final UserState uss) {
         final int userId = uss.mHandle.getIdentifier();
         // Only keep marching forward if user is actually unlocked
-        if (!StorageManager.isUserKeyUnlocked(userId)) return;
+        if (!StorageManager.isUserKeyUnlocked(userId)) return false;
         synchronized (mLock) {
             // Do not proceed if unexpected state or a stale user
             if (mStartedUsers.get(userId) != uss || uss.state != STATE_RUNNING_LOCKED) {
-                return;
+                return false;
             }
         }
         uss.mUnlockProgress.start();
@@ -427,6 +427,7 @@
             mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
                     .sendToTarget();
         });
+        return true;
     }
 
     /**
@@ -1209,7 +1210,10 @@
             return false;
         }
 
-        finishUserUnlocking(uss);
+        if (!finishUserUnlocking(uss)) {
+            notifyFinished(userId, listener);
+            return false;
+        }
 
         // We just unlocked a user, so let's now attempt to unlock any
         // managed profiles under that user.
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 4e0380d..42a7a5c 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -113,6 +113,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 +290,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 +302,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;
         }
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/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/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index aca02bf..c820841 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -30,6 +30,9 @@
 import android.net.NetworkPolicyManager;
 import android.net.NetworkRequest;
 import android.net.TrafficStats;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.os.UserHandle;
 import android.text.format.DateUtils;
 import android.util.ArraySet;
@@ -85,8 +88,14 @@
     @GuardedBy("mLock")
     private final ArraySet<Network> mAvailableNetworks = new ArraySet<>();
 
+    private static final int MSG_DATA_SAVER_TOGGLED = 0;
+    private static final int MSG_UID_RULES_CHANGES = 1;
+
+    private final Handler mHandler;
+
     public ConnectivityController(JobSchedulerService service) {
         super(service);
+        mHandler = new CcHandler(mContext.getMainLooper());
 
         mConnManager = mContext.getSystemService(ConnectivityManager.class);
         mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
@@ -545,11 +554,39 @@
 
     private final INetworkPolicyListener mNetPolicyListener = new NetworkPolicyManager.Listener() {
         @Override
+        public void onRestrictBackgroundChanged(boolean restrictBackground) {
+            if (DEBUG) {
+                Slog.v(TAG, "onRestrictBackgroundChanged: " + restrictBackground);
+            }
+            mHandler.obtainMessage(MSG_DATA_SAVER_TOGGLED).sendToTarget();
+        }
+
+        @Override
         public void onUidRulesChanged(int uid, int uidRules) {
             if (DEBUG) {
                 Slog.v(TAG, "onUidRulesChanged: " + uid);
             }
-            updateTrackedJobs(uid, null);
+            mHandler.obtainMessage(MSG_UID_RULES_CHANGES, uid, 0).sendToTarget();
+        }
+    };
+
+    private class CcHandler extends Handler {
+        CcHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            synchronized (mLock) {
+                switch (msg.what) {
+                    case MSG_DATA_SAVER_TOGGLED:
+                        updateTrackedJobs(-1, null);
+                        break;
+                    case MSG_UID_RULES_CHANGES:
+                        updateTrackedJobs(msg.arg1, null);
+                        break;
+                }
+            }
         }
     };
 
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index c173d66..8249999 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -166,9 +166,15 @@
     private static final int GPS_CAPABILITY_MSA = 0x0000004;
     private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
     private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
-    private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
+
+    // The following three capability flags are removed in IGnssCallback.hal@2.0 and their values
+    // are marked reserved and not reused in 2.0 to avoid confusion with prior versions.
+    public static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
     public static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
-    private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
+    public static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
+
+    private static final int GPS_CAPABILITY_LOW_POWER_MODE = 0x0000100;
+    private static final int GPS_CAPABILITY_SATELLITE_BLACKLIST = 0x0000200;
 
     // The AGPS SUPL mode
     private static final int AGPS_SUPL_MODE_MSA = 0x02;
@@ -333,7 +339,7 @@
     private boolean mStarted;
 
     // capabilities of the GPS engine
-    private int mEngineCapabilities;
+    private volatile int mEngineCapabilities;
 
     // true if XTRA is supported
     private boolean mSupportsXtra;
@@ -372,6 +378,7 @@
     private final LocationExtras mLocationExtras = new LocationExtras();
     private final GnssStatusListenerHelper mGnssStatusListenerHelper;
     private final GnssMeasurementsProvider mGnssMeasurementsProvider;
+    private final GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider;
     private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
     private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
     private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
@@ -437,6 +444,10 @@
         return mGnssMeasurementsProvider;
     }
 
+    public GnssMeasurementCorrectionsProvider getGnssMeasurementCorrectionsProvider() {
+        return mGnssMeasurementCorrectionsProvider;
+    }
+
     public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
         return mGnssNavigationMessageProvider;
     }
@@ -627,6 +638,8 @@
             }
         };
 
+        mGnssMeasurementCorrectionsProvider = new GnssMeasurementCorrectionsProvider(mHandler);
+
         mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mContext, mHandler) {
             @Override
             protected boolean isGpsEnabled() {
@@ -1258,6 +1271,10 @@
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
     }
 
+    public int getGnssCapabilities() {
+        return mEngineCapabilities;
+    }
+
     private boolean hasCapability(int capability) {
         return ((mEngineCapabilities & capability) != 0);
     }
@@ -1467,22 +1484,27 @@
     }
 
     @NativeEntryPoint
-    private void setEngineCapabilities(final int capabilities) {
+    private void setEngineCapabilities(final int capabilities, boolean hasSubHalCapabilityFlags) {
         // send to handler thread for fast native return, and in-order handling
-        mHandler.post(
-                () -> {
-                    mEngineCapabilities = capabilities;
+        mHandler.post(() -> {
+            mEngineCapabilities = capabilities;
 
-                    if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
-                        mNtpTimeHelper.enablePeriodicTimeInjection();
-                        requestUtcTime();
-                    }
+            if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
+                mNtpTimeHelper.enablePeriodicTimeInjection();
+                requestUtcTime();
+            }
 
-                    mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities);
-                    mGnssNavigationMessageProvider.onCapabilitiesUpdated(
-                            hasCapability(GPS_CAPABILITY_NAV_MESSAGES));
-                    restartRequests();
-                });
+            mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities, hasSubHalCapabilityFlags);
+            mGnssNavigationMessageProvider.onCapabilitiesUpdated(capabilities,
+                    hasSubHalCapabilityFlags);
+            restartRequests();
+        });
+    }
+
+    @NativeEntryPoint
+    private void setMeasurementCorrectionsCapabilities(final int capabilities) {
+        mHandler.post(() -> mGnssMeasurementCorrectionsProvider.onCapabilitiesUpdated(
+                capabilities));
     }
 
     private void restartRequests() {
@@ -2122,7 +2144,23 @@
         if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
         if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
         if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
+        if (hasCapability(GPS_CAPABILITY_LOW_POWER_MODE)) s.append("LOW_POWER_MODE ");
+        if (hasCapability(GPS_CAPABILITY_SATELLITE_BLACKLIST)) s.append("SATELLITE_BLACKLIST ");
         s.append(")\n");
+        if (mGnssGeofenceProvider.isHardwareGeofenceSupported()) {
+            s.append("  hasSubHal=GEOFENCING\n");
+        }
+        if (mGnssMeasurementsProvider.isAvailableInPlatform()) {
+            s.append("  hasSubHal=MEASUREMENTS\n");
+        }
+        if (mGnssNavigationMessageProvider.isAvailableInPlatform()) {
+            s.append("  hasSubHal=NAV_MESSAGES\n");
+        }
+        if (mGnssMeasurementCorrectionsProvider.isAvailableInPlatform()) {
+            s.append("  hasSubHal=MEASUREMENT_CORRECTIONS [");
+            s.append(mGnssMeasurementCorrectionsProvider.toStringCapabilities());
+            s.append("]\n");
+        }
         s.append(mGnssMetrics.dumpGnssMetricsAsText());
         s.append("  native internal state: ").append(native_get_internal_state());
         s.append("\n");
diff --git a/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java
new file mode 100644
index 0000000..2162787
--- /dev/null
+++ b/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java
@@ -0,0 +1,149 @@
+/*
+ * 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.location;
+
+import android.location.GnssMeasurementCorrections;
+import android.os.Handler;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Manages GNSS measurement corrections.
+ *
+ * <p>Implements the framework side of the GNSS HAL interfaces {@code IMeasurementCorrections.hal}
+ * and {@code IMeasurementCorrectionsCallback.hal).
+ *
+ * @hide
+ */
+public class GnssMeasurementCorrectionsProvider {
+    private static final String TAG = "GnssMeasurementCorrectionsProvider";
+
+    // These must match with the Capabilities enum in IMeasurementCorrectionsCallback.hal.
+    private static final int CAPABILITY_LOS_SATS = 0x0000001;
+    private static final int CAPABILITY_EXCESS_PATH_LENGTH = 0x0000002;
+    private static final int CAPABILITY_REFLECTING_PLANE = 0x0000004;
+
+    private static final int INVALID_CAPABILITIES = 1 << 31;
+
+    private final Handler mHandler;
+    private final GnssMeasurementCorrectionsProviderNative mNative;
+    private volatile int mCapabilities = INVALID_CAPABILITIES;
+
+    GnssMeasurementCorrectionsProvider(Handler handler) {
+        this(handler, new GnssMeasurementCorrectionsProviderNative());
+    }
+
+    @VisibleForTesting
+    GnssMeasurementCorrectionsProvider(Handler handler,
+            GnssMeasurementCorrectionsProviderNative aNative) {
+        mHandler = handler;
+        mNative = aNative;
+    }
+
+    /**
+     * Returns {@code true} if the GNSS HAL implementation supports measurement corrections.
+     */
+    public boolean isAvailableInPlatform() {
+        return mNative.isMeasurementCorrectionsSupported();
+    }
+
+    /**
+     * Injects GNSS measurement corrections into the GNSS chipset.
+     *
+     * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS
+     *     measurement corrections to be injected into the GNSS chipset.
+     */
+    public void injectGnssMeasurementCorrections(
+            GnssMeasurementCorrections measurementCorrections) {
+        if (!isCapabilitiesReceived()) {
+            Log.w(TAG, "Failed to inject GNSS measurement corrections. Capabilities "
+                    + "not received yet.");
+            return;
+        }
+        mHandler.post(() -> {
+            if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) {
+                Log.e(TAG, "Failure in injecting GNSS corrections.");
+            }
+        });
+    }
+
+    /** Handle measurement corrections capabilities update from the GNSS HAL implementation. */
+    void onCapabilitiesUpdated(int capabilities) {
+        if (hasCapability(capabilities, CAPABILITY_LOS_SATS) || hasCapability(capabilities,
+                CAPABILITY_EXCESS_PATH_LENGTH)) {
+            mCapabilities = capabilities;
+        } else {
+            Log.e(TAG, "Failed to set capabilities. Received capabilities 0x"
+                    + Integer.toHexString(capabilities) + " does not contain the mandatory "
+                    + "LOS_SATS or the EXCESS_PATH_LENGTH capability.");
+        }
+    }
+
+    /**
+     * Returns the measurement corrections specific capabilities of the GNSS HAL implementation.
+     */
+    public int getCapabilities() {
+        return mCapabilities;
+    }
+
+    /**
+     * Returns the string representation of the GNSS measurement capabilities.
+     */
+    String toStringCapabilities() {
+        final int capabilities = getCapabilities();
+        StringBuilder s = new StringBuilder();
+        s.append("mCapabilities=0x").append(Integer.toHexString(capabilities));
+        s.append(" ( ");
+        if (hasCapability(capabilities, CAPABILITY_LOS_SATS)) {
+            s.append("LOS_SATS ");
+        }
+        if (hasCapability(capabilities, CAPABILITY_EXCESS_PATH_LENGTH)) {
+            s.append("EXCESS_PATH_LENGTH ");
+        }
+        if (hasCapability(capabilities, CAPABILITY_REFLECTING_PLANE)) {
+            s.append("REFLECTING_PLANE ");
+        }
+        s.append(")");
+        return s.toString();
+    }
+
+    private boolean isCapabilitiesReceived() {
+        return mCapabilities != INVALID_CAPABILITIES;
+    }
+
+    private static  boolean hasCapability(int halCapabilities, int capability) {
+        return (halCapabilities & capability) != 0;
+    }
+
+    @VisibleForTesting
+    static class GnssMeasurementCorrectionsProviderNative {
+        public boolean isMeasurementCorrectionsSupported() {
+            return native_is_measurement_corrections_supported();
+        }
+
+        public boolean injectGnssMeasurementCorrections(
+                GnssMeasurementCorrections measurementCorrections) {
+            return native_inject_gnss_measurement_corrections(measurementCorrections);
+        }
+    }
+
+    private static native boolean native_is_measurement_corrections_supported();
+
+    private static native boolean native_inject_gnss_measurement_corrections(
+            GnssMeasurementCorrections measurementCorrections);
+}
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index 1fc7192..844735a 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -11,13 +11,12 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
 package com.android.server.location;
 
 import android.content.Context;
-import android.location.GnssMeasurementCorrections;
 import android.location.GnssMeasurementsEvent;
 import android.location.IGnssMeasurementsListener;
 import android.os.Handler;
@@ -42,7 +41,6 @@
 
     private boolean mIsCollectionStarted;
     private boolean mEnableFullTracking;
-    private int mGnssEngineCapabilities;
 
     protected GnssMeasurementsProvider(Context context, Handler handler) {
         this(context, handler, new GnssMeasurementProviderNative());
@@ -87,21 +85,6 @@
         }
     }
 
-    /**
-     * Injects GNSS measurement corrections into the GNSS chipset.
-     *
-     * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS
-     *     measurement corrections to be injected into the GNSS chipset.
-     */
-    public void injectGnssMeasurementCorrections(
-            GnssMeasurementCorrections measurementCorrections) {
-        mHandler.post(() -> {
-            if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) {
-                Log.e(TAG, "Failure in injecting GNSS corrections.");
-            }
-        });
-    }
-
     @Override
     protected void unregisterFromService() {
         boolean stopped = mNative.stopMeasurementCollection();
@@ -121,20 +104,20 @@
         });
     }
 
-    /** Updates the framework about the capabilities of the GNSS chipset */
-    public void onCapabilitiesUpdated(int capabilities) {
-        mGnssEngineCapabilities = capabilities;
-        boolean isGnssMeasurementsSupported =
-                (capabilities & GnssLocationProvider.GPS_CAPABILITY_MEASUREMENTS) != 0;
+    /** Handle GNSS capabilities update from the GNSS HAL implementation. */
+    public void onCapabilitiesUpdated(int capabilities, boolean hasSubHalCapabilityFlags) {
+        // The IGnssCallback.hal@2.0 removed sub-HAL capability flags from the Capabilities enum
+        // and instead uses the sub-HAL non-null handle returned from IGnss.hal@2.0 to indicate
+        // support. Therefore, the 'hasSubHalCapabilityFlags' parameter is needed to tell if the
+        // 'capabilities' parameter includes the sub-HAL capability flags or not. Old HALs
+        // which explicitly set the sub-HAL capability bits must continue to work.
+        final boolean isGnssMeasurementsSupported = hasSubHalCapabilityFlags
+                ? (capabilities & GnssLocationProvider.GPS_CAPABILITY_MEASUREMENTS) != 0
+                : mNative.isMeasurementSupported();
         setSupported(isGnssMeasurementsSupported);
         updateResult();
     }
 
-    /** Obtains the GNSS engine capabilities. */
-    public int getGnssCapabilities() {
-        return mGnssEngineCapabilities;
-    }
-
     public void onGpsEnabledChanged() {
         tryUpdateRegistrationWithService();
         updateResult();
@@ -195,11 +178,6 @@
         public boolean stopMeasurementCollection() {
             return native_stop_measurement_collection();
         }
-
-        public boolean injectGnssMeasurementCorrections(
-                GnssMeasurementCorrections measurementCorrections) {
-            return native_inject_gnss_measurement_corrections(measurementCorrections);
-        }
     }
 
     private static native boolean native_is_measurement_supported();
@@ -207,7 +185,4 @@
     private static native boolean native_start_measurement_collection(boolean enableFullTracking);
 
     private static native boolean native_stop_measurement_collection();
-
-    private static native boolean native_inject_gnss_measurement_corrections(
-            GnssMeasurementCorrections measurementCorrections);
 }
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 80a3f9b..7e8b599 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -11,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
 package com.android.server.location;
@@ -51,7 +51,6 @@
         mNative = aNative;
     }
 
-    // TODO(b/37460011): Use this with death recovery logic.
     void resumeIfStarted() {
         if (DEBUG) {
             Log.d(TAG, "resumeIfStarted");
@@ -92,7 +91,16 @@
         );
     }
 
-    public void onCapabilitiesUpdated(boolean isGnssNavigationMessageSupported) {
+    /** Handle GNSS capabilities update from the GNSS HAL implementation */
+    public void onCapabilitiesUpdated(int capabilities, boolean hasSubHalCapabilityFlags) {
+        // The IGnssCallback.hal@2.0 removed sub-HAL capability flags from the Capabilities enum
+        // and instead uses the sub-HAL non-null handle returned from IGnss.hal@2.0 to indicate
+        // support. Therefore, the 'hasSubHalCapabilityFlags' parameter is needed to tell if the
+        // 'capabilities' parameter includes the sub-HAL capability flags or not. Old HALs
+        // which explicitly set the sub-HAL capability bits must continue to work.
+        final boolean isGnssNavigationMessageSupported = hasSubHalCapabilityFlags
+                ? (capabilities & GnssLocationProvider.GPS_CAPABILITY_NAV_MESSAGES) != 0
+                : mNative.isNavigationMessageSupported();
         setSupported(isGnssNavigationMessageSupported);
         updateResult();
     }
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/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/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index aced1a2..459de1a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2693,6 +2693,7 @@
                 // seinfo     - seinfo label for the app (assigned at install time)
                 // gids       - supplementary gids this app launches with
                 // profileableFromShellFlag  - 0 or 1 if the package is profileable from shell.
+                // longVersionCode - integer version of the package.
                 //
                 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
                 //
@@ -2720,6 +2721,8 @@
                 }
                 sb.append(" ");
                 sb.append(ai.isProfileableByShell() ? "1" : "0");
+                sb.append(" ");
+                sb.append(String.valueOf(ai.longVersionCode));
                 sb.append("\n");
                 writer.append(sb);
             }
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/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/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/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/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 8c8b05f..72a1a2f 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -269,7 +269,8 @@
      * @return True if we may show an activity while Keyguard is occluded, false otherwise.
      */
     boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
-        return showWhenLocked || dismissKeyguard && !mWindowManager.isKeyguardSecure();
+        return showWhenLocked || dismissKeyguard
+                && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
     }
 
     private void visibilitiesUpdated() {
@@ -317,7 +318,7 @@
         // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
         // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
         // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
-        if (!mWindowManager.isKeyguardSecure()) {
+        if (!mWindowManager.isKeyguardSecure(mService.getCurrentUserId())) {
             return;
         }
 
@@ -345,7 +346,8 @@
      * @return true if Keyguard can be currently dismissed without entering credentials.
      */
     boolean canDismissKeyguard() {
-        return mWindowManager.isKeyguardTrusted() || !mWindowManager.isKeyguardSecure();
+        return mWindowManager.isKeyguardTrusted()
+                || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
     }
 
     private int resolveOccludeTransit() {
@@ -487,7 +489,8 @@
             }
             if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
                     && mDismissingKeyguardActivity != null
-                    && controller.mWindowManager.isKeyguardSecure()) {
+                    && controller.mWindowManager.isKeyguardSecure(
+                            controller.mService.getCurrentUserId())) {
                 mRequestDismissKeyguard = true;
             }
         }
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index e6e6275..2411e00 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -762,7 +762,7 @@
             } else {
                 // If keyguard is not secure and it is locked, dismiss the keyguard before
                 // disabling it, which avoids the platform to think the keyguard is still on.
-                if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure()) {
+                if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure(userId)) {
                     mPendingDisableFromDismiss = userId;
                     mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() {
                         @Override
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/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a6c9257..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
@@ -2868,8 +2870,13 @@
     }
 
     @Override
-    public boolean isKeyguardSecure() {
-        int userId = UserHandle.getCallingUserId();
+    public boolean isKeyguardSecure(int userId) {
+        if (userId != UserHandle.getCallingUserId()
+                && !checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS,
+                "isKeyguardSecure")) {
+            throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
+        }
+
         long origId = Binder.clearCallingIdentity();
         try {
             return mPolicy.isKeyguardSecure(userId);
@@ -3812,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/Android.bp b/services/core/jni/Android.bp
index 050a079..00b815a 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -109,6 +109,7 @@
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
+        "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.input.classifier@1.0",
         "android.hardware.ir@1.0",
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index caba3af..a6e9fdd 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -71,6 +71,7 @@
 static jmethodID method_reportNavigationMessages;
 static jmethodID method_reportLocationBatch;
 static jmethodID method_reportGnssServiceDied;
+static jmethodID method_setMeasurementCorrectionsCapabilities;
 static jmethodID method_correctionsGetLatitudeDegrees;
 static jmethodID method_correctionsGetLongitudeDegrees;
 static jmethodID method_correctionsGetAltitudeMeters;
@@ -118,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;
@@ -142,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;
@@ -158,10 +161,9 @@
 using IAGnssCallback_V1_0 = android::hardware::gnss::V1_0::IAGnssCallback;
 using IAGnssCallback_V2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
 
-using IMeasurementCorrections =
-    android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
-using GnssSingleSatCorrectionFlags =
-    android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags;
+using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags;
 
 using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
 using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback;
@@ -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;
@@ -201,7 +204,6 @@
 sp<IGnssMeasurement_V2_0> gnssMeasurementIface_V2_0 = nullptr;
 sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
 sp<IMeasurementCorrections> gnssCorrectionsIface = nullptr;
-
 sp<IGnssVisibilityControl> gnssVisibilityControlIface = nullptr;
 
 #define WAKE_LOCK_NAME  "GPS"
@@ -549,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;
@@ -567,14 +571,47 @@
             override;
     Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
     Return<void> gnssLocationCb_2_0(const GnssLocation_V2_0& location) override;
+    Return<void> gnssSvStatusCb_2_0(const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList) override {
+        return gnssSvStatusCbImpl(svInfoList);
+    }
 
-    // Templated implementation for gnnsLocationCb and gnnsLocationCb_2_0.
-    template <class T>
-    Return<void> gnssLocationCbImpl(const T& location);
+    Return<void> gnssSetCapabilitesCbImpl(uint32_t capabilities, bool hasSubHalCapabilityFlags);
 
-    // TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics
+    // 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) {
@@ -622,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,
@@ -654,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;
@@ -694,16 +732,29 @@
 }
 
 Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
-    ALOGD("%s: %du\n", __func__, capabilities);
-
-    JNIEnv* env = getJniEnv();
-    env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return Void();
+    return GnssCallback::gnssSetCapabilitesCbImpl(capabilities,
+        /* hasSubHalCapabilityFlags = */ true);
 }
 
 Return<void> GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
-    return GnssCallback::gnssSetCapabilitesCb(capabilities);
+    return GnssCallback::gnssSetCapabilitesCbImpl(capabilities,
+        /* hasSubHalCapabilityFlags = */ false);
+}
+
+Return <void> GnssCallback::gnssSetCapabilitesCbImpl(uint32_t capabilities,
+        bool hasSubHalCapabilityFlags) {
+    // The IGnssCallback.hal@2.0 removed sub-HAL capability flags from the Capabilities enum
+    // and instead uses the sub-HAL non-null handle returned from IGnss.hal@2.0 to indicate
+    // support. Therefore, the 'hasSubHalCapabilityFlags' parameter is needed to tell if the
+    // 'capabilities' parameter includes the sub-HAL capability flags or not. Old HALs
+    // which explicitly set the sub-HAL capability bits must continue to work.
+    ALOGD("%s: capabilities=%du, hasSubHalCapabilityFlags=%d\n", __func__, capabilities,
+        hasSubHalCapabilityFlags);
+    JNIEnv* env = getJniEnv();
+    env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities,
+            boolToJbool(hasSubHalCapabilityFlags));
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
 }
 
 Return<void> GnssCallback::gnssAcquireWakelockCb() {
@@ -1065,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(
@@ -1153,6 +1207,22 @@
 }
 
 /*
+ * MeasurementCorrectionsCallback implements callback methods of interface
+ * IMeasurementCorrectionsCallback.hal.
+ */
+struct MeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback {
+    Return<void> setCapabilitiesCb(uint32_t capabilities) override;
+};
+
+Return<void> MeasurementCorrectionsCallback::setCapabilitiesCb(uint32_t capabilities) {
+    ALOGD("%s: %du\n", __func__, capabilities);
+    JNIEnv* env = getJniEnv();
+    env->CallVoidMethod(mCallbacksObj, method_setMeasurementCorrectionsCapabilities, capabilities);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+/*
  * GnssNiCallback implements callback methods required by the IGnssNi interface.
  */
 struct GnssNiCallback : public IGnssNiCallback {
@@ -1434,7 +1504,7 @@
     method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "(I[I[F[F[F[F)V");
     method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
     method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
-    method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
+    method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(IZ)V");
     method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
     method_setGnssHardwareModelName = env->GetMethodID(clazz, "setGnssHardwareModelName",
             "(Ljava/lang/String;)V");
@@ -1474,6 +1544,9 @@
             "(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V");
     method_isInEmergencySession = env->GetMethodID(clazz, "isInEmergencySession", "()Z");
 
+    method_setMeasurementCorrectionsCapabilities = env->GetMethodID(clazz,
+            "setMeasurementCorrectionsCapabilities", "(I)V");
+
     jclass measCorrClass = env->FindClass("android/location/GnssMeasurementCorrections");
     method_correctionsGetLatitudeDegrees = env->GetMethodID(
             measCorrClass,"getLatitudeDegrees", "()D");
@@ -1591,7 +1664,7 @@
     }
 
     if (gnssHal_V2_0 != nullptr) {
-        // TODO(b/119638366): getExtensionGnssMeasurement_1_1 from gnssHal_V2_0
+        // TODO: getExtensionGnssMeasurement_1_1 from gnssHal_V2_0
         auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0();
         if (!gnssMeasurement.isOk()) {
             ALOGD("Unable to get a handle to GnssMeasurement_V2_0");
@@ -1623,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();
@@ -1795,6 +1878,12 @@
         gnssVisibilityControlIface->setCallback(gnssVisibilityControlCbIface);
     }
 
+    if (gnssCorrectionsIface != nullptr) {
+        sp<IMeasurementCorrectionsCallback> gnssCorrectionsIfaceCbIface =
+                new MeasurementCorrectionsCallback();
+        gnssCorrectionsIface->setCallback(gnssCorrectionsIfaceCbIface);
+    }
+
     return JNI_TRUE;
 }
 
@@ -2150,76 +2239,100 @@
     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;
     /*
-     * TODO(b/33089503) : Create a jobject to represent GnssDebug.
+     * TODO: Create a jobject to represent GnssDebug.
      */
 
     std::stringstream internalState;
 
     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;
 }
 
@@ -2380,13 +2493,25 @@
     return boolToJbool(result.isOk());
 }
 
-static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measurement_corrections(
+static jboolean
+    android_location_GnssMeasurementCorrectionsProvider_is_measurement_corrections_supported(
+    JNIEnv* env, jclass clazz) {
+    if (gnssCorrectionsIface != nullptr) {
+        return JNI_TRUE;
+    }
+
+    return JNI_FALSE;
+}
+
+static jboolean
+    android_location_GnssMeasurementCorrectionsProvider_inject_gnss_measurement_corrections(
         JNIEnv* env,
         jobject obj /* clazz*/,
         jobject correctionsObj) {
 
     if (gnssCorrectionsIface == nullptr) {
-        ALOGW("Trying to inject GNSS corrections on a chipset that does not support them.");
+        ALOGW("Trying to inject GNSS measurement corrections on a chipset that does not"
+            " support them.");
         return JNI_FALSE;
     }
 
@@ -2882,18 +3007,25 @@
 static const JNINativeMethod sMeasurementMethods[] = {
     /* name, signature, funcPtr */
     {"native_is_measurement_supported", "()Z",
-     reinterpret_cast<void*>(
-         android_location_GnssMeasurementsProvider_is_measurement_supported)},
+            reinterpret_cast<void*>(
+            android_location_GnssMeasurementsProvider_is_measurement_supported)},
     {"native_start_measurement_collection", "(Z)Z",
-     reinterpret_cast<void*>(
-         android_location_GnssMeasurementsProvider_start_measurement_collection)},
+            reinterpret_cast<void*>(
+            android_location_GnssMeasurementsProvider_start_measurement_collection)},
     {"native_stop_measurement_collection", "()Z",
-     reinterpret_cast<void*>(
-         android_location_GnssMeasurementsProvider_stop_measurement_collection)},
+            reinterpret_cast<void*>(
+            android_location_GnssMeasurementsProvider_stop_measurement_collection)},
+};
+
+static const JNINativeMethod sMeasurementCorrectionsMethods[] = {
+    /* name, signature, funcPtr */
+    {"native_is_measurement_corrections_supported", "()Z",
+            reinterpret_cast<void*>(
+            android_location_GnssMeasurementCorrectionsProvider_is_measurement_corrections_supported)},
     {"native_inject_gnss_measurement_corrections",
-     "(Landroid/location/GnssMeasurementCorrections;)Z",
-     reinterpret_cast<void*>(
-         android_location_GnssMeasurementsProvider_inject_gnss_measurement_corrections)},
+            "(Landroid/location/GnssMeasurementCorrections;)Z",
+            reinterpret_cast<void*>(
+            android_location_GnssMeasurementCorrectionsProvider_inject_gnss_measurement_corrections)},
 };
 
 static const JNINativeMethod sNavigationMessageMethods[] = {
@@ -2992,6 +3124,11 @@
             NELEM(sMeasurementMethods));
     jniRegisterNativeMethods(
             env,
+            "com/android/server/location/GnssMeasurementCorrectionsProvider",
+            sMeasurementCorrectionsMethods,
+            NELEM(sMeasurementCorrectionsMethods));
+    jniRegisterNativeMethods(
+            env,
             "com/android/server/location/GnssNavigationMessageProvider",
             sNavigationMessageMethods,
             NELEM(sNavigationMessageMethods));
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/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 6386b3b3..7c91b64 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -15,7 +15,10 @@
  */
 package com.android.server;
 
+import static android.app.AlarmManager.ELAPSED_REALTIME;
 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
+import static android.app.AlarmManager.RTC;
+import static android.app.AlarmManager.RTC_WAKEUP;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
@@ -254,14 +257,22 @@
     }
 
     private void setTestAlarm(int type, long triggerTime, PendingIntent operation) {
+        setTestAlarm(type, triggerTime, operation, TEST_CALLING_UID);
+    }
+
+    private void setTestAlarm(int type, long triggerTime, PendingIntent operation, int callingUid) {
         mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, 0,
                 operation, null, "test", AlarmManager.FLAG_STANDALONE, null, null,
-                TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+                callingUid, TEST_CALLING_PACKAGE);
     }
 
     private PendingIntent getNewMockPendingIntent() {
+        return getNewMockPendingIntent(TEST_CALLING_UID);
+    }
+
+    private PendingIntent getNewMockPendingIntent(int mockUid) {
         final PendingIntent mockPi = mock(PendingIntent.class, Answers.RETURNS_DEEP_STUBS);
-        when(mockPi.getCreatorUid()).thenReturn(TEST_CALLING_UID);
+        when(mockPi.getCreatorUid()).thenReturn(mockUid);
         when(mockPi.getCreatorPackage()).thenReturn(TEST_CALLING_PACKAGE);
         return mockPi;
     }
@@ -724,6 +735,91 @@
         verify(mMockContext).sendBroadcastAsUser(mService.mTimeTickIntent, UserHandle.ALL);
     }
 
+    @Test
+    public void alarmCountKeyedOnCallingUid() {
+        final int mockCreatorUid = 431412;
+        final PendingIntent pi = getNewMockPendingIntent(mockCreatorUid);
+        setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 5, pi);
+        assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
+        assertEquals(-1, mService.mAlarmsPerUid.get(mockCreatorUid, -1));
+    }
+
+    @Test
+    public void alarmCountOnSet() {
+        final int numAlarms = 103;
+        final int[] types = {RTC_WAKEUP, RTC, ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME};
+        for (int i = 1; i <= numAlarms; i++) {
+            setTestAlarm(types[i % 4], mNowElapsedTest + i, getNewMockPendingIntent());
+            assertEquals(i, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
+        }
+    }
+
+    @Test
+    public void alarmCountOnExpiration() throws InterruptedException {
+        final int numAlarms = 8; // This test is slow
+        for (int i = 0; i < numAlarms; i++) {
+            setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent());
+        }
+        int expired = 0;
+        while (expired < numAlarms) {
+            mNowElapsedTest = mTestTimer.getElapsed();
+            mTestTimer.expire();
+            expired++;
+            assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
+        }
+    }
+
+    @Test
+    public void alarmCountOnUidRemoved() {
+        final int numAlarms = 10;
+        for (int i = 0; i < numAlarms; i++) {
+            setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent());
+        }
+        assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
+        mService.removeLocked(TEST_CALLING_UID);
+        assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
+    }
+
+    @Test
+    public void alarmCountOnPackageRemoved() {
+        final int numAlarms = 10;
+        for (int i = 0; i < numAlarms; i++) {
+            setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent());
+        }
+        assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
+        mService.removeLocked(TEST_CALLING_PACKAGE);
+        assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
+    }
+
+    @Test
+    public void alarmCountOnUserRemoved() {
+        final int mockUserId = 15;
+        final int numAlarms = 10;
+        for (int i = 0; i < numAlarms; i++) {
+            int mockUid = UserHandle.getUid(mockUserId, 1234 + i);
+            setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10,
+                    getNewMockPendingIntent(mockUid), mockUid);
+        }
+        assertEquals(numAlarms, mService.mAlarmsPerUid.size());
+        mService.removeUserLocked(mockUserId);
+        assertEquals(0, mService.mAlarmsPerUid.size());
+    }
+
+    @Test
+    public void alarmCountOnAlarmRemoved() {
+        final int numAlarms = 10;
+        final PendingIntent[] pis = new PendingIntent[numAlarms];
+        for (int i = 0; i < numAlarms; i++) {
+            pis[i] = getNewMockPendingIntent();
+            setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]);
+        }
+        assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
+        for (int i = 0; i < numAlarms; i++) {
+            mService.removeLocked(pis[i], null);
+            assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
+        }
+    }
+
     @After
     public void tearDown() {
         if (mMockingSession != null) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 8e78a56..c45122e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -52,6 +52,7 @@
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkPolicyManager;
 import android.os.Build;
+import android.os.Looper;
 import android.os.SystemClock;
 import android.util.DataUnit;
 
@@ -102,6 +103,8 @@
         LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
         LocalServices.addService(NetworkPolicyManagerInternal.class, mNetPolicyManagerInternal);
 
+        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
+
         // Freeze the clocks at this moment in time
         JobSchedulerService.sSystemClock =
                 Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
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/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/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
index 1e02a12..329af95 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
@@ -38,9 +38,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 
 import android.app.AppOpsManager;
-import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
-import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.os.Handler;
@@ -50,7 +48,6 @@
 import android.util.Log;
 import android.view.IWindowManager;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
 
 import com.android.server.am.AssistDataRequester;
@@ -88,12 +85,10 @@
     private static final int TEST_UID = 0;
     private static final String TEST_PACKAGE = "";
 
-    private Context mContext;
     private AssistDataRequester mDataRequester;
     private Callbacks mCallbacks;
     private Object mCallbacksLock;
     private Handler mHandler;
-    private IActivityManager mAm;
     private IActivityTaskManager mAtm;
     private IWindowManager mWm;
     private AppOpsManager mAppOpsManager;
@@ -109,7 +104,6 @@
 
     @Before
     public void setUp() throws Exception {
-        mAm = mock(IActivityManager.class);
         mAtm = mock(IActivityTaskManager.class);
         mWm = mock(IWindowManager.class);
         mAppOpsManager = mock(AppOpsManager.class);
@@ -118,7 +112,7 @@
         mCallbacks = new Callbacks();
         mDataRequester = new AssistDataRequester(mContext, mWm, mAppOpsManager, mCallbacks,
                 mCallbacksLock, OP_ASSIST_STRUCTURE, OP_ASSIST_SCREENSHOT);
-
+        mDataRequester.mActivityTaskManager = mAtm;
         // Gate the continuation of the assist data callbacks until we are ready within the tests
         mGate = new CountDownLatch(1);
         doAnswer(invocation -> {
@@ -155,7 +149,6 @@
                 .checkOpNoThrow(eq(OP_ASSIST_SCREENSHOT), anyInt(), anyString());
     }
 
-    @FlakyTest(bugId = 124088319)
     @Test
     public void testRequestData() throws Exception {
         setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -176,7 +169,6 @@
         assertReceivedDataCount(0, 0, 0, 0);
     }
 
-    @FlakyTest(bugId = 124088319)
     @Test
     public void testCurrentAppDisallow_expectNullCallbacks() throws Exception {
         setupMocks(!CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -187,7 +179,6 @@
         assertReceivedDataCount(0, 1, 0, 1);
     }
 
-    @FlakyTest(bugId = 124088319)
     @Test
     public void testProcessPendingData() throws Exception {
         setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -245,7 +236,6 @@
         assertReceivedDataCount(0, 1, 0, 1);
     }
 
-    @FlakyTest(bugId = 124088319)
     @Test
     public void testDisallowAssistContextExtras_expectNullDataCallbacks() throws Exception {
         setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -259,7 +249,6 @@
         assertReceivedDataCount(0, 1, 0, 1);
     }
 
-    @FlakyTest(bugId = 124088319)
     @Test
     public void testNoFetchScreenshots_expectNoScreenshotCallbacks() throws Exception {
         setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -270,7 +259,6 @@
         assertReceivedDataCount(5, 5, 0, 0);
     }
 
-    @FlakyTest(bugId = 124088319)
     @Test
     public void testDisallowAssistScreenshot_expectNullScreenshotCallback() throws Exception {
         setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
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/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 17e2e90..30dcaa0 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -53,6 +53,9 @@
  *   <li>Operator name, short name and numeric id
  *   <li>Network selection mode
  * </ul>
+ *
+ * For historical reasons this class is not declared as final; however,
+ * it should be treated as though it were final.
  */
 public class ServiceState implements Parcelable {
 
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 245f5b3..ac11940 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -161,11 +161,6 @@
     private String mGroupUUID;
 
     /**
-     *  A property in opportunistic subscription to indicate whether it is metered or not.
-     */
-    private boolean mIsMetered;
-
-    /**
      * Whether group of the subscription is disabled.
      * This is only useful if it's a grouped opportunistic subscription. In this case, if all
      * primary (non-opportunistic) subscriptions in the group are deactivated (unplugged pSIM
@@ -197,7 +192,7 @@
             @Nullable UiccAccessRule[] accessRules, String cardString) {
         this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
                 roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString,
-                false, null, true, TelephonyManager.UNKNOWN_CARRIER_ID,
+                false, null, TelephonyManager.UNKNOWN_CARRIER_ID,
                 SubscriptionManager.PROFILE_CLASS_DEFAULT);
     }
 
@@ -208,10 +203,10 @@
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
             Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
             @Nullable UiccAccessRule[] accessRules, String cardString, boolean isOpportunistic,
-            @Nullable String groupUUID, boolean isMetered, int carrierId, int profileClass) {
+            @Nullable String groupUUID, int carrierId, int profileClass) {
         this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
                 roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString, -1,
-                isOpportunistic, groupUUID, isMetered, false, carrierId, profileClass,
+                isOpportunistic, groupUUID, false, carrierId, profileClass,
                 SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
     }
 
@@ -222,7 +217,7 @@
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
             Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
             @Nullable UiccAccessRule[] accessRules, String cardString, int cardId,
-            boolean isOpportunistic, @Nullable String groupUUID, boolean isMetered,
+            boolean isOpportunistic, @Nullable String groupUUID,
             boolean isGroupDisabled, int carrierId, int profileClass, int subType) {
         this.mId = id;
         this.mIccId = iccId;
@@ -243,7 +238,6 @@
         this.mCardId = cardId;
         this.mIsOpportunistic = isOpportunistic;
         this.mGroupUUID = groupUUID;
-        this.mIsMetered = isMetered;
         this.mIsGroupDisabled = isGroupDisabled;
         this.mCarrierId = carrierId;
         this.mProfileClass = profileClass;
@@ -472,18 +466,6 @@
     }
 
     /**
-     * Used in opportunistic subscription ({@link #isOpportunistic()}) to indicate whether it's
-     * metered or not.This is one of the factors when deciding to switch to the subscription.
-     * (a non-metered subscription, for example, would likely be preferred over a metered one).
-     *
-     * @return whether subscription is metered.
-     * @hide
-     */
-    public boolean isMetered() {
-        return mIsMetered;
-    }
-
-    /**
      * @return the profile class of this subscription.
      * @hide
      */
@@ -624,7 +606,6 @@
             int cardId = source.readInt();
             boolean isOpportunistic = source.readBoolean();
             String groupUUID = source.readString();
-            boolean isMetered = source.readBoolean();
             boolean isGroupDisabled = source.readBoolean();
             int carrierid = source.readInt();
             int profileClass = source.readInt();
@@ -633,7 +614,7 @@
             return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
                     nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
                     isEmbedded, accessRules, cardString, cardId, isOpportunistic, groupUUID,
-                    isMetered, isGroupDisabled, carrierid, profileClass, subType);
+                    isGroupDisabled, carrierid, profileClass, subType);
         }
 
         @Override
@@ -663,7 +644,6 @@
         dest.writeInt(mCardId);
         dest.writeBoolean(mIsOpportunistic);
         dest.writeString(mGroupUUID);
-        dest.writeBoolean(mIsMetered);
         dest.writeBoolean(mIsGroupDisabled);
         dest.writeInt(mCarrierId);
         dest.writeInt(mProfileClass);
@@ -703,7 +683,7 @@
                 + " accessRules " + Arrays.toString(mAccessRules)
                 + " cardString=" + cardStringToPrint + " cardId=" + mCardId
                 + " isOpportunistic " + mIsOpportunistic + " mGroupUUID=" + mGroupUUID
-                + " isMetered=" + mIsMetered + " mIsGroupDisabled=" + mIsGroupDisabled
+                + " mIsGroupDisabled=" + mIsGroupDisabled
                 + " profileClass=" + mProfileClass
                 + " subscriptionType=" + mSubscriptionType + "}";
     }
@@ -711,7 +691,7 @@
     @Override
     public int hashCode() {
         return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
-                mIsOpportunistic, mGroupUUID, mIsMetered, mIccId, mNumber, mMcc, mMnc,
+                mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc,
                 mCountryIso, mCardString, mCardId, mDisplayName, mCarrierName, mAccessRules,
                 mIsGroupDisabled, mCarrierId, mProfileClass);
     }
@@ -737,7 +717,6 @@
                 && mIsOpportunistic == toCompare.mIsOpportunistic
                 && mIsGroupDisabled == toCompare.mIsGroupDisabled
                 && mCarrierId == toCompare.mCarrierId
-                && mIsMetered == toCompare.mIsMetered
                 && Objects.equals(mGroupUUID, toCompare.mGroupUUID)
                 && Objects.equals(mIccId, toCompare.mIccId)
                 && Objects.equals(mNumber, toCompare.mNumber)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 3707aa4..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}
@@ -2853,29 +2855,6 @@
     }
 
     /**
-     * Set if a subscription is metered or not. Similar to Wi-Fi, metered means
-     * user may be charged more if more data is used.
-     *
-     * By default all Cellular networks are considered metered. System or carrier privileged apps
-     * can set a subscription un-metered which will be considered when system switches data between
-     * primary subscription and opportunistic subscription.
-     *
-     * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier
-     * privilege permission of the subscription.
-     *
-     * @param isMetered whether it’s a metered subscription.
-     * @param subId the unique SubscriptionInfo index in database
-     * @return {@code true} if the operation is succeed, {@code false} otherwise.
-     */
-    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
-    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public boolean setMetered(boolean isMetered, int subId) {
-        if (VDBG) logd("[setIsMetered]+ isMetered:" + isMetered + " subId:" + subId);
-        return setSubscriptionPropertyHelper(subId, "setIsMetered",
-                (iSub)-> iSub.setMetered(isMetered, subId, mContext.getOpPackageName())) == 1;
-    }
-
-    /**
      * Whether a subscription is visible to API caller. If it's a bundled opportunistic
      * subscription, it should be hidden anywhere in Settings, dialer, status bar etc.
      * Exception is if caller owns carrier privilege, in which case they will
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c91f16b..282b1ff 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4779,18 +4779,22 @@
      * Registers a listener object to receive notification of changes
      * in specified telephony states.
      * <p>
-     * To register a listener, pass a {@link PhoneStateListener}
-     * and specify at least one telephony state of interest in
-     * the events argument.
+     * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony
+     * state of interest in the events argument.
      *
-     * At registration, and when a specified telephony state
-     * changes, the telephony manager invokes the appropriate
-     * callback method on the listener object and passes the
-     * current (updated) values.
+     * At registration, and when a specified telephony state changes, the telephony manager invokes
+     * the appropriate callback method on the listener object and passes the current (updated)
+     * values.
      * <p>
-     * To unregister a listener, pass the listener object and set the
-     * events argument to
+     * To un-register a listener, pass the listener object and set the events argument to
      * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
+     *
+     * If this TelephonyManager object has been created with {@link #createForSubscriptionId},
+     * applies to the given subId. Otherwise, applies to
+     * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds,
+     * pass a separate listener object to each TelephonyManager object created with
+     * {@link #createForSubscriptionId}.
+     *
      * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
      * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
      * {@link SecurityException} will be thrown otherwise.
@@ -4805,17 +4809,18 @@
         if (mContext == null) return;
         try {
             boolean notifyNow = (getITelephony() != null);
-            // If the listener has not explicitly set the subId (for example, created with the
-            // default constructor), replace the subId so it will listen to the account the
-            // telephony manager is created with.
-            if (listener.mSubId == null) {
-                listener.mSubId = mSubId;
-            }
-
             ITelephonyRegistry registry = getTelephonyRegistry();
             if (registry != null) {
-                registry.listenForSubscriber(listener.mSubId, getOpPackageName(),
+                // listen to the subId the telephony manager is created with. Ignore subId in
+                // PhoneStateListener.
+                registry.listenForSubscriber(mSubId, getOpPackageName(),
                         listener.callback, events, notifyNow);
+                // TODO: remove this once we remove PhoneStateListener constructor with subId.
+                if (events == PhoneStateListener.LISTEN_NONE) {
+                    listener.mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+                } else {
+                    listener.mSubId = mSubId;
+                }
             } else {
                 Rlog.w(TAG, "telephony registry not ready.");
             }
@@ -10368,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 {}
 
     /**
@@ -10382,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)
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 79e0aa1..3bbf7a4 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -205,15 +205,6 @@
     String setSubscriptionGroup(in int[] subIdList, String callingPackage);
 
     /**
-     * Set whether a subscription is metered
-     *
-     * @param isMetered whether it’s a metered subscription.
-     * @param subId the unique SubscriptionInfo index in database
-     * @return the number of records updated
-     */
-    int setMetered(boolean isMetered, int subId, String callingPackage);
-
-    /**
      * Set which subscription is preferred for cellular data. It's
      * designed to overwrite default data subscription temporarily.
      *
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 9d78bf4..4886a3f 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -317,7 +317,8 @@
                 Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_PRIV_CHECK_RELAXED, 0) == 1;
         ApplicationInfo callingPackageInfo = null;
         try {
-            callingPackageInfo = context.getPackageManager().getApplicationInfo(callingPackage, 0);
+            callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser(
+                    callingPackage, 0, UserHandle.getUserId(uid));
             if (callingPackageInfo.isSystemApp()) {
                 isPreinstalled = true;
                 if (callingPackageInfo.isPrivilegedApp()) {
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index b31235b..41cb74a 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -4,7 +4,7 @@
  -->
 <configuration description="Runs WindowManager Flicker Tests">
     <option name="test-tag" value="FlickerTests" />
-    <target_preparer class="com.google.android.tradefed.targetprep.GoogleDeviceSetup">
+    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on" />
         <!-- prevents the phone from restarting -->
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..52919df 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;
@@ -46,8 +45,6 @@
 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 +84,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 +173,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 +231,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 +288,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 +341,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 +401,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 +473,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 +510,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);
@@ -540,7 +538,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.installSplit(false,
@@ -598,7 +596,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 +691,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 +768,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.
@@ -760,7 +827,7 @@
             RollbackTestUtils.adoptShellPermissionIdentity(
                     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 +857,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/apf/ApfCapabilitiesTest.java b/tests/net/java/android/net/apf/ApfCapabilitiesTest.java
new file mode 100644
index 0000000..75752c3
--- /dev/null
+++ b/tests/net/java/android/net/apf/ApfCapabilitiesTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.apf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.net.shared.ParcelableTestUtil;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.TestUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ApfCapabilitiesTest {
+    @Test
+    public void testParcelUnparcel() {
+        final ApfCapabilities caps = new ApfCapabilities(123, 456, 789);
+        ParcelableTestUtil.assertFieldCountEquals(3, ApfCapabilities.class);
+
+        TestUtils.assertParcelingIsLossless(caps, ApfCapabilities.CREATOR);
+    }
+
+    @Test
+    public void testEquals() {
+        assertEquals(new ApfCapabilities(1, 2, 3), new ApfCapabilities(1, 2, 3));
+        assertNotEquals(new ApfCapabilities(2, 2, 3), new ApfCapabilities(1, 2, 3));
+        assertNotEquals(new ApfCapabilities(1, 3, 3), new ApfCapabilities(1, 2, 3));
+        assertNotEquals(new ApfCapabilities(1, 2, 4), new ApfCapabilities(1, 2, 3));
+    }
+}
diff --git a/tools/aapt2/cmd/Dump.h b/tools/aapt2/cmd/Dump.h
index 5cf056e..7ded9bc 100644
--- a/tools/aapt2/cmd/Dump.h
+++ b/tools/aapt2/cmd/Dump.h
@@ -32,6 +32,7 @@
  public:
   explicit DumpApkCommand(const std::string&& name, text::Printer* printer, IDiagnostics* diag)
       : Command(name), printer_(printer), diag_(diag) {
+        SetDescription("Dump information about an APK or APC.");
   }
 
   text::Printer* GetPrinter() {
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/InspectablePropertyProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java
index 2042a68..7f5f9ca 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
@@ -635,14 +635,14 @@
             final String name = mAnnotationUtils.typedValueByName(
                     "name", String.class, accessor, enumAnnotation)
                     .orElseThrow(() -> new ProcessingException(
-                            "Name is required for @EnumMap",
+                            "Name is required for @EnumEntry",
                             accessor,
                             enumAnnotation));
 
             final int value = mAnnotationUtils.typedValueByName(
                     "value", Integer.class, accessor, enumAnnotation)
                     .orElseThrow(() -> new ProcessingException(
-                            "Value is required for @EnumMap",
+                            "Value is required for @EnumEntry",
                             accessor,
                             enumAnnotation));
 
@@ -684,14 +684,14 @@
             final String name = mAnnotationUtils.typedValueByName(
                     "name", String.class, accessor, flagAnnotation)
                     .orElseThrow(() -> new ProcessingException(
-                            "Name is required for @FlagMap",
+                            "Name is required for @FlagEntry",
                             accessor,
                             flagAnnotation));
 
             final int target = mAnnotationUtils.typedValueByName(
                     "target", Integer.class, accessor, flagAnnotation)
                     .orElseThrow(() -> new ProcessingException(
-                            "Target is required for @FlagMap",
+                            "Target is required for @FlagEntry",
                             accessor,
                             flagAnnotation));